File: glgtk3glxcontext.pas

package info (click to toggle)
lazarus 2.2.6%2Bdfsg2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 219,980 kB
  • sloc: pascal: 1,944,919; xml: 357,634; makefile: 270,608; cpp: 57,115; sh: 3,249; java: 609; perl: 297; sql: 222; ansic: 137
file content (140 lines) | stat: -rw-r--r-- 4,162 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
  // todo(ryan): get the correct screen for the handle!
  result := TGdkScreen.get_default^.get_monitor_scale_factor(0);
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 := TLCLIntfHandle(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.