mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 06:21:38 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			256 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|  *****************************************************************************
 | |
|  *                                                                           *
 | |
|  *  See the file COPYING.modifiedLGPL.txt, included in this distribution,    *
 | |
|  *  for details about the copyright.                                         *
 | |
|  *                                                                           *
 | |
|  *  This program is distributed in the hope that it will be useful,          *
 | |
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 | |
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
 | |
|  *                                                                           *
 | |
|  *****************************************************************************
 | |
| 
 | |
|   Author: Mattias Gaertner
 | |
| 
 | |
| }
 | |
| unit GLQTContext;
 | |
| 
 | |
| {$mode objfpc}{$H+}
 | |
| {$LinkLib GL}
 | |
| {$PACKRECORDS C}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   Classes, SysUtils, Controls, LCLProc, LCLType, X, XUtil, XLib, gl,
 | |
|   InterfaceBase,
 | |
|   WSLCLClasses,
 | |
|   // Bindings
 | |
|   qt4,
 | |
|   qtwidgets, qtobjects, qtproc, qtint,
 | |
|   QtWSControls;
 | |
| 
 | |
| // gdkgl
 | |
| 
 | |
| const
 | |
| // enum _QT_GL_CONFIGS
 | |
|   QT_GL_NONE                           = 0;
 | |
|   QT_GL_USE_GL                         = 1;
 | |
|   QT_GL_BUFFER_SIZE                    = 2;
 | |
|   QT_GL_LEVEL                          = 3;
 | |
|   QT_GL_RGBA                           = 4;
 | |
|   QT_GL_DOUBLEBUFFER                   = 5;
 | |
|   QT_GL_STEREO                         = 6;
 | |
|   QT_GL_AUX_BUFFERS                    = 7;
 | |
|   QT_GL_RED_SIZE                       = 8;
 | |
|   QT_GL_GREEN_SIZE                     = 9;
 | |
|   QT_GL_BLUE_SIZE                      = 10;
 | |
|   QT_GL_ALPHA_SIZE                     = 11;
 | |
|   QT_GL_DEPTH_SIZE                     = 12;
 | |
|   QT_GL_STENCIL_SIZE                   = 13;
 | |
|   QT_GL_ACCUM_RED_SIZE                 = 14;
 | |
|   QT_GL_ACCUM_GREEN_SIZE               = 15;
 | |
|   QT_GL_ACCUM_BLUE_SIZE                = 16;
 | |
|   QT_GL_ACCUM_ALPHA_SIZE               = 17;
 | |
| 
 | |
|   // GLX_EXT_visual_info extension
 | |
|   QT_GL_X_VISUAL_TYPE_EXT              = $22;
 | |
|   QT_GL_TRANSPARENT_TYPE_EXT           = $23;
 | |
|   QT_GL_TRANSPARENT_INDEX_VALUE_EXT    = $24;
 | |
|   QT_GL_TRANSPARENT_RED_VALUE_EXT      = $25;
 | |
|   QT_GL_TRANSPARENT_GREEN_VALUE_EXT    = $26;
 | |
|   QT_GL_TRANSPARENT_BLUE_VALUE_EXT     = $27;
 | |
|   QT_GL_TRANSPARENT_ALPHA_VALUE_EXT    = $28;
 | |
| 
 | |
| type
 | |
|   TGLXContext = pointer;
 | |
| 
 | |
| procedure LOpenGLViewport(Left, Top, Width, Height: integer);
 | |
| procedure LOpenGLSwapBuffers(Handle: HWND);
 | |
| function LOpenGLMakeCurrent(Handle: HWND): boolean;
 | |
| function LOpenGLCreateContext(AWinControl: TWinControl;
 | |
|              WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
 | |
|              DoubleBuffered, RGBA: boolean;
 | |
|              const AParams: TCreateParams): HWND;
 | |
| procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
 | |
| function CreateOpenGLContextAttrList(DoubleBuffered: boolean;
 | |
|                                      RGBA: boolean): PInteger;
 | |
| 
 | |
| implementation
 | |
| 
 | |
| type
 | |
|   //PGLXPixmap = ^GLXPixmap;
 | |
|   GLXPixmap = TXID;
 | |
| 
 | |
|   //PGLXDrawable = ^GLXDrawable;
 | |
|   GLXDrawable = TXID;
 | |
| 
 | |
| { GLX 1.0 functions. }
 | |
| 
 | |
| function glXChooseVisual(dpy:PDisplay; screen:longint; attrib_list:Plongint):PXVisualInfo;cdecl;external;
 | |
| procedure glXCopyContext(dpy:PDisplay; src:TGLXContext; dst:TGLXContext; mask: cardinal);cdecl;external;
 | |
| function glXCreateContext(dpy:PDisplay; vis:PXVisualInfo; share_list:TGLXContext; direct:TBool):TGLXContext;cdecl;external;
 | |
| function glXCreateGLXPixmap(dpy:PDisplay; vis:PXVisualInfo; pixmap:TPixmap):GLXPixmap;cdecl;external;
 | |
| procedure glXDestroyContext(dpy:PDisplay; ctx:TGLXContext);cdecl;external;
 | |
| procedure glXDestroyGLXPixmap(dpy:PDisplay; pix:GLXPixmap);cdecl;external;
 | |
| function glXGetConfig(dpy:PDisplay; vis:PXVisualInfo; attrib:longint; value:Plongint):longint;cdecl;external;
 | |
| function glXGetCurrentContext:TGLXContext;cdecl;external;
 | |
| function glXGetCurrentDrawable:GLXDrawable;cdecl;external;
 | |
| function glXIsDirect(dpy:PDisplay; ctx:TGLXContext):TBool;cdecl;external;
 | |
| function glXMakeCurrent(dpy:PDisplay; drawable:GLXDrawable; ctx:TGLXContext):TBool;cdecl;external;
 | |
| function glXQueryExtension(dpy:PDisplay; error_base:Plongint; event_base:Plongint):TBool;cdecl;external;
 | |
| function glXQueryVersion(dpy:PDisplay; major:Plongint; minor:Plongint):TBool;cdecl;external;
 | |
| procedure glXSwapBuffers(dpy:PDisplay; drawable:GLXDrawable);cdecl;external;
 | |
| procedure glXUseXFont(font:TFont; first:longint; count:longint; list_base:longint);cdecl;external;
 | |
| procedure glXWaitGL;cdecl;external;
 | |
| procedure glXWaitX;cdecl;external;
 | |
| 
 | |
| function XVisualAsString(AVisual: PVisual): string;
 | |
| begin
 | |
|   if AVisual=nil then begin
 | |
|     Result:='nil';
 | |
|   end else begin
 | |
|     Result:=''
 | |
|         +' bits_per_rgb='+dbgs(AVisual^.bits_per_rgb)
 | |
|         +' red_mask='+hexstr(AVisual^.red_mask,8)
 | |
|         +' green_mask='+hexstr(AVisual^.green_mask,8)
 | |
|         +' blue_mask='+hexstr(AVisual^.blue_mask,8)
 | |
|         +' map_entries='+dbgs(AVisual^.map_entries)
 | |
|         +'';
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function XDisplayAsString(ADisplay: PDisplay): string;
 | |
| begin
 | |
|   if ADisplay=nil then begin
 | |
|     Result:='nil';
 | |
|   end else begin
 | |
|     Result:=''
 | |
|         +'';
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| type
 | |
| 
 | |
|   { TQtGLWidget }
 | |
| 
 | |
|   TQtGLWidget = class(TQtWidget)
 | |
|   public
 | |
|     xdisplay: PDisplay;
 | |
|     visual: PXVisualInfo;
 | |
|     glxcontext: TGLXContext;
 | |
|     ref_count: integer;
 | |
|     function GetGLXDrawable: GLXDrawable;
 | |
|   end;
 | |
| 
 | |
| { TQtGLWidget }
 | |
| 
 | |
| function TQtGLWidget.GetGLXDrawable: GLXDrawable;
 | |
| begin
 | |
|   Result:=0; {$ERROR ToDo: get GLXDrawable}
 | |
| end;
 | |
| 
 | |
| procedure LOpenGLViewport(Left, Top, Width, Height: integer);
 | |
| begin
 | |
|   glViewport(Left,Top,Width,Height);
 | |
| end;
 | |
| 
 | |
| procedure LOpenGLSwapBuffers(Handle: HWND);
 | |
| var
 | |
|   Widget: TQtGLWidget;
 | |
| begin
 | |
|   if Handle=0 then
 | |
|     RaiseGDBException('LOpenGLSwapBuffers Handle=0');
 | |
| 
 | |
|   Widget:=TQtGLWidget(Handle);
 | |
|   glXSwapBuffers(Widget.xdisplay,
 | |
|                  Widget.GetGLXDrawable
 | |
|                  );
 | |
| end;
 | |
| 
 | |
| function LOpenGLMakeCurrent(Handle: HWND): boolean;
 | |
| var
 | |
|   Widget: TQtGLWidget;
 | |
| begin
 | |
|   if Handle=0 then
 | |
|     RaiseGDBException('LOpenGLSwapBuffers Handle=0');
 | |
|   Result:=false;
 | |
| 
 | |
|   Widget:=TQtGLWidget(Handle);
 | |
|   Result:=boolean(glXMakeCurrent(Widget.xdisplay,
 | |
|                                  Widget.GetGLXDrawable,
 | |
|                                  Widget.glxcontext));
 | |
| end;
 | |
| 
 | |
| function LOpenGLCreateContext(AWinControl: TWinControl;
 | |
|   WSPrivate: TWSPrivateClass; SharedControl: TWinControl; DoubleBuffered,
 | |
|   RGBA: boolean; const AParams: TCreateParams): HWND;
 | |
| var
 | |
|   AttrList: PInteger;
 | |
|   NewQtWidget: TQtGLWidget;
 | |
|   direct: TBool;
 | |
| begin
 | |
|   if WSPrivate=nil then ;
 | |
|   AttrList:=CreateOpenGLContextAttrList(DoubleBuffered,RGBA);
 | |
|   try
 | |
|     NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
 | |
|     NewQtWidget.xdisplay := QX11Info_display;
 | |
|     NewQtWidget.visual:=glXChooseVisual(NewQtWidget.xdisplay,
 | |
|       DefaultScreen(NewQtWidget.xdisplay), @attrList[0]);
 | |
|     direct:=0;
 | |
|     NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
 | |
|                                                NewQtWidget.visual, nil, direct);
 | |
|     NewQtWidget.ref_count := 1;
 | |
| 
 | |
|     NewQtWidget.AttachEvents;
 | |
| 
 | |
|     Result:=HWND(PtrUInt(Pointer(NewQtWidget)));
 | |
|   finally
 | |
|     FreeMem(AttrList);
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
 | |
| begin
 | |
|   if not AWinControl.HandleAllocated then exit;
 | |
|   // nothing to do
 | |
| end;
 | |
| 
 | |
| function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean
 | |
|   ): PInteger;
 | |
| var
 | |
|   p: integer;
 | |
| 
 | |
|   procedure Add(i: integer);
 | |
|   begin
 | |
|     if Result<>nil then
 | |
|       Result[p]:=i;
 | |
|     inc(p);
 | |
|   end;
 | |
| 
 | |
|   procedure CreateList;
 | |
|   begin
 | |
|     if DoubleBuffered then
 | |
|       Add(QT_GL_DOUBLEBUFFER);
 | |
|     if RGBA then
 | |
|       Add(QT_GL_RGBA);
 | |
|     Add(QT_GL_RED_SIZE);  Add(1);
 | |
|     Add(QT_GL_GREEN_SIZE);  Add(1);
 | |
|     Add(QT_GL_BLUE_SIZE);  Add(1);
 | |
|     Add(QT_GL_DEPTH_SIZE);  Add(1);
 | |
|     Add(QT_GL_STENCIL_SIZE); Add(1);
 | |
|     Add(QT_GL_None);
 | |
|   end;
 | |
| 
 | |
| begin
 | |
|   Result:=nil;
 | |
|   p:=0;
 | |
|   CreateList;
 | |
|   GetMem(Result,SizeOf(integer)*p);
 | |
|   p:=0;
 | |
|   CreateList;
 | |
| end;
 | |
| 
 | |
| end.
 | |
| 
 | 
