(*
/*

// wrapper for {OpenGL} control in Delphi
//------------------------------------------------------------------------------
// (C) by Vladimir Kladov, 2017

CLASS {AL4_OpenGL|_Delphi_KOL}, NATIVE, UNTESTED :
      IMPORT: {OpenGL} ;

NATIVE: "uses AL4_OpenGL, Windows, Messages;" .
*/
*)
unit AL4_OpenGL;
{$I EXTERNAL_DEFINES.inc}
{$I KOLDEF.inc}

interface

uses {$IFDEF KOL} KOL 
     {$ELSE} Classes, Forms, Controls, StdCtrls, ExtCtrls, ComCtrls, Dialogs
     {$ENDIF},
// use AL4 to access system functions (AL4.pas inserted by the compiler into
// a project folder)
     AL4,
// use All_classes from a project folder (generated for a certain project)
     All_classes,
     AL4_form, unitC_Control {to access NoneObj_C_Control},
     Windows, Messages, OpenGL;

//{$WARN UNIT_DEPRECATED OFF}
//{$WARN SYMBOL_PLATFORM OFF}
//{$WARN UNSAFE_TYPE OFF}
//{$WARN UNSAFE_CAST OFF}
//{$WARN UNSAFE_CODE OFF}

type
	{$IFnDEF _D7orHigher}
	PInteger = ^Integer;
	{$ENDIF}

    POpenGLBox = ^TOpenGLBox;
    TOpenGLbox = object(TObj)
    public
        AL4Form: PAL4Form;
        DC: HDC;
        RC: HGLRC;
        Box: PControl;
        procedure BoxPaint(Sender: PControl; aDC: HDC);
        procedure BoxErase(Sender: PControl; aDC: HDC);
        constructor Create;
        procedure Initialize_OpenGL;
    end;
    
function Do_Create_opengl_control(P: Integer; X_GL: Pointer): Integer;  
procedure Do_GenTextures(N: Integer; Textures: DynAInt);  
procedure Do_DeleteTextures(N: Integer; Textures: DynAInt);
function Do_IsTexture(Texture: Integer): Boolean;

var All_textures: PList;
var glBindTexture: procedure(Target: Integer; Texture: Integer); stdcall;
var glTexSubImage1D: procedure( target: Integer; 
                                level: Integer; 
                                xoffset: Integer; 
                                width: Integer; 
                                format: Integer; 
                                _type: Integer; 
                                const pixels: Pointer); stdcall;
var glTexSubImage2D: procedure( target: Integer;
                                level: Integer;
                                xoffset: Integer;
                                yoffset: Integer;
                                width: Integer;
                                height: Integer;
                                format: Integer;
                                _type: Integer;
                                const pixels: Pointer); stdcall;
var glPolygonOffset: procedure( Factor: Single; Units: Single ); stdcall;
var glPushClientAttrib: procedure( Mask: Integer ); stdcall;
var glPopClientAttrib: procedure; stdcall;


function GLProcAddress(const ProcName: String): Pointer;
var GLLib: THandle;

procedure Turn_VSync_off;

function  gluBuild2DMipmaps (target: GLenum; components, width, height: GLint;
//																height
// was forgotten in Delphi5 OpenGL.pas
                             format, atype: GLenum; data: Pointer): Integer;
                             stdcall; external glu32;


implementation


//-------------------------------------------------------- O P E N   G L   B O X

(*
/*
// Create Open GL control, return descriptor.
//-------------------------------------------
FUN Create_opengl_control({OpenGL} GL|_control) ==> INT, NATIVE :
        ---------------------------------------- 'redirect to GL control create'
        INT f|orm_handle = GL_control.Form_.Handle
        NATIVE "    RESULT := Do_Create_opengl_control(X_f, X_GL);" .
*/
*)
function Do_Create_opengl_control(P: Integer; X_GL: Pointer): Integer;
var Parent: PAL4Column;
    G: POpenGLbox;
    F: PAL4Form;
begin
    F := PAL4Form(P);
    Parent := PAL4Column(F.Get_current_column_handle);
    new( G, Create );
    
    //G.Box := NewPaintBox(Parent.Panel);
    G.Box := NewPanel(Parent.Panel, esNONE);
    //G.Box.HasBorder := FALSE;
    G.AL4Form := Parent.AL4Form;
    G.Box.Tag := Integer(X_GL);
    G.Tag := Integer(X_GL);
    PObj(X_GL).Tag := DWORD(G);
    
    G.Box.Width := Points(200);
    G.Box.Height := Points(200);
    
    //G.Parent := Parent;
    //G.TabStop := TRUE;
    G.Box.LookTabKeys := [tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn];
    G.Box.TabStop := TRUE;
    
    Adjust_control_location_1(Parent, G.Box);
    
    G.Initialize_OpenGL;
    
    Set_control_events(Parent, G.Box);
    Set_Win_control_events(Parent, G.Box);
    G.Box.OnPaint := G.BoxPaint;
    G.Box.OnEraseBkgnd := G.BoxErase;
    Result := Integer(G.Box);
end;

procedure Do_GenTextures(N: Integer; Textures: DynAInt);  
var i, j: Integer;
begin
    if All_textures = nil then 
    begin 
        All_textures := NewList;
        All_textures.Add(Pointer(-1));
    end;
    for i := 0 to N-1 do
    begin
        j := All_textures.IndexOf(nil);
        if j < 0 then
        begin
            j := All_textures.Count;
            All_textures.Add(nil);
        end;
        All_textures.Items[j] := Pointer(1);
        Textures.Add(MAXINT, j);
    end;
end;

procedure Do_DeleteTextures(N: Integer; Textures: DynAInt); 
var i, j: Integer;
begin
    if All_textures = nil then Exit;
    for i := 0 to N-1 do
    begin 
        if i >= Textures.Count then Exit;
        j := Textures.GetIntegers(i);
        if (j >= 1) and (j < All_textures.Count) then
            All_textures.Items[j] := nil;
    end;
end;

function Do_IsTexture(Texture: Integer): Boolean;
begin
    Result := (Texture > 0) and (Texture < All_textures.Count) and 
        (All_textures.Items[Texture] = Pointer(1));
end;

function GLProcAddress(const ProcName: String): Pointer;
begin
    Result := nil;
    if GLLib = 0 then
       GLLib := LoadLibrary('OpenGL32.dll');
    if GLLib = 0 then Exit;
    Result := GetProcAddress(GLLib, PChar(ProcName));
end;

{ TOpenGLbox }

procedure setupPixelFormat(DC:HDC);
const
   pfd:TPIXELFORMATDESCRIPTOR = (
        nSize:sizeof(TPIXELFORMATDESCRIPTOR);	// size
        nVersion:1;			                    // version
        dwFlags:PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or
                PFD_DOUBLEBUFFER;	// support double-buffering
        iPixelType:PFD_TYPE_RGBA;	// color type
        cColorBits:24;			    // preferred color depth
        cRedBits:0; cRedShift:0;	// color bits (ignored)
        cGreenBits:0;  cGreenShift:0;
        cBlueBits:0; cBlueShift:0;
        cAlphaBits:0;  
        cAlphaShift:0;              // no alpha buffer
        cAccumBits: 0;
        cAccumRedBits: 0;  		    // no accumulation buffer,
        cAccumGreenBits: 0;     	// accum bits (ignored)
        cAccumBlueBits: 0;
        cAccumAlphaBits: 0;
        cDepthBits:16;			    // depth buffer
        cStencilBits:0;			    // no stencil buffer
        cAuxBuffers:0;			    // no auxiliary buffers
        iLayerType:PFD_MAIN_PLANE;  // main layer
        bReserved: 0;
        dwLayerMask: 0;             // no layer
        dwVisibleMask: 0;           // visible
        dwDamageMask: 0;            // damage masks
   );
var pixelFormat:integer;
begin
   pixelFormat := ChoosePixelFormat(DC, @pfd);
   if (pixelFormat = 0) then exit;
   if (not SetPixelFormat(DC, pixelFormat, @pfd)) then exit;
end;

constructor TOpenGLbox.Create;
begin
  inherited;
end;

procedure TOpenGLbox.Initialize_OpenGL;
begin
  DC := GetDC(Box.GetWindowHandle);
  SetupPixelFormat(DC);
  RC:=wglCreateContext(DC); //makes OpenGL window out of DC
  wglMakeCurrent(DC, RC);   //makes OpenGL window active
  //ReleaseDC(Handle, DC);
end;

procedure TOpenGLbox.BoxErase(Sender: PControl; aDC: HDC);
begin
    //M.Result := 1;
end;

procedure TOpenGLbox.BoxPaint(Sender: PControl; aDC: HDC);
var R: TRect;
    F: C_Form;
    save: String;
begin
    if Tag = 0 then Exit;
    R := Box.ClientRect;
    wglMakeCurrent(DC, RC);
    glViewport(0, 0, R.Right - R.Left, R.Bottom - R.Top);
    F := C_Form( AL4Form.AL4Object.Obj );
    //begin
    //    Object_assign_hard(F.F_sender, (Ref_obj(Tag)).Obj);
    //end;
    save := F.F_menu_alias;
    F.F_menu_alias := C_OpenGL(Ref_obj(Box.Tag).Obj).F_Alias;
    
    operation_started(F, 22, nil);
	try
    F.M_Paint;
    finally
    F.M_operation_ended(22);
    end;
    
    //Object_assign_hard(F.F_sender, NoneObj_C_Control);
    F.F_menu_alias := save;
    
    ValidateRect(Box.Handle, nil);
    SwapBuffers(DC);
end;

(*
/*
FUN Format_pixels_from_internal_format_bitmap( INT I|nternal_format ) ==> INT :
    ----------------------------------------- 'for Delphi'
    CASE I ?
    [GL_RGB, 3]: RESULT = GL_BGR
    ELSE RESULT = GL_BGRA ; .

    
FUN Type_pixels_from_internal_format_bitmap( INT I|nternal_format ) ==> INT :
    ----------------------------------------- 'for Delphi'
    CASE I ?
    [GL_RGB, 3]: RESULT = GL_UNSIGNED_BYTE
    ELSE RESULT = GL_UNSIGNED_BYTE ; .
    
*/
*)

(*
/*
FUN Invalidate_open_gl_control(INT H|andle_control), NATIVE :
       @"var G: PControl;"
        "    G := PControl(X_H);"
        "    if G = nil then Exit;"
        "    G.Invalidate();" .
        
FUN Update_open_gl_control(INT H|andle_control), NATIVE :
       @"var G: PControl;"
        "    G := PControl(X_H);"
        "    if G = nil then Exit;"
        "    G.Invalidate;"
        "    G.Perform(WM_PAINT, 0, 0);"
        "    Turn_VSync_off;"
        .
*/
*)
var VSync_turned_off: Boolean;

var wglSwapIntervalEXT: function(Param: Integer): BOOL; stdcall;

procedure Turn_VSync_off;
begin
    wglSwapIntervalEXT := wglGetProcAddress('wglSwapIntervalEXT');
    if Assigned(wglSwapIntervalEXT) then wglSwapIntervalEXT(0);
end;

(*
/*
        
CONST STR : 
        NATIVE_import_OpenGL = @
        "uses OpenGL, AL4_OpenGL;"

                NATIVE_glGetError = @
                "    RESULT := glGetError();"
    
                NATIVE_gluErrorString = @
                "    RESULT := gluErrorString(X_Code);"
    
                NATIVE_glGetString = @
                "    RESULT := PChar(glGetString(X_Name));"
    
        NATIVE_glViewport = @
        "    glViewport(X_X, X_Y, X_Width, X_Height);"
    
        NATIVE_glClearColor = @
        "    glClearColor(X_R, X_G, X_B, X_A);"
        
                NATIVE_glClearDepth = @
                "    glClearDepth(X_Depth);"
                
                NATIVE_glClearStencil = @
                "    glClearStencil(X_S);"
                
                NATIVE_glAccum = @
                "    glAccum(X_Op, X_Value);"
                
                NATIVE_glClearAccum = @
                "    glClearAccum(X_R, X_G, X_B, X_A);"
                
        NATIVE_glClear = @
        "    glClear(X_B);"
        
        NATIVE_glEnable = @
        "    glEnable(X_What);"
        
        NATIVE_glDisable = @
        "    glDisable(X_What);"
        
        NATIVE_glIsEnabled = @
        "    RESULT := glIsEnabled(X_What);"
        
        NATIVE_glGetBooleanv = @
        "var p: array[0..1] of Byte;"
        "    glGetBooleanv(X_What, @p[0]);"
        "    X_Params.Clear();"
        "    X_Params.Add(MAXINT, Byte(p[0] <> 0));"
        
        NATIVE_glGetIntegerv = @
        "var p: array[0..3] of Integer;"
        "var i: Integer;"
        "    glGetIntegerv(X_What, @p[0]);"
        "    X_Param.Clear();"
        "    for i := 0 to X_size-1 do"
        "        X_Param.Add(MAXINT, p[i]);"
        
        NATIVE_glGetDoublev = @
        "var p: array[0..3] of Double;"
        "var i: Integer;"
        "    glGetDoublev(X_What, @p[0]);"
        "    X_Param.Clear();"
        "    for i := 0 to X_size-1 do"
        "        X_Param.Add(MAXINT, p[i]);"
        
                NATIVE_glColorMask = @
                "    glColorMask(X_Red,"
                "       X_Green,"
                "       X_Blue,"
                "       X_Alpha);"
                
        NATIVE_glCullFace = @
        "    glCullFace(X_Side);"
        
        NATIVE_glDepthFunc = @
        "    glDepthFunc(X_Func);"
        
                NATIVE_glDepthMask = @
                "    glDepthMask(X_Flag);"
                
                NATIVE_glDepthRange = @
                "    glDepthRange(X_Near, X_Far);"
                
                NATIVE_glLineWidth = @
                "    glLineWidth(X_Width);"
                
                NATIVE_glLineStipple = @
                "    glLineStipple(X_Factor, X_Pattern);"
                
                NATIVE_glPointSize = @
                "    glPointSize(X_Size);"
                
                NATIVE_glPolygonMode = @
                "       glPolygonMode(X_Face, X_Mode);"
                
                NATIVE_glPolygonOffset = @
                "    if (not Assigned(glPolygonOffset)) then"
                "       glPolygonOffset := GLProcAddress('glPolygonOffset');"
                "    if Assigned(glPolygonOffset) then"
                "       glPolygonOffset(X_Factor, X_Units);"
                
                NATIVE_glHint = @
                "    glHint(X_Target, X_Mode);"
                
        NATIVE_glFrontFace = @
        "    glFrontFace(X_Orient);"
        
        NATIVE_glMatrixMode = @
        "    glMatrixMode(X_Mode);"
        
        NATIVE_glLoadIdentity = @
        "    glLoadIdentity();"
        
        NATIVE_glPushMatrix = @
        "    glPushMatrix();"
        
        NATIVE_glPopMatrix = @
        "    glPopMatrix();"
        
        NATIVE_glMultMatrixd = @
        "var p: array[0..15] of Double;"
        "var i: Integer;"
        "    for i := 0 to X_Matrix.Count-1 do"
        "        p[i] := X_Matrix.GetReals(i);"
        "    glMultMatrixd(@p[0]);"
        
        NATIVE_glTranslated = @
        "    glTranslated(X_X, X_Y, X_Z);"
        
        NATIVE_glTranslatef = @
        "    glTranslatef(X_X, X_Y, X_Z);"
        
        NATIVE_glRotated = @
        "    glRotated(X_A, X_X, X_Y, X_Z);"
        
        NATIVE_glRotatef = @
        "    glRotatef(X_A, X_X, X_Y, X_Z);"
        
        NATIVE_glScaled = @
        "    glScaled(X_X, X_Y, X_Z);"
        
        NATIVE_glScalef = @
        "    glScalef(X_X, X_Y, X_Z);"
        
        NATIVE_gluPerspective = @
        "    gluPerspective(X_VerticalFOV, X_Aspect, X_Near, X_Far);"
                
                NATIVE_gluOrtho2D = @
                "    gluOrtho2D(X_Left, X_Right, X_Top, X_Bottom);"
                
                NATIVE_glOrtho = @
                "    glOrtho(X_Left, X_Right, X_Bottom, X_Top, X_Near, X_Far);"
                
                NATIVE_glFrustum = @
                "    glFrustum(X_Left, X_Right, X_Bottom, X_Top,"
                "       X_Near, X_Far);"
                
                NATIVE_gluProject = @
                "var m: array[0..15] of Double;"
                "var p: array[0..15] of Double;"
                "var v: array[0..3] of Integer;"
                "var r: array[0..2] of Double;"
                "var i: Integer;"
                "    for i := 0 to 15 do"
                "    begin"
                "        if i < X_Model.Count then"
                "           m[i] := X_Model.GetReals(i);"
                "        if i < X_Project.Count then"
                "           p[i] := X_Project.GetReals(i);"
                "    end;"
                "    for i := 0 to 3 do"
                "        if i < X_Viewport.Count then"
                "           v[i] := X_Viewport.GetIntegers(i);"
                "    gluProject(X_X_obj, X_Y_obj, X_Z_obj,"
                "       @m[0], @p[0], @v[0], r[0], r[1], r[2]);"
                "    for i := 0 to 3 do"
                "        if i < X_XYZ_win.Count then"
                "           X_XYZ_win.SetReals(i, r[i]);"
                
                NATIVE_gluUnProject = @
                "var m: array[0..15] of Double;"
                "var p: array[0..15] of Double;"
                "var v: array[0..3] of Integer;"
                "var r: array[0..2] of Double;"
                "var i: Integer;"
                "    for i := 0 to 15 do"
                "    begin"
                "        if i < X_Model.Count then"
                "           m[i] := X_Model.GetReals(i);"
                "        if i < X_Project.Count then"
                "           p[i] := X_Project.GetReals(i);"
                "    end;"
                "    for i := 0 to 3 do"
                "        if i < X_Viewport.Count then"
                "           v[i] := X_Viewport.GetIntegers(i);"
                "    gluUnProject(X_X_win, X_Y_win, X_Z_win,"
                "       @m[0], @p[0], @v[0], r[0], r[1], r[2]);"
                "    for i := 0 to 3 do"
                "        if i < X_XYZ_obj.Count then"
                "           X_XYZ_obj.SetReals(i, r[i]);"
                
                NATIVE_glClipPlane = @
                "var p: array[0..3] of Double;"
                "var i: Integer;"
                "    for i := 0 to X_Equation.Count-1 do"
                "        if i < 4 then"
                "           p[i] := X_Equation.GetReals(i);"
                "    glClipPlane(X_Plane, @p[0]);"
                
                NATIVE_glPushAttrib = @
                "    glPushAttrib(X_Mask);"
                
                NATIVE_glPopAttrib = @
                "    glPopAttrib();"
                
                NATIVE_glPushClientAttrib = @
                "    if not Assigned(glPushClientAttrib) then"
                "       glPushClientAttrib := GLProcAddress("
                "           'glPushClientAttrib');"
                "    if Assigned(glPushClientAttrib) then"
                "       glPushClientAttrib(X_Mask);"
                
                NATIVE_glPopClientAttrib = @
                "    if not Assigned(glPopClientAttrib) then"
                "       glPopClientAttrib := GLProcAddress("
                "           'glPopClientAttrib');"
                "    if Assigned(glPopClientAttrib) then"
                "       glPopClientAttrib();"
                
        NATIVE_glBegin = @
        "    glBegin(X_Mode);"
        
        NATIVE_glEnd = @
        "    glEnd;"
        
                NATIVE_glListBase = @
                "    glListBase(X_Base);"
                
                NATIVE_glGenLists = @
                "    RESULT := glGenLists(X_Range);"
                
                NATIVE_glIsList = @
                "    RESULT := glIsList(X_List);"
                
                NATIVE_glNewList = @
                "    glNewList(X_List, X_Mode);"
                
                NATIVE_glEndList = @
                "    glEndList;"
                
                NATIVE_glCallList = @
                "    glCallList(X_List);"
                
                NATIVE_glCallLists = @
                "var lists: PInteger;"
                "var p: PInteger;"
                "var i: Integer;"
                "    if X_N <= 0 then X_N := X_Lists.Count;"
                "    if X_N > X_Lists.Count then X_N := X_Lists.Count;"
                "    if X_N = 0 then Exit;"
                "    GetMem(lists, X_N * Sizeof(Integer));"
                "    p := lists;"
                "    for i := 0 to X_N-1 do"
                "    begin"
                "       p^ := X_Lists.GetIntegers(i);"
                "       inc(p);"
                "    end;"
                "    glCallLists(X_N, X_Type, lists);"
                "    FreeMem(lists);"
                
                NATIVE_glDeleteLists = @
                "    glDeleteLists(X_List, X_Range);"
                
        NATIVE_glVertex2d = @
        "    glVertex2d(X_X, X_Y);"
        
        NATIVE_glVertex2f = @
        "    glVertex2f(X_X, X_Y);"
        
        NATIVE_glVertex3d = @
        "    glVertex3d(X_X, X_Y, X_Z);"
        
        NATIVE_glVertex3f = @
        "    glVertex3f(X_X, X_Y, X_Z);"
        
        NATIVE_glVertex4d = @
        "    glVertex4d(X_X, X_Y, X_Z, X_W);"
        
        NATIVE_glVertex4f = @
        "    glVertex4f(X_X, X_Y, X_Z, X_W);"
        
        NATIVE_glTexCoord1d = @
        "    glTexCoord1d(X_S);"
        
        NATIVE_glTexCoord1f = @
        "    glTexCoord1f(X_S);"
        
        NATIVE_glTexCoord2d = @
        "    glTexCoord2d(X_S, X_T);"
        
        NATIVE_glTexCoord2f = @
        "    glTexCoord2f(X_S, X_T);"
        
        NATIVE_glTexCoord3d = @
        "    glTexCoord3d(X_S, X_T, X_R);"
        
        NATIVE_glTexCoord3f = @
        "    glTexCoord3f(X_S, X_T, X_R);"
        
        NATIVE_glTexCoord4d = @
        "    glTexCoord4d(X_S, X_T, X_R, X_Q);"
        
        NATIVE_glTexCoord4f = @
        "    glTexCoord4f(X_S, X_T, X_R, X_Q);"
        
        NATIVE_glNormal3d = @
        "    glNormal3d(X_X, X_Y, X_Z);"
        
        NATIVE_glNormal3f = @
        "    glNormal3f(X_X, X_Y, X_Z);"
        
        NATIVE_glColor3d = @
        "    glColor3d(X_Red, X_Green, X_Blue);"
        
        NATIVE_glColor3f = @
        "    glColor3f(X_Red, X_Green, X_Blue);"
        
        NATIVE_glColor4d = @
        "    glColor4d(X_Red, X_Green, X_Blue, X_Alpha);"
        
        NATIVE_glColor4f = @
        "    glColor4f(X_Red, X_Green, X_Blue, X_Alpha);"
        
        NATIVE_glGenTextures = @
        "    Do_GenTextures(X_N, X_Textures);"
        
        NATIVE_glIsTexture = @
        "    RESULT := Do_IsTexture(X_Texture);"
        
        NATIVE_glDeleteTextures = @
        "    Do_DeleteTextures(X_N, X_Textures);"
        
        NATIVE_glBindTexture = @
        "    if not Assigned(glBindTexture) then"
        "       glBindTexture := GLProcAddress('glBindTexture');"
        "    if not Assigned(glBindTexture) then Exit;"
        "    glBindTexture(X_Target, X_Texture);"
        
        NATIVE_glTexImage1D = @
        "    {$IFNDEF NOEXCEPTIONS}"
        "    try "
        "    {$ENDIF}"
        "    glTexImage1D(X_Target, X_Level, X_Internal_format,"
        "       X_Width, X_Border, X_Format, X_Type, X_Data.First_Byte);"
        "    {$IFNDEF NOEXCEPTIONS}"
        "    except on e: Exception do begin"
        "                   AL4.Any_exception(e);"
        "           end;"
        "    end;"
        "    {$ENDIF}"
        
        NATIVE_glTexSubImage1D = @
        "    {$IFNDEF NOEXCEPTIONS}"
        "    try "
        "    {$ENDIF}"
        "    if not Assigned(glTexSubImage1D) then"
        "       glTexSubImage1D := GLProcAddress('glTexSubImage1D');"
        "    if not Assigned(glTexSubImage1D) then Exit;"
        ""
        "    glTexSubImage1D(X_Target, X_Level, X_X_offset,"
        "       X_Width, X_Format, X_Type, X_Data.First_Byte);"
        "    {$IFNDEF NOEXCEPTIONS}"
        "    except on e: Exception do begin"
        "                   AL4.Any_exception(e);"
        "           end;"
        "    end;"
        "    {$ENDIF}"
        
        NATIVE_glTexImage2D = @
        "    {$IFNDEF NOEXCEPTIONS}"
        "    try "
        "    {$ENDIF}"
        "    glTexImage2D(X_Target, X_Level, X_Internal_format,"
        "       X_Width, X_Height, X_Border, X_Format, X_Type,"
        "       X_Data.First_Byte);"
        "    {$IFNDEF NOEXCEPTIONS}"
        "    except on e: Exception do begin"
        "                   AL4.Any_exception(e);"
        "           end;"
        "    end;"
        "    {$ENDIF}"
        
        NATIVE_glTexSubImage2D = @
        "    {$IFNDEF NOEXCEPTIONS}"
        "    try "
        "    {$ENDIF}"
        "    if not Assigned(glTexSubImage2D) then"
        "       glTexSubImage2D := GLProcAddress('glTexSubImage2D');"
        "    if not Assigned(glTexSubImage2D) then Exit;"
        ""
        "    glTexSubImage2D(X_Target, X_Level, X_X_offset,"
        "       X_Y_offset, X_Width, X_Height, X_Format, X_Type,"
        "       X_Data.First_Byte);"
        "    {$IFNDEF NOEXCEPTIONS}"
        "    except on e: Exception do begin"
        "                   AL4.Any_exception(e);"
        "           end;"
        "    end;"
        "    {$ENDIF}"
        
        NATIVE_gluBuild1DMipmaps = @
        "    gluBuild1DMipmaps(X_Target, X_Components, X_Width,"
        "       X_Format, X_Type, X_Data.First_Byte);"
        
        NATIVE_gluBuild2DMipmaps = @
        "    gluBuild2DMipmaps(X_Target, X_Components, X_Width,"
        "       X_Height, X_Format, X_Type,"
        "		X_Data.First_Byte);"
        
        NATIVE_glTexParameteri = @
        "    glTexParameteri(X_Target, X_Pname, X_Param);"
        
        NATIVE_glTexParameterf = @
        "    glTexParameterf(X_Target, X_Pname, X_Param);"
        
        NATIVE_glTexParameterfv = @
        "var p: array[0..3] of Single;"
        "var i: Integer;"
        "var n: Integer;"
        "    n := 4;"
        "    if (n > X_Param.Count) then n := X_Param.Count;"
        "    for i := 0 to n-1 do"
        "        p[i] := X_Param.GetReals(i);"
        "    glTexParameterfv(X_Target, X_Pname, @p[0]);"
        
        NATIVE_glTexEnvi = @
        "    glTexEnvi(X_Target, X_Pname, X_Param);"
        
        NATIVE_glTexEnvf = @
        "    glTexEnvf(X_Target, X_Pname, X_Param);"
        
        NATIVE_glBlendFunc = @
        "    glBlendFunc(X_Sfactor, X_Dfactor);"
        
        NATIVE_glAlphaFunc = @
        "    glAlphaFunc(X_Func, X_Ref);"
        
        NATIVE_glStencilFunc = @
        "    glStencilFunc(X_Func, X_Ref, X_Mask);"
        
        NATIVE_glStencilOp = @
        "    glStencilOp(X_Ffail, X_Dpfail, X_Dppass);"
        
        NATIVE_glStencilMask = @
        "    glStencilMask(X_Mask);"
        
        NATIVE_glLightf = @
        "    glLightf(X_Light, X_Pname, X_Param);"
        
        NATIVE_glLightfv = @
        "var p: array[0..3] of Single;"
        "var i: Integer;"
        "var n: Integer;"
        "    n := 4;"
        "    if (n > X_Param.Count) then n := X_Param.Count;"
        "    for i := 0 to n-1 do"
        "        p[i] := X_Param.GetReals(i);"
        "    glLightfv(X_Light, X_Pname, @p[0]);"
        
        NATIVE_glLightModeli = @
        "    glLightModeli(X_Pname, X_Param);"
        
        NATIVE_glLightModelfv = @
        "var p: array[0..3] of Single;"
        "var i: Integer;"
        "var n: Integer;"
        "    n := 4;"
        "    if (n > X_Param.Count) then n := X_Param.Count;"
        "    for i := 0 to n-1 do"
        "        p[i] := X_Param.GetReals(i);"
        "    glLightModelfv(X_Pname, @p[0]);"
        
        NATIVE_glMaterialf = @
        "    glMaterialf(X_Face, X_Pname, X_Param);"
        
        NATIVE_glMaterialfv = @
        "var p: array[0..3] of Single;"
        "var i: Integer;"
        "var n: Integer;"
        "    n := 4;"
        "    if (n > X_Param.Count) then n := X_Param.Count;"
        "    for i := 0 to n-1 do"
        "        p[i] := X_Param.GetReals(i);"
        "    glMaterialfv(X_Face, X_Pname, @p[0]);"
        
        NATIVE_glMaterialiv = @
        "var p: array[0..2] of Integer;"
        "var i: Integer;"
        "var n: Integer;"
        "    n := 3;"
        "    if (n > X_Param.Count) then n := X_Param.Count;"
        "    for i := 0 to n-1 do"
        "        p[i] := X_Param.GetIntegers(i);"
        "    glMaterialiv(X_Face, X_Pname, @p[0]);"
        
        NATIVE_glColorMaterial = @
        "    glColorMaterial(X_Face, X_Mode);"
        
        NATIVE_glFogi = @
        "    glFogi(X_Pname, X_Param);"
        
        NATIVE_glFogf = @
        "    glFogf(X_Pname, X_Param);"
        
        NATIVE_glFogfv = @
        "var p: array[0..3] of Single;"
        "var i: Integer;"
        "var n: Integer;"
        "    n := 4;"
        "    if (n > X_Param.Count) then n := X_Param.Count;"
        "    for i := 0 to n-1 do"
        "        p[i] := X_Param.GetReals(i);"
        "    glFogfv(X_Pname, @p[0]);"

        NATIVE_gluNewQuadric = @
        "    RESULT := Integer(gluNewQuadric());"
        
        NATIVE_gluDeleteQuadric = @
        "    gluDeleteQuadric(Pointer(X_Obj));"
        
        NATIVE_gluQuadricDrawStyle = @
        "    gluQuadricDrawStyle(Pointer(X_Obj), X_Style);"
        
        NATIVE_gluQuadricOrientation = @
        "    gluQuadricOrientation(Pointer(X_Obj), X_Orient);"
        
        NATIVE_gluQuadricTexture = @
        "    gluQuadricTexture(Pointer(X_Obj), ByteBool(X_Texture_c));"
        
        NATIVE_gluQuadricNormals = @
        "    gluQuadricNormals(Pointer(X_Obj), X_Normals);"
        
        NATIVE_gluCylinder = @
        "    gluCylinder(Pointer(X_Obj),"
        "       X_Base_r, X_Top_r, X_Height, X_Slices, X_Stacks);"
        
        NATIVE_gluDisk = @
        "    gluDisk(Pointer(X_Obj), X_Inner_r, X_Outer_r, X_Slices, X_Loops);"
        
        NATIVE_gluPartialDisk = @
        "    gluPartialDisk(Pointer(X_Obj),"
        "       X_Inner_r, X_Outer_r, X_Slices, X_Loops, X_Start_a, X_Sweep_a);"
        
        NATIVE_gluSphere = @
        "    gluSphere(Pointer(X_Obj), X_Radius,"
        "       X_Slices, X_Stacks);"

        .        
*/
*)

end.
(*
/*
END
*/
*)



