mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 03:37:54 +02:00
591 lines
19 KiB
ObjectPascal
591 lines
19 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Author: Mattias Gaertner
|
|
|
|
}
|
|
unit GLQTContext;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$LinkLib GL}
|
|
{$PACKRECORDS C}
|
|
{$DEFINE ModernGL}
|
|
//{$DEFINE VerboseMultiSampling}
|
|
interface
|
|
|
|
uses
|
|
// Classes, SysUtils, ctypes, LCLProc, LCLType, X, XUtil, XLib, gl,
|
|
//InterfaceBase,
|
|
//glx,
|
|
//WSLCLClasses,
|
|
{$IFDEF ModernGL} ctypes,{$ENDIF}
|
|
Classes, SysUtils, Types, Controls, LCLProc, LCLType, X, XUtil, XLib, gl,
|
|
InterfaceBase,
|
|
WSLCLClasses,glx,
|
|
// Bindings
|
|
{$IFDEF LCLQt}qt4,{$ENDIF}
|
|
{$IFDEF LCLQt5}qt5, qlclopenglwidget,{$ENDIF}
|
|
{$IFDEF LCLQt6}qt6, qlclopenglwidget,{$ENDIF}
|
|
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(Handle: HWND; Left, Top, Width, Height: integer);
|
|
procedure LOpenGLSwapBuffers(Handle: HWND);
|
|
function LOpenGLMakeCurrent(Handle: HWND): boolean;
|
|
function LOpenGLReleaseContext(Handle: HWND): boolean;
|
|
function LOpenGLCreateContext(AWinControl: TWinControl;
|
|
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
|
|
DoubleBuffered, RGBA: boolean;
|
|
const RedBits, GreenBits, BlueBits, MajorVersion, MinorVersion,
|
|
MultiSampling, AlphaBits, DepthBits, StencilBits, AUXBuffers: Cardinal;
|
|
const AParams: TCreateParams): HWND;
|
|
|
|
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
|
|
function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
|
|
const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits,
|
|
StencilBits, AUXBuffers, MultiSampling: Cardinal): PInteger;
|
|
|
|
|
|
implementation
|
|
uses LMessages, Forms;
|
|
|
|
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({$IF DEFINED(LCLQt5) OR DEFINED(LCLQt6)}TQtOpenGLWidget{$ELSE}TQtWidget{$ENDIF})
|
|
protected
|
|
function PaintGLControl(Sender: QObjectH; Event: QEventH): boolean; cdecl;
|
|
{$IF DEFINED(LCLQt5) OR DEFINED(LCLQt6)}
|
|
procedure paintGL(); cdecl; override;
|
|
{$ENDIF}
|
|
public
|
|
xdisplay: PDisplay;
|
|
visual: PXVisualInfo;
|
|
glxcontext: TGLXContext;
|
|
ref_count: integer;
|
|
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; override;
|
|
function GetGLXDrawable: GLXDrawable;
|
|
end;
|
|
|
|
{ TQtGLWidget }
|
|
|
|
function TQtGLWidget.PaintGLControl(Sender: QObjectH; Event: QEventH): boolean;
|
|
cdecl;
|
|
var
|
|
Msg: TLMPaint;
|
|
AStruct: PPaintStruct;
|
|
B: Boolean;
|
|
begin
|
|
Result := False;
|
|
QEvent_accept(Event);
|
|
if CanSendLCLMessage and (LCLObject is TWinControl) then
|
|
begin
|
|
FillChar(Msg{%H-}, SizeOf(Msg), #0);
|
|
|
|
Msg.Msg := LM_PAINT;
|
|
New(AStruct);
|
|
try
|
|
try
|
|
FillChar(AStruct^, SizeOf(TPaintStruct), 0);
|
|
// QWidget_geometry(Widget, @AStruct^.rcPaint);
|
|
QPaintEvent_rect(QPaintEventH(Event), @AStruct^.rcPaint);
|
|
AStruct^.hdc := PtrUInt(Self.glxcontext); // HDC(QOpenGLWidget_context(QOpenGLWidgetH(Sender)));
|
|
Msg.PaintStruct := AStruct;
|
|
|
|
Msg.DC := AStruct^.hdc;
|
|
LCLObject.WindowProc(TLMessage(Msg));
|
|
|
|
QEvent_ignore(Event);
|
|
Result := True; {let Qt finish}
|
|
finally
|
|
Dispose(AStruct);
|
|
end;
|
|
except
|
|
// prevent recursive repainting !
|
|
B := (Sender <> nil) and QtWidgetSet.IsValidHandle(HWND(Self));
|
|
if B then
|
|
QWidget_setUpdatesEnabled(QWidgetH(Sender), False);
|
|
try
|
|
Application.HandleException(nil);
|
|
finally
|
|
if B and Assigned(Application) and not Application.Terminated then
|
|
QWidget_setUpdatesEnabled(QWidgetH(Sender), True);
|
|
end;
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
DebugLn('TQtGLWidget.PaintGLControl error CanSendLCLMessage=',dbgs(CanSendLCLMessage),' LCLObject=',dbgsName(LCLObject));
|
|
end;
|
|
end;
|
|
|
|
{$IF DEFINED(LCLQt5) OR DEFINED(LCLQt6)}
|
|
procedure TQtGLWidget.paintGL(); cdecl;
|
|
var
|
|
AEvent: QPaintEventH;
|
|
ARect: TRect;
|
|
begin
|
|
QWidget_rect(Widget, @ARect);
|
|
AEvent := QPaintEvent_Create(PRect(@ARect));
|
|
PaintGLControl(Widget, AEvent);
|
|
QPaintEvent_Destroy(AEvent);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
function TQtGLWidget.EventFilter(Sender: QObjectH; Event: QEventH): Boolean;
|
|
cdecl;
|
|
begin
|
|
Result := False;
|
|
if QEvent_type(Event) = QEventPaint then
|
|
begin
|
|
{$IFDEF LCLQt}
|
|
PaintGLControl(Sender, Event);
|
|
{$ENDIF}
|
|
end else
|
|
Result := inherited EventFilter(Sender, Event);
|
|
end;
|
|
|
|
function TQtGLWidget.GetGLXDrawable: GLXDrawable;
|
|
begin
|
|
result := QWidget_winID(Widget);
|
|
end;
|
|
|
|
procedure LOpenGLViewport(Handle: HWND; 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:=glXMakeCurrent(Widget.xdisplay,
|
|
Widget.GetGLXDrawable,
|
|
Widget.glxcontext);
|
|
end;
|
|
|
|
function LOpenGLReleaseContext(Handle: HWND): boolean;
|
|
var
|
|
Widget: TQtGLWidget;
|
|
begin
|
|
Result := false;
|
|
if Handle=0 then
|
|
RaiseGDBException('LOpenGLSwapBuffers Handle=0');
|
|
|
|
Widget:=TQtGLWidget(Handle);
|
|
Result := glXMakeCurrent(Widget.xdisplay, 0, nil);
|
|
end;
|
|
|
|
{$IFDEF ModernGL}
|
|
function CustomXErrorHandler({%H-}para1:PDisplay; para2:PXErrorEvent):cint;cdecl;
|
|
begin
|
|
if para2^.error_code=8 then begin
|
|
raise Exception.Create('A BadMatch X error occurred. Most likely the requested OpenGL version is invalid.');
|
|
end;
|
|
Result:=0;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
type
|
|
TContextAttribs = record
|
|
AttributeList: PLongint;
|
|
MajorVersion: Cardinal;
|
|
MinorVersion: Cardinal;
|
|
MultiSampling: Cardinal;
|
|
ContextFlags: Cardinal;
|
|
end;
|
|
|
|
{function LOpenGLCreateContext(AWinControl: TWinControl;
|
|
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
|
|
DoubleBuffered, RGBA: boolean;
|
|
const MultiSampling, AlphaBits, DepthBits, StencilBits: Cardinal;
|
|
const AParams: TCreateParams): HWND;}
|
|
function LOpenGLCreateContext(AWinControl: TWinControl;
|
|
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
|
|
DoubleBuffered, RGBA: boolean;
|
|
const RedBits, GreenBits, BlueBits, MajorVersion, MinorVersion,
|
|
MultiSampling, AlphaBits, DepthBits, StencilBits, AUXBuffers: Cardinal;
|
|
const AParams: TCreateParams): HWND;
|
|
var
|
|
{$IFDEF ModernGL} { Used with glXCreateContextAttribsARB to select 3.X and above context }
|
|
Context3X: array [0..6] of Integer;
|
|
ScreenNum: cint;
|
|
FBConfig: TGLXFBConfig;
|
|
FBConfigs: PGLXFBConfig;
|
|
FBConfigsCount: Integer;
|
|
i: Integer;
|
|
Samples: cint;
|
|
BestSamples: Integer;
|
|
BestFBConfig: Integer;
|
|
XVInfo: PXVisualInfo;
|
|
XDisplay: PDisplay;
|
|
{$ENDIF}
|
|
AttrList: TContextAttribs;
|
|
NewQtWidget: TQtGLWidget;
|
|
direct: boolean;
|
|
{$IF DEFINED(LCLQt5) OR DEFINED(LCLQt6)}
|
|
AWinFormat: QSurfaceFormatH;
|
|
{$ENDIF}
|
|
{$IFDEF VerboseMultiSampling}
|
|
samp_buf, visual_id, red_size, blue_size, green_size, alpha_size: integer;
|
|
{$ENDIF}
|
|
SharedContext: TGLXContext;
|
|
begin
|
|
if WSPrivate=nil then ;
|
|
AttrList.AttributeList := CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers, MultiSampling);
|
|
try
|
|
NewQtWidget:=TQtGLWidget.Create(AWinControl,AParams);
|
|
{$ifdef LCLQt}
|
|
NewQtWidget.setAttribute(QtWA_PaintOnScreen);
|
|
NewQtWidget.setAttribute(QtWA_NoSystemBackground);
|
|
NewQtWidget.setAttribute(QtWA_OpaquePaintEvent);
|
|
{$endif}
|
|
NewQtWidget.HasPaint := false;
|
|
{$IFDEF LCLQt6}
|
|
NewQtWidget.xdisplay := QtWidgetSet.x11Display;
|
|
{$ELSE}
|
|
NewQtWidget.xdisplay := QX11Info_display;
|
|
{$ENDIF}
|
|
NewQtWidget.visual := glXChooseVisual(NewQtWidget.xdisplay,
|
|
DefaultScreen(NewQtWidget.xdisplay), @attrList.AttributeList[0]);
|
|
direct := false;
|
|
{$IF DEFINED(LCLQt5) OR DEFINED(LCLQt6)}
|
|
QWindow_setSurfaceType(QWidget_windowHandle(NewQtWidget.Widget), QSurfaceSurfaceTypeOpenGLSurface);
|
|
|
|
AWinFormat := QSurfaceFormat_Create();
|
|
|
|
if MajorVersion > 0 then
|
|
begin
|
|
QSurfaceFormat_setMajorVersion(AWinFormat, MajorVersion);
|
|
QSurfaceFormat_setMinorVersion(AWinFormat, MinorVersion);
|
|
end;
|
|
|
|
if DoubleBuffered then
|
|
QSurfaceFormat_setSwapBehavior(AWinFormat, QSurfaceSwapBehaviorDoubleBuffer);
|
|
QSurfaceFormat_setSamples(AWinFormat, Integer(MultiSampling));
|
|
QSurfaceFormat_setDepthBufferSize(AWinFormat, DepthBits);
|
|
QSurfaceFormat_setStencilBufferSize(AWinFormat, Integer(StencilBits));
|
|
QSurfaceFormat_setRenderableType(AWinFormat, QSurfaceFormatRenderableTypeOpenGL);
|
|
QSurfaceFormat_setAlphaBufferSize(AWinFormat, AlphaBits);
|
|
QWindow_destroyPlatformResources(QWidget_windowHandle(NewQtWidget.Widget));
|
|
QWindow_setFormat(QWidget_windowHandle(NewQtWidget.Widget), AWinFormat);
|
|
QWindow_createPlatformResources(QWidget_windowHandle(NewQtWidget.Widget));
|
|
QSurfaceFormat_destroy(AWinFormat);
|
|
|
|
NewQtWidget.GetGLXDrawable;
|
|
|
|
{$ENDIF}
|
|
|
|
{ SharedContext will be passed to various glX routines,
|
|
to enable sharing OpenGL resources with SharedControl. }
|
|
if SharedControl <> nil then
|
|
SharedContext := TQtGLWidget(SharedControl.Handle).GLXContext
|
|
else
|
|
SharedContext := nil;
|
|
|
|
{$IFDEF ModernGL}
|
|
if GLX_version_1_3(NewQtWidget.xdisplay) then
|
|
begin
|
|
//use approach recommended since glX 1.3
|
|
direct := true;
|
|
XDisplay := NewQtWidget.xdisplay;
|
|
ScreenNum := DefaultScreen (XDisplay);
|
|
AttrList.MajorVersion:=MajorVersion;
|
|
AttrList.MinorVersion:=MinorVersion;
|
|
// fill in context flags
|
|
AttrList.ContextFlags:=0;
|
|
//if DebugContext then
|
|
// AttrList.ContextFlags:=Attribs.ContextFlags or GLX_CONTEXT_DEBUG_BIT_ARB;
|
|
if (MultiSampling > 1) and GLX_ARB_multisample(XDisplay,ScreenNum) then begin
|
|
AttrList.MultiSampling := MultiSampling;
|
|
end else
|
|
begin
|
|
AttrList.MultiSampling:=0;
|
|
if MultiSampling > 1 then
|
|
{$IFDEF UNIX}writeln('Multi-sampling not supported');{$ENDIF}
|
|
end;
|
|
FBConfigsCount:=0;
|
|
FBConfigs:=glXChooseFBConfig(XDisplay, ScreenNum, @AttrList.AttributeList[0], FBConfigsCount);
|
|
if FBConfigsCount = 0 then begin
|
|
{$IFDEF UNIX}writeln('Could not find FB config: will try without multi-sampling');{$ENDIF}
|
|
FreeMem(AttrList.AttributeList);
|
|
AttrList.AttributeList := CreateOpenGLContextAttrList(DoubleBuffered,RGBA,RedBits,GreenBits,BlueBits,AlphaBits,DepthBits,StencilBits,AUXBuffers, 0);
|
|
AttrList.MajorVersion:=MajorVersion;
|
|
AttrList.MinorVersion:=MinorVersion;
|
|
// fill in context flags
|
|
AttrList.ContextFlags:=0;
|
|
FBConfigs:=glXChooseFBConfig(XDisplay, ScreenNum, @AttrList.AttributeList[0], FBConfigsCount);
|
|
end;
|
|
if FBConfigsCount = 0 then begin
|
|
raise Exception.Create('Could not find FB config');
|
|
//{$IFDEF UNIX}writeln('Could not find FB config: this may end poorly.');{$ENDIF}
|
|
//NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,NewQtWidget.visual, nil, direct);
|
|
//goto 123;
|
|
end;
|
|
// if multisampling is requested try to get a number of sample buffers as
|
|
// close to the specified number as possible
|
|
if AttrList.MultiSampling > 0 then
|
|
begin
|
|
BestSamples:=0;
|
|
for i := 0 to FBConfigsCount-1 do
|
|
begin
|
|
Samples:=0;
|
|
glXGetFBConfigAttrib(NewQtWidget.xdisplay, FBConfigs[i], GLX_SAMPLES_ARB, Samples);
|
|
if Samples = AttrList.MultiSampling then
|
|
begin
|
|
BestSamples := Samples;
|
|
BestFBConfig := i;
|
|
break;
|
|
end else
|
|
begin
|
|
if (Samples>BestSamples) and (Samples<AttrList.MultiSampling) then
|
|
begin
|
|
BestSamples := Samples;
|
|
BestFBConfig := i;
|
|
end;
|
|
end;
|
|
end;
|
|
//raise Exception.Create('BestFBConfig '+inttostr(BestFBConfig));
|
|
FBConfig := FBConfigs[BestFBConfig];
|
|
{$IFDEF VerboseMultiSampling}
|
|
//HTTPS://WWW.OPENGL.ORG/DISCUSSION_BOARDS/SHOWTHREAD.PHP/168359-OPENGL-3-X-AND-QT-FRAMEWORK?STYLEID=12
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_SAMPLE_BUFFERS, SAMP_BUF);
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_SAMPLES, SAMPLES);
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_VISUAL_ID, VISUAL_ID);
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_RED_SIZE, RED_SIZE);
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_BLUE_SIZE, BLUE_SIZE);
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_GREEN_SIZE, GREEN_SIZE);
|
|
GLXGETFBCONFIGATTRIB(XDISPLAY, FBCONFIG, GLX_ALPHA_SIZE, ALPHA_SIZE);
|
|
DEBUGLN(FORMAT('OPENGL FBCONFIG %D, ID 0X%X, SAMPLE_BUFFERS %D, SAMPLES %D, R%D G%D B%D A%D',
|
|
[BESTFBCONFIG, VISUAL_ID, SAMP_BUF, SAMPLES, RED_SIZE, BLUE_SIZE, GREEN_SIZE, ALPHA_SIZE]));
|
|
{$ENDIF}
|
|
end else
|
|
begin
|
|
{ just choose the first FB config from the FBConfigs list.
|
|
More involved selection possible. }
|
|
FBConfig := FBConfigs^;
|
|
end;
|
|
XVInfo:=glXGetVisualFromFBConfig(NewQtWidget.xdisplay, FBConfig);
|
|
if XVInfo=nil then
|
|
raise Exception.Create('QT no visual found');
|
|
if (GLX_ARB_create_context(NewQtWidget.xdisplay, DefaultScreen(NewQtWidget.xdisplay))) then
|
|
begin
|
|
// install custom X error handler
|
|
XSetErrorHandler(@CustomXErrorHandler);
|
|
Context3X[0] := GLX_CONTEXT_MAJOR_VERSION_ARB;
|
|
if AttrList.MajorVersion = 0 then
|
|
Context3X[1] := 1
|
|
else
|
|
Context3X[1] := AttrList.MajorVersion;
|
|
Context3X[2] := GLX_CONTEXT_MINOR_VERSION_ARB;
|
|
Context3X[3] := AttrList.MinorVersion;
|
|
Context3X[4] := GLX_CONTEXT_FLAGS_ARB;
|
|
Context3X[5] := AttrList.ContextFlags;
|
|
Context3X[6] := None;
|
|
NewQtWidget.glxcontext := glXCreateContextAttribsARB(NewQtWidget.xdisplay, FBConfig, SharedContext, direct, Context3X);
|
|
//raise Exception.Create('key '+inttostr(BestFBConfig));
|
|
// restore default error handler
|
|
XSetErrorHandler(nil);
|
|
end else
|
|
begin
|
|
NewQtWidget.glxcontext := glXCreateNewContext(NewQtWidget.xdisplay, FBConfig, GLX_RGBA_TYPE, SharedContext, direct);
|
|
end;
|
|
if FBConfigs<>nil then
|
|
XFree(FBConfigs);
|
|
|
|
end else
|
|
{$ENDIF}
|
|
NewQtWidget.glxcontext := glXCreateContext(NewQtWidget.xdisplay,
|
|
NewQtWidget.visual, SharedContext, direct);
|
|
//123:
|
|
NewQtWidget.ref_count := 1;
|
|
|
|
NewQtWidget.AttachEvents;
|
|
|
|
Result:=HWND(NewQtWidget);
|
|
finally
|
|
FreeMem(AttrList.AttributeList);
|
|
end;
|
|
end;
|
|
|
|
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
|
|
begin
|
|
if not AWinControl.HandleAllocated then exit;
|
|
// nothing to do
|
|
end;
|
|
|
|
function CreateOpenGLContextAttrList(DoubleBuffered: boolean; RGBA: boolean;
|
|
const RedBits, GreenBits, BlueBits, AlphaBits, DepthBits, StencilBits,
|
|
AUXBuffers, MultiSampling: Cardinal): PInteger;
|
|
var
|
|
p: integer;
|
|
UseFBConfig: boolean;
|
|
|
|
procedure Add(i: integer);
|
|
begin
|
|
if Result<>nil then
|
|
Result[p]:=i;
|
|
inc(p);
|
|
end;
|
|
|
|
procedure CreateList;
|
|
begin
|
|
p:=0;
|
|
//UseFBConfig := false;
|
|
if UseFBConfig then
|
|
begin
|
|
Add(GLX_X_RENDERABLE); Add(1);
|
|
Add(GLX_X_VISUAL_TYPE);
|
|
Add(GLX_TRUE_COLOR);
|
|
end;
|
|
if DoubleBuffered then
|
|
begin
|
|
if UseFBConfig then
|
|
begin Add(GLX_DOUBLEBUFFER); Add(1); end else
|
|
Add(GLX_DOUBLEBUFFER);
|
|
end;
|
|
if RGBA then
|
|
begin
|
|
if not UseFBConfig then Add(GLX_RGBA);
|
|
{ For UseFBConfig, glXChooseFBConfig already defaults to RGBA }
|
|
end;
|
|
Add(GLX_RED_SIZE); Add(RedBits);
|
|
Add(GLX_GREEN_SIZE); Add(GreenBits);
|
|
Add(GLX_BLUE_SIZE); Add(BlueBits);
|
|
if AlphaBits>0 then
|
|
begin
|
|
Add(GLX_ALPHA_SIZE); Add(AlphaBits);
|
|
end;
|
|
if DepthBits>0 then
|
|
begin
|
|
Add(GLX_DEPTH_SIZE); Add(DepthBits);
|
|
end;
|
|
if StencilBits>0 then
|
|
begin
|
|
Add(GLX_STENCIL_SIZE); Add(StencilBits);
|
|
end;
|
|
if AUXBuffers>0 then
|
|
begin
|
|
Add(GLX_AUX_BUFFERS); Add(AUXBuffers);
|
|
end;
|
|
{$IFDEF ModernGL}
|
|
if MultiSampling>1 then
|
|
begin
|
|
Add(GLX_SAMPLE_BUFFERS); Add(1);
|
|
Add(GLX_SAMPLES); Add(MultiSampling);
|
|
end;
|
|
{$ENDIF}
|
|
Add(0); { 0 = X.None (be careful: GLX_NONE is something different) }
|
|
end;
|
|
|
|
begin
|
|
{$IFDEF VerboseMultiSampling}
|
|
debugln(['CreateOpenGLContextAttrList MultiSampling=',MultiSampling]);
|
|
{$ENDIF}
|
|
{$IFDEF ModernGL}
|
|
{$IFDEF LCLQt6}
|
|
UseFBConfig := GLX_version_1_3(QtWidgetSet.x11Display());
|
|
{$ELSE}
|
|
UseFBConfig := GLX_version_1_3(QX11Info_display());
|
|
{$ENDIF}
|
|
{$ELSE}
|
|
UseFBConfig := false;
|
|
{$ENDIF}
|
|
Result:=nil;
|
|
CreateList;
|
|
GetMem(Result,SizeOf(integer)*p);
|
|
CreateList;
|
|
end;
|
|
|
|
|
|
end.
|
|
|
|
|