home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue42 / opengl / glAbsWin.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-11-26  |  32.9 KB  |  904 lines

  1. unit glAbsWin;
  2. {============================================================}
  3. { Unit Title -  Abstract OpenGL Window                            }
  4. {                                                            }
  5. { Codemaster  -      ohn Hutchings                             }
  6. {   Date      -      10/6/98                                 }
  7. {  DeBugged   -               }
  8. {                                }
  9. {============================================================}
  10.  
  11. {$V+,X+,F+,B-}
  12. {$IFDEF MinSize} {$S-,L-,R-,Q-,D-} {$ENDIF}
  13.  
  14. {===============================================================================
  15.  
  16. PURPOSE
  17.  
  18.    Unit contains all the basic GL windows functionality.
  19.    Should be considered as an abstract class and not used
  20.  
  21. METHOD
  22.  
  23. COMPILER DIRECTIVES
  24.  
  25.   DEBUG     adds addition tests for valid data and type safe assigns
  26.   MINSIZE   limits debug and symbol info
  27.  
  28. GLOBALS
  29.  
  30.   Classes
  31.   Exceptions
  32.   Variables
  33.  
  34.   Procedures
  35.  
  36. EXCEPTIONS
  37.  
  38.  
  39. NOTES
  40.  
  41.  
  42. ===============================================================================}
  43.  
  44. interface
  45. {$W+}//set stack frames on as this seemms to help win95 access error
  46. uses
  47.   Windows, Messages, SysUtils, Classes, Graphics, MmSystem,
  48.   Controls, Forms, Dialogs, stdctrls,comctrls,opengl, glFuncs;
  49.  
  50.  Type
  51.    // handle hi -res bit map image
  52.    TAbstractOpenGLBitmap = class(TObject)
  53.    Protected
  54.     faPPfd                 : TPixelFormatDescriptor;
  55.     fPixelFormat           : LongInt;
  56.     fRenderDC              : HDC;
  57.     fGLPalette             : HPalette;
  58.     fHRC                   : HGLRC;
  59.     fBitMap                : TBitMap;
  60.     fAllOK                 : Boolean;
  61.     fBackColor             : GLBackground;
  62.  
  63.     Procedure GLStartUp;                    Virtual;
  64.     // Startn up the GLSession
  65.     Procedure GLShutDown;                   Virtual;
  66.     // Shut down a session
  67.     Function GetCanvas:TCanvas;
  68.  
  69.  
  70.     Function SetUpPixelFormat:Boolean;       Virtual;
  71.     //Set up the pixel formatfor the session}
  72.  
  73.     Public
  74.      constructor CreateInit(aBitMap:tBitMap;aBack:GLBackground);
  75.      destructor Destroy; override;
  76.  
  77.      Property GLRC    : HGLRC Read fHRC;
  78.      property RenderDC: HDC   Read fRenderDC;
  79.      Property GLCanvas: TCanvas Read GetCanvas;
  80.      Property ViewMap : TBitMap Read fBitMap;
  81.      Property GLSessionOK:Boolean Read fAllOk;
  82.   end;
  83.  
  84.  TAbstractOpenGLControl = Class(TComponent)
  85.    Private
  86.     FWindowHandle          : HWnd;
  87.     faPPfd                 : TPixelFormatDescriptor;
  88.     fPixelFormat           : LongInt;
  89.     fHRC                   : HGLRC;
  90.   // pixel Support flags
  91.    (*
  92.     pfd_Win_Draw,
  93.     fpfd_BitMap,
  94.     fpfd_Accel,
  95.     fpfdDoubleBuf,
  96.     fpfd_Swap_Copy,
  97.     fpfd_swap_exhg,
  98.     fpfd_GL_sup,
  99.     fpfd_GDI_sup,
  100.     fpfd_Stereo            : Boolean;
  101.      *)
  102.     procedure WndProc(var Msg: TMessage);
  103.  
  104.     Procedure SetRenderContext(aVal:HGLRC);
  105.     Procedure SetPFormat(aVal:LongInt);
  106.     Procedure SetPixelDescription(aVal:TPixelFormatDescriptor);
  107.  
  108.    Public
  109.     constructor Create(AOwner: TComponent);Override;
  110.     destructor Destroy;                             Override;
  111.  
  112.     Procedure SetUpHandle;
  113.  
  114.     Property RenderDC: HGLRC read fHRC Write SetRenderContext;
  115.     Property PixelDescription:TPixelFormatDescriptor Read faPPfd Write SetPixelDescription;
  116.     Property PixelFormat : LongInt read fPixelFormat Write SetPFormat;
  117.  
  118.   end;
  119.  
  120.   TAbstractOpenGL = class(TWinControl)
  121.    Private
  122.     fGLLock                : TRTLCriticalSection;
  123.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  124.  
  125.    Protected
  126.     faPPfd                 : TPixelFormatDescriptor;
  127.     fPixelFormat           : LongInt;
  128.     fRenderDC              : HDC;
  129.     fGLPalette             : HPalette;
  130.     fHRC                   : HGLRC;
  131.     fGMF                   : tGMF;
  132.     // bitmap size=0 when drawing to screen
  133.  
  134.     fShareGL               : TAbstractOpenGL;
  135.     fErrorList             : TStringList;
  136.     // holds a list of all errors from the last get error call
  137.     //use display list of this GLWin
  138.  
  139.     fDoneGLSetup,      // used to tag initial setup been done
  140.     fValidBuffer,          //valid buffer for copying to screen rather than repaint
  141.     fRebuildNeeded,        //need to rebuild ie rerender
  142.     fGrabFocus,            // Grab the focus if set to true Default=true
  143.     fRepaintNeeded,        // only need to repaint ie swap buffer if valid
  144.     fCloseGL,               // close the GL session if not focused
  145.   // pixel Support flags
  146.     pfd_Win_Draw,
  147.     fpfd_BitMap,
  148.     fpfd_Accel,
  149.     fpfdDoubleBuf,
  150.     fpfd_Swap_Copy,
  151.     fpfd_swap_exhg,
  152.     fpfd_GL_sup,
  153.     fpfd_GDI_sup,
  154.     fpfd_Stereo,
  155.     fGDIGeneric           // WARNING this needs to be true for safe GDI calls
  156.     //there is a risk if this is false that GDI calls via canvas will fail dramatically
  157.              : Boolean;
  158.  
  159.  
  160.     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  161.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  162.     procedure WMKillFocus(var Message: TWMSetFocus); message WM_KILLFOCUS;
  163.  
  164.     procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  165.     procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  166.  
  167.  //Override basic startup and shut down
  168.     procedure CreateParams(var Params: TCreateParams);           Override;
  169. // set up the basic window parameters
  170.     procedure DestroyWindowHandle;                               Override;
  171. // close down the GL session
  172.  
  173.    Procedure GLStartUp;                    Virtual;
  174.   // Startn up the GLSession
  175.    Procedure GLShutDown;                   Virtual;
  176.   // Shut down a session
  177.  
  178.     Procedure DoMoveTidyUp;                 Virtual;
  179.     // If pan zoom etc then tidy up the possible cursor draw
  180.     Function SetUpPixelFormat:Boolean;       Virtual;
  181.     //Set up the pixel formatfor the session}
  182.     Procedure GLLock;
  183.     // Lock the current procedure
  184.     Procedure GLUnLock;
  185.     // Unlock the current procedure
  186.     Procedure SetGrabFocus(Val:Boolean);
  187.     // force focus to this window
  188.     Procedure setShareGLWin(Val: TAbstractOpenGL);
  189.     //TIDY UP - this may not be needed
  190.     Procedure SetGenericGDI(AVal:Boolean);
  191.   // set the GDI use state
  192.  
  193.     Procedure SaveState(aState:GLSaveState);
  194.     // save the current state before mods restore state will reset
  195.     Procedure RestoreState;
  196.     // return the last state
  197.  
  198.  
  199.   Public
  200.     constructor Create(AOwner: TComponent); Override; 
  201.     destructor Destroy;                     override;
  202.  
  203.     procedure Repaint;                      Override;
  204.     {Modifies the standard paint to now handle the OpenGL drawing}
  205.     procedure InvalidateRectangle(Rect:TRect;DoRepaint:Boolean);
  206.     // will invalidate only the given rectangle area of the control
  207.    Function EnableGL:Boolean;
  208.    // Ensure that this window has the active session
  209.  
  210.    Procedure DisableGL;
  211.    //Turn off the GL Session
  212.  
  213.    Function IsGLActive:Boolean;
  214.     {Is the current }
  215.  
  216.    Function  GetError:Boolean;
  217.     // run error checking on GL session
  218.    Procedure ClearError;
  219.     // empty the error list
  220.   { Procedure PrintWindow(aPrinter:tPrinter);  Virtual;}
  221.    //Handle the printing of the window to a Printer
  222.  
  223.    Property GLRenderDC :HDC         Read fRenderDC;
  224.    Property GLContext  :HGLRC       Read fHRC;
  225.    Property PixelFormat:LongInt     Read fPixelFormat;
  226.    Property PixelData  :TPixelFormatDescriptor read faPPfd;
  227.    Property ErrorList  :TStringList read fErrorList;
  228.  //publish later
  229.    Property GrabFocus:Boolean Read fGrabFocus Write SetGrabFocus;
  230.    Property ShareGL  :TAbstractOpenGL Read fShareGL Write setShareGLWin;
  231.    Property GenericGDI :Boolean     Read fGDIGeneric write SetGenericGDI;
  232.  
  233.   end;
  234. (*************************************************************)
  235.                           implementation
  236. (*************************************************************)
  237. (*************************************************************)
  238. var
  239.   GLUtilWindowClass: TWndClass = (
  240.     style: CS_VREDRAW + CS_HREDRAW + CS_DBLCLKS + CS_OWNDC;
  241.     lpfnWndProc: @DefWindowProc;
  242.     cbClsExtra: 0;
  243.     cbWndExtra: 0;
  244.     hInstance: 0;
  245.     hIcon: 0;
  246.     hCursor: 0;
  247.     hbrBackground: 0;
  248.     lpszMenuName: nil;
  249.     lpszClassName: 'GLUtilWindow');
  250.  
  251. (*************************************************************)
  252. (*************************************************************)
  253. function GLAllocateHWnd(parentWin:HWND;Method: TWndMethod): HWND;
  254. var
  255.   TempClass: TWndClass;
  256.   ClassRegistered: Boolean;
  257. begin
  258.   Result:=0;
  259.   If ParentWin=0 then exit;
  260.   GLUtilWindowClass.hInstance := HInstance;
  261.   ClassRegistered := GetClassInfo(HInstance, GLUtilWindowClass.lpszClassName,TempClass);
  262.   if not ClassRegistered or (TempClass.lpfnWndProc <> @DefWindowProc) then
  263.   begin
  264.     if ClassRegistered then
  265.       Windows.UnregisterClass(GLUtilWindowClass.lpszClassName, HInstance);
  266.     Windows.RegisterClass(GLUtilWindowClass);
  267.   end;
  268.  
  269.   Result := CreateWindowEx(0, GLUtilWindowClass.lpszClassName,
  270.     '', WS_BORDER or WS_CHILD or WS_CLIPCHILDREN or WS_CLIPSIBLINGS , 0, 0, 10, 10, parentWin, 0, HInstance, nil);
  271.   if Assigned(Method) then
  272.     SetWindowLong(Result, GWL_WNDPROC, Longint(MakeObjectInstance(Method)));
  273. end;
  274.  
  275. (*************************************************************)
  276. (*************************************************************)
  277. procedure GLDeallocateHWnd(Wnd: HWND);
  278. var
  279.   Instance: Pointer;
  280. begin
  281.   If Wnd=0 then exit;
  282.   Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
  283.   DestroyWindow(Wnd);
  284.   if Instance <> @DefWindowProc then FreeObjectInstance(Instance);
  285. end;
  286. (*************************************************************)
  287. constructor TAbstractOpenGLControl.Create(AOwner: TComponent);
  288. begin
  289.   inherited Create(AOwner);
  290. end;
  291. (*************************************************************)
  292.  
  293. destructor TAbstractOpenGLControl.Destroy;
  294. begin
  295.   GLDeallocateHWnd(FWindowHandle);
  296.   inherited Destroy;
  297. end;
  298. (*************************************************************)
  299.  Procedure TAbstractOpenGLControl.SetUpHandle;
  300.   Begin
  301.    If (FWindowHandle=0) and
  302.       Assigned(Application) and
  303.       Assigned(Application.MainForm) and
  304.       (Application.MainForm.Handle<>0) then FWindowHandle := GLAllocateHWnd(Application.mainform.Handle,WndProc);
  305.   end;
  306. (*************************************************************)
  307.   procedure TAbstractOpenGLControl.WndProc(var Msg: TMessage);
  308.   begin
  309.    With Msg do
  310.      Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  311.   end;
  312. (*************************************************************)
  313.   Procedure TAbstractOpenGLControl.SetRenderContext(aVal:HGLRC);
  314.     Begin
  315.  
  316.     end;
  317. (*************************************************************)
  318.   Procedure TAbstractOpenGLControl.SetPFormat(aVal:LongInt);
  319.     Begin
  320.     end;
  321. (*************************************************************)
  322. Procedure TAbstractOpenGLControl.SetPixelDescription(aVal:TPixelFormatDescriptor);
  323.     Begin
  324.     end;
  325. (*************************************************************)
  326. (*************************************************************)
  327. constructor TAbstractOpenGL.Create(AOwner: TComponent);
  328. Begin
  329.   DoubleBuffered:=False;
  330.   Inherited Create(aOwner);
  331.   TabStop:=True;
  332.   ShowHint:=true;
  333.   fErrorList  := TStringList.Create;
  334.   fShareGL    := nil;
  335.   fValidBuffer:= False;        //valid buffer for copying to screen rather than repaint
  336.   fRebuildNeeded:=True;        //need to rebuild ie rerender
  337.   fRepaintNeeded:=True;        // only need to repaint ie swap buffer if valid
  338.   fDoneGLSetup:=False;
  339.  
  340.   InitializeCriticalSection(fGLLock);
  341. end;
  342. (*************************************************************)
  343. procedure TAbstractOpenGL.CreateParams(var Params: TCreateParams);
  344. begin
  345.   inherited CreateParams(Params);    { call the inherited first }
  346.   Params.Style := WS_child + WS_CLIPCHILDREN + WS_CLIPSIBLINGS + ws_border;
  347.   //set up the windows style flags MUST have ClipChildren and clipsiblings
  348.   Params.WindowClass.style := CS_VREDRAW + CS_HREDRAW + CS_DBLCLKS + CS_OWNDC;
  349.   // set up the windowclass style MUST have VRedraw, HRedraw and OwnDC
  350. end;
  351. (******* ******************************************************)
  352. Procedure TAbstractOpenGL.GLStartUp;
  353.   // Startn up the GLSession
  354.   Begin
  355.      fRenderDC:=GetDC(handle);
  356.  //MUST use the current window handle and will hold onto it
  357.      If fRenderDC=0 then Exit;
  358.  // Set up the pixel format for the window}
  359.      SetUpPixelFormat;
  360.  // Create the Render Context}
  361.      fHRC:=wglCreateContext(fRenderDC);
  362.      If fHRC=0 then  Exit;
  363.      EnableGL;
  364.      // set this session as current
  365.   // if the first GL context then set as primary
  366.      if assigned(fShareGL) then wglShareLists(fShareGL.fHRC,fHRC);
  367.   // check for GLErrors
  368.      GetError;
  369.   end;
  370. (******* ******************************************************)
  371. destructor TAbstractOpenGL.Destroy;
  372. Begin
  373.   DeleteCriticalSection(FGLLock);
  374.   fErrorList.Free;
  375.   Inherited Destroy;
  376. end;
  377. (******* ******************************************************)
  378. Procedure TAbstractOpenGL.GLShutDown;
  379.   // Shut down a GL session
  380.   Begin
  381.      If (wglGetCurrentContext=fHRC)then  wglMakeCurrent(0,0);
  382.      If fHRC<>0 then
  383.       Begin
  384.        wglDeleteContext(fHRC);
  385.        fHRC:=0;
  386.       end;
  387.      If fGLPalette<>0 then DeleteObject(fGLPalette);
  388.      fGLPalette:=0;
  389.      If fRenderDC<>0 then ReleaseDC(handle,fRenderDC);
  390.      //no real need to do this for pri vate DC
  391.      fRenderDC:=0;
  392.   end;
  393. (*************************************************************)
  394.  Procedure TAbstractOpenGL.DoMoveTidyUp;
  395.     // If pan zoom etc then tidy up the possible cursor draw
  396.   Begin    end;
  397. (******* ******************************************************)
  398. Function TAbstractOpenGL.SetUpPixelFormat:Boolean;
  399.  Var
  400.   ECode        : DWord;
  401. { If necessary, creates a 3-3-2 palette for the device context listed.}
  402.           Procedure GetOpenGLPalette;
  403.           Var
  404.             pPal:^TLogPalette;        {Pointer to memory for logical palette}
  405.             nColors:Integer;        { Number of entries in palette}
  406.             i      :Integer;               { Counting variable }
  407.             RedRange,GreenRange,BlueRange:BYTE;{ Range for each color entry (7,7,and 3)}
  408.             MultVal:Byte;
  409.             aVal:Byte;
  410.           Begin
  411.             { Get the pixel format index and retrieve the pixel format description}
  412.             DescribePixelFormat(frenderDC, fPixelFormat, sizeof(TPIXELFORMATDESCRIPTOR), faPPfd);
  413.              { Does this pixel format require a palette?  If not, do not create a}
  414.              { palette and just return NULL}
  415.             if not(PFD_NEED_PALETTE = (faPPfd.dwFlags and PFD_NEED_PALETTE)) then exit;
  416.              { Number of entries in palette.  8 bits yeilds 256 entries}
  417.             nColors := 1 shl faPPfd.cColorbits{1 << pfd.cColorBits};
  418.           { Allocate space for a logical palette structure plus all the palette entries}
  419.             GetMem(pPal,SizeOf(TLogPalette)+nColors*sizeOf(TpaletteEntry));
  420.           { Fill in palette header}
  421.             pPal^.palVersion := $300;        { Windows 3.0}
  422.             pPal^.palNumEntries := nColors; { table size }
  423.  
  424.                   { Build mask of all 1's.  This creates a number represented by having
  425.                   { the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
  426.                   { pfd.cBlueBits. }
  427.             RedRange   := (1 shl faPPfd.cRedBits)-1{(1 << pfd.cRedBits) -1};
  428.             GreenRange :=( 1 shl faPPfd.cGreenBits)-1 {(1 << pfd.cGreenBits) - 1};
  429.             BlueRange  := (1 shl faPPfd.cBlueBits)-1{(1 << pfd.cBlueBits) -1};
  430.             MultVal:=255;
  431.                   { Loop through all the palette entries}
  432.           {$R-}
  433.             For i:=0 to nColors-1 do
  434.               With pPal^ do Begin
  435.                 AVal:=   (i shr faPPfd.cRedShift) and RedRange;
  436.                 aVal:=   aVal*MultVal div RedRange;
  437.                 palPalEntry[i].peRed:=aVal;
  438.                 aVal:= (i shr faPPfd.cGreenshift) and GreenRange;
  439.                 aVal:= aVal*MultVal div GreenRange;
  440.                 palPalEntry[i].peGreen:=aVal;
  441.                 aVal:=  (i shr faPPfd.cBlueShift) and BlueRange;
  442.                 aVal:=  aVal*MultVal div BlueRange;
  443.                 palPalEntry[i].peBlue:=aVal;
  444.                 palPalEntry[i].peFlags := 0;
  445.                end;
  446.                   { Create the palette}
  447.           {R+}
  448.             fGLPalette := CreatePalette(pPal^);
  449.  
  450.                   { Free the memory used for the logical palette structure}
  451.             FreeMem(pPal,SizeOf(TLogPalette)+nColors*sizeOf(TpaletteEntry));
  452.           end;
  453. Begin
  454.   Result:=False;
  455.   fGLPalette:=0;
  456.   If fRenderDC=0 then exit;
  457.   FillChar(fAPPFD,SizeOf(fAPPFD),0);
  458.   With fAPPFD do
  459.   Begin
  460.     nSize:=SizeOf(fAPPFD);
  461.     nVersion:=1;                     //Must Be
  462.     dwFlags:=(PFD_Draw_To_Window or  //rendering to a window
  463.               Pfd_Support_OpenGL or  //supporting OpenGL
  464.               Pfd_Stereo or          //request stereo buffers if hardware supports it(not often)
  465.               pfd_Generic_Accelerated or //use accelerated if available
  466.               pfd_swap_copy or      //swapcopy will swap in a buffer but keep a copy
  467.               PFD_DOUBLEBUFFER) ;   //want double buffering for smooth animation
  468.     iPixelType:=PFD_TYPE_RGBA;      //see current settings in GLFuncs
  469.     cColorBits:=pix_ColorBits;      //see current settings in GLFuncs
  470.     cDepthBits:=pix_DepthBits;      //see current settings in GLFuncs
  471.     cStencilBits:=pix_StencilBits;  //see current settings in GLFuncs
  472.     cAccumBits:=pix_AccumBits;      //see current settings in GLFuncs
  473.     cAlphaBits:=0;                  //no choice in Windows
  474.     cAuxBuffers:=0;                 //no choice in Windows
  475.     iLayerType:=PFD_Main_Plane;     //no choice in Windows
  476.   end;
  477.   fPixelFormat:=ChoosePixelFormat(fRenderDC,@fAPPFD); // find the closest fit to the requested
  478.   Result:=SetPixelFormat(fRenderDC,fPixelFormat,@faPPFD); //set the pixel format
  479.   DescribePixelFormat(frenderDC, fPixelFormat, sizeof(TPIXELFORMATDESCRIPTOR), faPPfd);
  480.   fPixelFormat:=GetPixelFormat(fRenderDC);
  481.   fGDIGeneric:=False;
  482. // set up identifier flags
  483.   pfd_Win_Draw  := (PFD_Draw_To_Window = (faPPFD.dwFlags and PFD_Draw_To_Window));
  484.   fpfd_BitMap   := (PFD_Draw_To_Bitmap = (faPPFD.dwFlags and PFD_Draw_To_Bitmap));
  485.   fpfd_Accel    := (PFD_GENERIC_ACCELERATED = (faPPFD.dwFlags and PFD_GENERIC_ACCELERATED));
  486.   fpfdDoubleBuf := (PFD_DOUBLEBUFFER = (faPPFD.dwFlags and PFD_DOUBLEBUFFER));
  487.   fpfd_Swap_Copy:= (pfd_swap_copy = (faPPFD.dwFlags and pfd_swap_copy));
  488.   fpfd_swap_exhg:= (pfd_swap_exchange = (faPPFD.dwFlags and pfd_swap_exchange));
  489.   fpfd_GL_sup   := (Pfd_Support_OpenGL = (faPPFD.dwFlags and Pfd_Support_OpenGL));
  490.   fpfd_GDI_sup  := (Pfd_Support_GDI = (faPPFD.dwFlags and Pfd_Support_GDI));
  491.   fpfd_Stereo   := (PFD_STEREO = (faPPFD.dwFlags and PFD_STEREO));
  492.   If Result then
  493.    Begin
  494.       { Get the pixel format index and retrieve the pixel format description}
  495.        if (PFD_NEED_PALETTE = (faPPfd.dwFlags and PFD_NEED_PALETTE)) then
  496.        Begin
  497.          { Go ahead and select and realize the palette for this device context}
  498.          If fGLPalette=0 then GetOpenGLPalette;
  499.          SelectPalette(fRenderDC,fGLPalette,FALSE);
  500.          RealizePalette(fRenderDC);
  501.        end;
  502.    end else
  503.     Begin
  504.      ECode:=GetLastError;
  505.      If ECode>0 then
  506.         MessageDlg('Problem with Set pixel format',mtInformation,[mbOk], 0);
  507.     end;
  508. end;
  509. (*************************************************************)
  510. Procedure TAbstractOpenGL.ClearError;
  511.   Begin
  512.     fErrorList.Clear;
  513.   end;
  514. (************************************************************)
  515. Function TAbstractOpenGL.GetError:Boolean;
  516. var
  517.   glError: glEnum;
  518.   s: string;
  519.   Counter:LongInt;
  520. begin
  521.   Result:=False;
  522.   If not EnableGL then exit;
  523.   Counter:=0;
  524.   Repeat
  525.     glError:= glGetError;
  526.     case glError of
  527.       GL_INVALID_ENUM:      s:= 'GL_INVALID_ENUM';
  528.       GL_INVALID_VALUE:     s:= 'GL_INVALID_VALUE';
  529.       GL_INVALID_OPERATION: s:= 'GL_INVALID_OPERATION';
  530.       GL_STACK_OVERFLOW:    s:= 'GL_STACK_OVERFLOW';
  531.       GL_STACK_UNDERFLOW:   s:= 'GL_STACK_UNDERFLOW';
  532.       GL_OUT_OF_MEMORY:     s:= 'GL_OUT_OF_MEMORY';
  533.     end;
  534.     If Length(s)>0 then
  535.       fErrorList.Add(s);
  536.     Inc(Counter);
  537.   Until  (glError<>GL_NO_ERROR) or (Counter=1000)or (Length(s)=0);
  538.   Result:=(counter>1);
  539.   {$IFDEF ERRORDEBUG}
  540.   If Result then messagedlg('Error here',mtinformation,[mbok],0);
  541.   {$ENDIF}
  542. end;
  543. (*************************************************************)
  544. procedure TAbstractOpenGL.WMPaint(var Message: TWMPaint);
  545. begin
  546.   ControlState:= ControlState + [csCustomPaint];
  547.   inherited;
  548.   ControlState:= ControlState - [csCustomPaint];
  549. end;
  550. (*************************************************************)
  551. procedure TAbstractOpenGL.DestroyWindowHandle;
  552. Begin
  553.   GLShutDown;
  554.   //close the GL render session
  555.   Inherited DestroyWindowHandle;
  556. end;
  557. (*************************************************************)
  558. Procedure TAbstractOpenGL.GLLock;
  559.    Begin
  560.      EnterCriticalSection(fGLLock);
  561.    end;
  562. (*************************************************************)
  563. Procedure TAbstractOpenGL.GLUnLock;
  564.   begin
  565.     LeaveCriticalSection(fGLLock);
  566.  end;
  567. (******* ******************************************************)
  568. procedure TAbstractOpenGL.Repaint;
  569.  Var aRect,WinRect:TRect;
  570.      aErase,UpdateB:Boolean;
  571. Begin
  572.   fValidBuffer    :=False;
  573.   fRepaintNeeded  :=true;
  574.   aErase:=False;
  575.  // does a small area need redrawing
  576.   UpdateB:=GetUpdateRect(Handle,aRect,aErase);
  577.   SetRectEmpty(WinRect);
  578.   With WinRect do
  579.    Begin
  580.     Right:=Width;Bottom:=Height;
  581.    end;
  582.  
  583.   fRebuildNeeded  :=True;
  584.  
  585.   If not EqualRect(aRect,WinRect)and UpDateB then
  586.     Begin
  587.      // only a small area needs redrawing not finished
  588.      {glScissor}
  589.      Invalidate;
  590.      update;
  591.     end else
  592.     Begin
  593.       Invalidate;
  594.       Update;
  595.     end;
  596. end;
  597. (*************************************************************)
  598. procedure TAbstractOpenGL.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  599. begin
  600.   Message.Result := 1;
  601. end;
  602. (*************************************************************)
  603. procedure TAbstractOpenGL.WMSetFocus(var Message: TWMSetFocus);
  604.  begin
  605.   inherited;
  606.   If fCloseGL and (fHRC=0) then GLStartUp;
  607.   EnableGL;
  608.   RePaint;
  609.  end;
  610. (*************************************************************)
  611. procedure TAbstractOpenGL.WMKillFocus(var Message: TWMSetFocus);
  612. begin
  613.   inherited;
  614.   DoMoveTidyUp;
  615.   RePaint;
  616.   DisableGL;
  617.   If fCloseGL then GLShutDown;
  618. end;
  619. (*************************************************************)
  620. procedure TAbstractOpenGL.CMMouseEnter(var Message: TMessage);
  621. begin
  622.   inherited;
  623.   If canFocus and not focused and fGrabFocus then SetFocus;
  624.   // used to automatically grab the focus if the mouse passes over
  625. end;
  626. (*************************************************************)
  627. procedure TAbstractOpenGL.CMShowingChanged(var Message: TMessage);
  628. begin
  629.   Inherited;
  630.   if not fDoneGLSetup then
  631.     Begin
  632.       GLStartUp;
  633.       fValidBuffer:=False;
  634.       fRebuildNeeded:=True;        //need to rebuild ie rerender
  635.       fRepaintNeeded:=True;        // only need to repaint ie swap buffer if valid
  636.       fDoneGLSetup:=True;
  637.     end;
  638. end;
  639. (*************************************************************)
  640.  procedure TAbstractOpenGL.InvalidateRectangle(Rect:TRect;DoRepaint:Boolean);
  641.     // will invalidate only the given rectangle area of the control will concatinate with
  642.     // existing update if already there
  643.  Var CRect,OutRect:tRect;
  644.      aErase:Boolean;
  645.  Begin
  646.   CopyRect(OutRect,Rect);
  647.   aErase:=False;
  648.   If GetUpdateRect(Handle,CRect,aErase) then IntersectRect(OutRect,CRect,Rect);
  649.   if HandleAllocated then
  650.    begin
  651.     if Parent <> nil then Parent.Perform(CM_INVALIDATE, 1, 0);
  652.     InvalidateRect(Handle, @OutRect, not (csOpaque in ControlStyle));
  653.     If DoRepaint then Repaint;
  654.    end;
  655.  end;
  656. (*************************************************************)
  657. Function TAbstractOpenGL.EnableGL:Boolean;
  658. {Ensures that the windows DC and RC and active}
  659.  var TempRC:HGLRC;
  660.      TempDC:HDC;
  661.  Begin
  662.   Result:=False;
  663. // normal window
  664.   If (fRenderDC=0) or (fHRC=0) then exit;
  665.   TempRC:= wglGetCurrentContext;
  666.   TempDC:= wglGetCurrentDC;
  667.   If (TempRC<>fHRC) or (TempDC<>fRenderDC) then
  668.      Result:=wglMakeCurrent(fRenderDC,fHRC) else
  669.      Result:=True;
  670.  {$IFDEF ERRORDEBUG}
  671.   If not Result then
  672.     MessageDlg('Problem with OpenGL Session',mtInformation,[mbOk],0);
  673.  {$ENDIF}
  674.  end;
  675. (*************************************************************)
  676.  Procedure TAbstractOpenGL.DisableGL;
  677.    //Turn off the GL Session
  678.    Begin
  679.     If (wglGetCurrentContext=fHRC)then wglMakeCurrent(0,0);
  680.    end;
  681. (*************************************************************)
  682. Function TAbstractOpenGL.IsGLActive:Boolean;
  683.     {Is the current }
  684.   Begin
  685.     Result:=False;
  686.     If (fRenderDC=0) or (fHRC=0) then exit;
  687.     Result:= (wglGetCurrentContext=fHRC) AND (wglGetCurrentDC=fRenderDC);
  688.   end;
  689. (*************************************************************)
  690.  Procedure TAbstractOpenGL.SetGrabFocus(Val:Boolean);
  691.    Begin
  692.      fGrabFocus:=Val;
  693.    end;
  694. (*************************************************************)
  695. Procedure TAbstractOpenGL.setShareGLWin(Val: TAbstractOpenGL);
  696.   Begin
  697.      If Val = fShareGL then exit;
  698.      fShareGL:=Val;
  699.      If fHRC=0 then exit;
  700.      GLShutDown;
  701.      GLStartUp;
  702.   end;
  703. (******************************************************)
  704.  Procedure TAbstractOpenGL.SaveState(aState:GLSaveState);
  705.     // save the current state before mods restore state will reset
  706.   Begin
  707.     Case aState of
  708.       stAll      :glPushAttrib(GL_ALL_ATTRIB_BITS);
  709.       stDrawing  :glPushAttrib(GL_ENABLE_BIT or GL_LINE_BIT or GL_POINT_BIT or GL_POLYGON_BIT
  710.                                 or GL_CURRENT_BIT or GL_HINT_BIT or GL_SCISSOR_BIT);
  711.       stLighting :glPushAttrib(GL_LIGHTING_BIT);
  712.       stTexturing:glPushAttrib(GL_TEXTURe_BIT);
  713.     end;
  714.   end;
  715. (******************************************************)
  716.  Procedure TAbstractOpenGL.RestoreState;
  717.       Begin
  718.         glPopAttrib;
  719.       end;
  720. (*************************************************************)
  721.  Procedure TAbstractOpenGL.SetGenericGDI(AVal:Boolean);
  722.   // set the GDI use state
  723.   Begin
  724.     If aVal=fGDIGeneric then exit;
  725.     fGDIGeneric:=aVal;
  726.     Repaint;
  727.   end;
  728. (******* ******************************************************)
  729. (*************************************************************)
  730. constructor TAbstractOpenGLBitmap.CreateInit(aBitMap:tBitMap;aBack:GLBackground);
  731. Begin
  732.   Inherited Create;
  733.   fBitMap:=aBitMap;
  734.   fBackColor:=aBack;
  735.   GLStartUp;
  736. end;
  737. (*************************************************************)
  738. Destructor TAbstractOpenGLBitmap.Destroy;
  739. Begin
  740.   GLShutDown;
  741.   Inherited Destroy;
  742. end;
  743. (******* ******************************************************)
  744. Procedure TAbstractOpenGLBitmap.GLStartUp;
  745.  Var  CompDC:HDC;
  746.       TempBM:hBitMap;
  747.   // Startn up the GLSession
  748.   Begin
  749.     iF Not Assigned(fBitMap) then exit;
  750.     fRenderDC:=fBitMap.Canvas.Handle;
  751.     fHRC:=0;
  752.     If SetUpPixelFormat then fHRC:=wglCreateContext(fRenderDC)
  753.      else
  754.      Begin
  755.        CompDC:=CreateCompatibleDC(0);
  756.        TempBM:=CreateCompatibleBitMap(CompDC,fBitMap.Width,fBitMap.Height);
  757.        If (CompDC<>0) and (TempBM<>0) then
  758.          SelectObject(CompDC,TempBM);
  759.        fBitmap.Handle:=TempBM;
  760.        fRenderDC:=CompDC;
  761.        If SetUpPixelFormat then fHRC:=wglCreateContext(fRenderDC)
  762.         else exit;
  763.      end;
  764.     If fHRC<>0 then
  765.      If wglMakeCurrent(fRenderDC,fHRC) then
  766.       Begin
  767.           If fBackColor=glWhiteBkgd then
  768.             glClearColor(1.0,1.0,1.0,1.0)
  769.           else
  770.             glClearColor(0.0,0.0,0.0,1.0);
  771.           glClearIndex(0.0);
  772.           glClearDepth(1.0);
  773.           glPixelStorei(GL_Unpack_Alignment,1);
  774.             //specific for windows and byte alignment
  775.           glDisable(GL_SCISSOR_TEST);
  776.           glDisable(GL_BLEND);
  777.           glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  778.           glfinish;
  779.  
  780.           fAllOK:=True;
  781.      end;
  782.   end;
  783. (******* ******************************************************)
  784. Procedure TAbstractOpenGLBitmap.GLShutDown;
  785.   // Shut down a session
  786.   Begin
  787.      If (wglGetCurrentContext=fHRC) then  wglMakeCurrent(fRenderDC,0);
  788.      // if the current Rendering context is this one then make NOT current
  789.      If fHRC<>0 then
  790.        Begin
  791.          wglDeleteContext(fHRC);
  792.      // delete the Rendering Context
  793.          fHRC:=0;
  794.        end;
  795.      If fGLPalette<>0 then
  796.        Begin
  797.          DeleteObject(fGLPalette);
  798.      // delete the Palette if used
  799.          fGLPalette:=0;
  800.        end;
  801.   end;
  802. (******* ******************************************************)
  803. Function TAbstractOpenGLBitmap.SetUpPixelFormat:Boolean;
  804.  
  805. { If necessary, creates a 3-3-2 palette for the device context listed.}
  806.           Procedure GetOpenGLPalette;
  807.           Var
  808.             pPal:^TLogPalette;        {Pointer to memory for logical palette}
  809.             nColors:Integer;        { Number of entries in palette}
  810.             i      :Integer;               { Counting variable }
  811.             RedRange,GreenRange,BlueRange:BYTE;{ Range for each color entry (7,7,and 3)}
  812.             MultVal:Byte;
  813.             aVal:Byte;
  814.           Begin
  815.             { Get the pixel format index and retrieve the pixel format description}
  816.             DescribePixelFormat(frenderDC, fPixelFormat, sizeof(TPIXELFORMATDESCRIPTOR), faPPfd);
  817.              { Does this pixel format require a palette?  If not, do not create a}
  818.              { palette and just return NULL}
  819.             if not(PFD_NEED_PALETTE = (faPPfd.dwFlags and PFD_NEED_PALETTE)) then exit;
  820.              { Number of entries in palette.  8 bits yeilds 256 entries}
  821.             nColors := 1 shl faPPfd.cColorbits{1 << pfd.cColorBits};
  822.           { Allocate space for a logical palette structure plus all the palette entries}
  823.             GetMem(pPal,SizeOf(TLogPalette)+nColors*sizeOf(TpaletteEntry));
  824.           { Fill in palette header}
  825.             pPal^.palVersion := $300;        { Windows 3.0}
  826.             pPal^.palNumEntries := nColors; { table size }
  827.  
  828.                   { Build mask of all 1's.  This creates a number represented by having
  829.                   { the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
  830.                   { pfd.cBlueBits. }
  831.             RedRange   := (1 shl faPPfd.cRedBits)-1{(1 << pfd.cRedBits) -1};
  832.             GreenRange :=( 1 shl faPPfd.cGreenBits)-1 {(1 << pfd.cGreenBits) - 1};
  833.             BlueRange  := (1 shl faPPfd.cBlueBits)-1{(1 << pfd.cBlueBits) -1};
  834.             MultVal:=255;
  835.                   { Loop through all the palette entries}
  836.           {$R-}
  837.             For i:=0 to nColors-1 do
  838.               With pPal^ do Begin
  839.                 AVal:=   (i shr faPPfd.cRedShift) and RedRange;
  840.                 aVal:=   aVal*MultVal div RedRange;
  841.                 palPalEntry[i].peRed:=aVal;
  842.                 aVal:= (i shr faPPfd.cGreenshift) and GreenRange;
  843.                 aVal:= aVal*MultVal div GreenRange;
  844.                 palPalEntry[i].peGreen:=aVal;
  845.                 aVal:=  (i shr faPPfd.cBlueShift) and BlueRange;
  846.                 aVal:=  aVal*MultVal div BlueRange;
  847.                 palPalEntry[i].peBlue:=aVal;
  848.                 palPalEntry[i].peFlags := 0;
  849.                end;
  850.                   { Create the palette}
  851.           {R+}
  852.             fGLPalette := CreatePalette(pPal^);
  853.  
  854.                   { Free the memory used for the logical palette structure}
  855.             FreeMem(pPal,SizeOf(TLogPalette)+nColors*sizeOf(TpaletteEntry));
  856.           end;
  857. Begin
  858.   Result:=False;
  859.   fGLPalette:=0;
  860.   If fRenderDC=0 then exit;
  861.   FillChar(fAPPFD,SizeOf(fAPPFD),0);//set values to zero
  862.   With fAPPFD do
  863.   Begin
  864.     nSize:=SizeOf(fAPPFD);
  865.     nVersion:=1;
  866.     dwFlags:=(PFD_Draw_To_Window or
  867.               PFD_Draw_To_BitMap or
  868.               PFD_SUPPORT_GDI or
  869.               Pfd_Support_OpenGL);
  870.     iPixelType:=PFD_TYPE_RGBA;
  871.     cColorBits:=24;  //24 bit color for bitmaps
  872.     cDepthBits:=16;
  873.     cStencilBits:=1;
  874.     cAccumBits:=0;
  875.     cAlphaBits:=0;
  876.     cAuxBuffers:=0;
  877.     iLayerType:=PFD_Main_Plane;
  878.   end;
  879.   fPixelFormat:=ChoosePixelFormat(fRenderDC,@fAPPFD);
  880.   Result:=SetPixelFormat(fRenderDC,fPixelFormat,@faPPFD);
  881.   fPixelFormat:=GetPixelFormat(fRenderDC);
  882.   If Result then
  883.    Begin
  884.       { Get the pixel format index and retrieve the pixel format description}
  885.        if (PFD_NEED_PALETTE = (faPPfd.dwFlags and PFD_NEED_PALETTE)) then
  886.        Begin
  887.          { Go ahead and select and realize the palette for this device context}
  888.          If fGLPalette=0 then GetOpenGLPalette;
  889.          SelectPalette(fRenderDC,fGLPalette,FALSE);
  890.          RealizePalette(fRenderDC);
  891.        end;
  892.      //  if (PFD_NEED_PALETTE = (faPPfd.dwFlags and INSTALLABLE_DRIVER_TYPE_MASK)) then
  893.    end;
  894.   end;
  895. (*************************************************************)
  896.  Function TAbstractOpenGLBitmap.GetCanvas:TCanvas;
  897.   Begin
  898.     Result:=fBitMap.Canvas;
  899.   end;
  900. (*************************************************************)
  901. (*************************************************************)
  902.  
  903.  end.
  904.