mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 01:18:14 +02:00
144 lines
4.1 KiB
ObjectPascal
144 lines
4.1 KiB
ObjectPascal
unit GLGtk3GlxContext;
|
|
|
|
{$mode objfpc}
|
|
{$LinkLib GL}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, ctypes, X, XUtil, XLib, gl, glext, glx,
|
|
// LazUtils
|
|
LazUtilities,
|
|
// LCL
|
|
LCLType, InterfaceBase, LMessages, Controls,
|
|
WSLCLClasses, LCLMessageGlue,
|
|
glib2, gtk3int, LazGdk3, LazGtk3, gtk3widgets;
|
|
|
|
function LBackingScaleFactor(Handle: HWND): single;
|
|
procedure LOpenGLViewport({%H-}Handle: HWND; Left, Top, Width, Height: integer);
|
|
procedure LOpenGLSwapBuffers(Handle: HWND);
|
|
function LOpenGLMakeCurrent(Handle: HWND): boolean;
|
|
function LOpenGLReleaseContext({%H-}Handle: HWND): boolean;
|
|
function LOpenGLCreateContext(AWinControl: TWinControl;
|
|
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
|
|
DoubleBuffered, RGBA, DebugContext: boolean;
|
|
const RedBits, GreenBits, BlueBits, MajorVersion, MinorVersion,
|
|
MultiSampling, AlphaBits, DepthBits, StencilBits, AUXBuffers: Cardinal;
|
|
const AParams: TCreateParams): HWND;
|
|
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
|
|
|
|
implementation
|
|
|
|
{$assertions on}
|
|
|
|
procedure on_render(widget: PGtkWidget; context: gpointer{Pcairo_t}; data: TGtk3Widget); cdecl;
|
|
begin
|
|
data.LCLObject.Perform(LM_PAINT, WParam(data), 0);
|
|
end;
|
|
|
|
function gtkglarea_size_allocateCB(Widget: PGtkWidget; Size: pGtkAllocation; Data: gPointer): GBoolean; cdecl;
|
|
var
|
|
SizeMsg: TLMSize;
|
|
GtkWidth, GtkHeight: integer;
|
|
LCLControl: TWinControl;
|
|
begin
|
|
Result := true;
|
|
LCLControl:=TWinControl(Data);
|
|
if LCLControl=nil then exit;
|
|
|
|
gtk_widget_get_size_request(Widget, @GtkWidth, @GtkHeight);
|
|
|
|
SizeMsg.Msg:=0;
|
|
FillChar(SizeMsg,SizeOf(SizeMsg),0);
|
|
with SizeMsg do
|
|
begin
|
|
Result := 0;
|
|
Msg := LM_SIZE;
|
|
SizeType := Size_SourceIsInterface;
|
|
Width := SmallInt(GtkWidth);
|
|
Height := SmallInt(GtkHeight);
|
|
end;
|
|
LCLControl.WindowProc(TLMessage(SizeMsg));
|
|
end;
|
|
|
|
function gtk_gl_area_get_error (area: PGtkGLArea): PGError; cdecl; external;
|
|
|
|
function LBackingScaleFactor(Handle: HWND): single;
|
|
var
|
|
glarea: TGtk3GLArea absolute Handle;
|
|
begin
|
|
if Assigned(glarea) then begin
|
|
Result := glarea.GetWindow^.get_scale_factor;
|
|
end else begin
|
|
Result := 1;
|
|
end;
|
|
end;
|
|
|
|
procedure LOpenGLViewport(Handle: HWND; Left, Top, Width, Height: integer);
|
|
var
|
|
scaleFactor: integer;
|
|
begin
|
|
scaleFactor := RoundToInt(LBackingScaleFactor(Handle));
|
|
glViewport(Left,Top,Width*scaleFactor,Height*scaleFactor);
|
|
end;
|
|
|
|
procedure LOpenGLSwapBuffers(Handle: HWND);
|
|
var
|
|
glarea: TGtk3GLArea absolute Handle;
|
|
begin
|
|
if Handle=0 then exit;
|
|
glFlush();
|
|
end;
|
|
|
|
function LOpenGLMakeCurrent(Handle: HWND): boolean;
|
|
var
|
|
glarea: TGtk3GLArea absolute Handle;
|
|
begin
|
|
glarea.Widget^.realize;
|
|
PGtkGLArea(glarea.Widget)^.make_current;
|
|
Assert(gtk_gl_area_get_error(PGtkGLArea(glarea.Widget)) = nil, 'LOpenGLMakeCurrent failed');
|
|
result := true;
|
|
end;
|
|
|
|
function LOpenGLReleaseContext(Handle: HWND): boolean;
|
|
var
|
|
glarea: TGtk3GLArea absolute Handle;
|
|
begin
|
|
// todo(ryan): is it possible to make no context current?
|
|
result:=true;
|
|
end;
|
|
|
|
function LOpenGLCreateContext(AWinControl: TWinControl;
|
|
WSPrivate: TWSPrivateClass; SharedControl: TWinControl;
|
|
DoubleBuffered, RGBA, DebugContext: boolean;
|
|
const RedBits, GreenBits, BlueBits, MajorVersion, MinorVersion,
|
|
MultiSampling, AlphaBits, DepthBits, StencilBits, AUXBuffers: Cardinal;
|
|
const AParams: TCreateParams): HWND;
|
|
var
|
|
NewWidget: TGtk3GLArea;
|
|
glarea: PGtkGLArea;
|
|
begin
|
|
NewWidget := TGtk3GLArea.Create(AWinControl, AParams);
|
|
result := TLCLHandle(NewWidget);
|
|
glarea := PGtkGLArea(NewWidget.Widget);
|
|
|
|
g_signal_connect(glarea, 'render', TGCallback(@on_render), NewWidget);
|
|
// todo(ryan): do we need this?
|
|
g_signal_connect_after(glarea, 'size-allocate', TGCallback(@gtkglarea_size_allocateCB), AWinControl);
|
|
|
|
glarea^.set_auto_render(false);
|
|
glarea^.set_required_version(MajorVersion, MinorVersion);
|
|
glarea^.set_has_depth_buffer(DepthBits > 0);
|
|
glarea^.set_has_alpha(AlphaBits > 0);
|
|
glarea^.set_has_stencil_buffer(StencilBits > 0);
|
|
end;
|
|
|
|
procedure LOpenGLDestroyContextInfo(AWinControl: TWinControl);
|
|
begin
|
|
if not AWinControl.HandleAllocated then exit;
|
|
// nothing to do
|
|
end;
|
|
|
|
end.
|
|
|