GXS.WinContext.pas 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.WinContext;
  5. (* Cross-platform context. *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.Windows,
  10. Winapi.Messages,
  11. System.SysUtils,
  12. System.Classes,
  13. FMX.Forms,
  14. FMX.Dialogs,
  15. FMX.Platform.Win,
  16. GXS.Context,
  17. GXS.State,
  18. Stage.OpenGL4,
  19. Stage.Strings,
  20. Stage.VectorGeometry;
  21. type
  22. // A context driver for standard Windows OpenGL
  23. TgxWinContext = class(TgxContext)
  24. protected
  25. FDC: HDC;
  26. FRC: HGLRC;
  27. FShareContext: TgxWinContext;
  28. FHPBUFFER: Integer;
  29. FiAttribs: packed array of Integer;
  30. FfAttribs: packed array of Single;
  31. FLegacyContextsOnly: Boolean;
  32. FSwapBufferSupported: Boolean;
  33. procedure SpawnLegacyContext(aDC: HDC); // used for WGL_pixel_format soup
  34. procedure CreateOldContext(aDC: HDC); virtual;
  35. procedure CreateNewContext(aDC: HDC); virtual;
  36. procedure ClearIAttribs;
  37. procedure AddIAttrib(attrib, value: Integer);
  38. procedure ChangeIAttrib(attrib, newValue: Integer);
  39. procedure DropIAttrib(attrib: Integer);
  40. procedure ClearFAttribs;
  41. procedure AddFAttrib(attrib, value: Single);
  42. procedure DestructionEarlyWarning(sender: TObject);
  43. procedure ChooseWGLFormat(DC: HDC; nMaxFormats: Cardinal; piFormats: PInteger; var nNumFormats: Integer;
  44. BufferCount: Integer = 1);
  45. procedure DoCreateContext(ADeviceHandle: THandle); override;
  46. procedure DoCreateMemoryContext(OutputDevice: THandle; Width, Height: Integer; BufferCount: Integer); override;
  47. function DoShareLists(aContext: TgxContext): Boolean; override;
  48. procedure DoDestroyContext; override;
  49. procedure DoActivate; override;
  50. procedure DoDeactivate; override;
  51. (* DoGetHandles must be implemented in child classes,
  52. and return the display + window *)
  53. public
  54. constructor Create; override;
  55. destructor Destroy; override;
  56. function IsValid: Boolean; override;
  57. procedure SwapBuffers; override;
  58. function RenderOutputDevice: Pointer; override;
  59. property DC: HDC read FDC;
  60. property RC: HGLRC read FRC;
  61. end;
  62. function CreateTempWnd: HWND;
  63. var
  64. (* This boolean controls a hook-based tracking of top-level forms destruction,
  65. with the purpose of being able to properly release OpenGL contexts before
  66. they are (improperly) released by some drivers upon top-level form
  67. destruction. *)
  68. vUseWindowTrackingHook: Boolean = True;
  69. implementation // ------------------------------------------------------------
  70. var
  71. vTrackingCount: Integer;
  72. vTrackedHwnd: array of HWND;
  73. vTrackedEvents: array of TNotifyEvent;
  74. vTrackingHook: HHOOK;
  75. function TrackHookProc(nCode: Integer; wParam: wParam; lParam: lParam): Integer; stdcall;
  76. var
  77. i: Integer;
  78. p: PCWPStruct;
  79. begin
  80. if nCode = HC_ACTION then
  81. begin
  82. p := PCWPStruct(lParam);
  83. // if (p.message=WM_DESTROY) or (p.message=WM_CLOSE) then begin // destroy & close variant
  84. if p.message = WM_DESTROY then
  85. begin
  86. // special care must be taken by this loop, items may go away unexpectedly
  87. i := vTrackingCount - 1;
  88. while i >= 0 do
  89. begin
  90. if IsChild(p.HWND, vTrackedHwnd[i]) then
  91. begin
  92. // got one, send notification
  93. vTrackedEvents[i](nil);
  94. end;
  95. Dec(i);
  96. while i >= vTrackingCount do
  97. Dec(i);
  98. end;
  99. end;
  100. CallNextHookEx(vTrackingHook, nCode, wParam, lParam);
  101. Result := 0;
  102. end
  103. else
  104. Result := CallNextHookEx(vTrackingHook, nCode, wParam, lParam);
  105. end;
  106. procedure TrackWindow(h: HWND; notifyEvent: TNotifyEvent);
  107. begin
  108. if not IsWindow(h) then
  109. Exit;
  110. if vTrackingCount = 0 then
  111. vTrackingHook := SetWindowsHookEx(WH_CALLWNDPROC, @TrackHookProc, 0, GetCurrentThreadID);
  112. Inc(vTrackingCount);
  113. SetLength(vTrackedHwnd, vTrackingCount);
  114. vTrackedHwnd[vTrackingCount - 1] := h;
  115. SetLength(vTrackedEvents, vTrackingCount);
  116. vTrackedEvents[vTrackingCount - 1] := notifyEvent;
  117. end;
  118. procedure UnTrackWindow(h: HWND);
  119. var
  120. i, k: Integer;
  121. begin
  122. if not IsWindow(h) then
  123. Exit;
  124. if vTrackingCount = 0 then
  125. Exit;
  126. k := 0;
  127. for i := 0 to MinInteger(vTrackingCount, Length(vTrackedHwnd)) - 1 do
  128. begin
  129. if vTrackedHwnd[i] <> h then
  130. begin
  131. if (k <> i) then
  132. begin
  133. vTrackedHwnd[k] := vTrackedHwnd[i];
  134. vTrackedEvents[k] := vTrackedEvents[i];
  135. end;
  136. Inc(k);
  137. end
  138. end;
  139. if (k >= vTrackingCount) then
  140. Exit;
  141. Dec(vTrackingCount);
  142. SetLength(vTrackedHwnd, vTrackingCount);
  143. SetLength(vTrackedEvents, vTrackingCount);
  144. if vTrackingCount = 0 then
  145. UnhookWindowsHookEx(vTrackingHook);
  146. end;
  147. var
  148. vUtilWindowClass: TWndClass = (style: 0; lpfnWndProc: @DefWindowProc;
  149. cbClsExtra: 0; cbWndExtra: 0; hInstance: 0; hIcon: 0;
  150. hCursor: 0; hbrBackground: 0; lpszMenuName: nil; lpszClassName: 'GXSUtilWindow');
  151. function CreateTempWnd: HWND;
  152. var
  153. classRegistered: Boolean;
  154. tempClass: TWndClass;
  155. begin
  156. vUtilWindowClass.hInstance := hInstance;
  157. classRegistered := GetClassInfo(hInstance, vUtilWindowClass.lpszClassName, tempClass);
  158. if not classRegistered then
  159. /// RegisterClass(vUtilWindowClass) - to do for FMX ;
  160. Result := CreateWindowEx(WS_EX_TOOLWINDOW, vUtilWindowClass.lpszClassName, '', WS_POPUP, 0, 0, 0, 0, 0, 0, hInstance, nil);
  161. end;
  162. // ------------------
  163. // ------------------ TgxSceneContext ------------------
  164. // ------------------
  165. constructor TgxWinContext.Create;
  166. begin
  167. inherited Create;
  168. ClearIAttribs;
  169. ClearFAttribs;
  170. end;
  171. destructor TgxWinContext.Destroy;
  172. begin
  173. inherited Destroy;
  174. end;
  175. function SetupPalette(DC: HDC; PFD: TPixelFormatDescriptor): HPalette;
  176. var
  177. nColors, i: Integer;
  178. LogPalette: TMaxLogPalette;
  179. RedMask, GreenMask, BlueMask: Byte;
  180. begin
  181. nColors := 1 shl PFD.cColorBits;
  182. LogPalette.palVersion := $300;
  183. LogPalette.palNumEntries := nColors;
  184. RedMask := (1 shl PFD.cRedBits) - 1;
  185. GreenMask := (1 shl PFD.cGreenBits) - 1;
  186. BlueMask := (1 shl PFD.cBlueBits) - 1;
  187. with LogPalette, PFD do
  188. for i := 0 to nColors - 1 do
  189. begin
  190. palPalEntry[i].peRed := (((i shr cRedShift) and RedMask) * 255) div RedMask;
  191. palPalEntry[i].peGreen := (((i shr cGreenShift) and GreenMask) * 255) div GreenMask;
  192. palPalEntry[i].peBlue := (((i shr cBlueShift) and BlueMask) * 255) div BlueMask;
  193. palPalEntry[i].peFlags := 0;
  194. end;
  195. Result := CreatePalette(PLogPalette(@LogPalette)^);
  196. if Result <> 0 then
  197. begin
  198. SelectPalette(DC, Result, False);
  199. RealizePalette(DC);
  200. end
  201. else
  202. RaiseLastOSError;
  203. end;
  204. procedure TgxWinContext.ClearIAttribs;
  205. begin
  206. SetLength(FiAttribs, 1);
  207. FiAttribs[0] := 0;
  208. end;
  209. procedure TgxWinContext.AddIAttrib(attrib, value: Integer);
  210. var
  211. n: Integer;
  212. begin
  213. n := Length(FiAttribs);
  214. SetLength(FiAttribs, n + 2);
  215. FiAttribs[n - 1] := attrib;
  216. FiAttribs[n] := value;
  217. FiAttribs[n + 1] := 0;
  218. end;
  219. procedure TgxWinContext.ChangeIAttrib(attrib, newValue: Integer);
  220. var
  221. i: Integer;
  222. begin
  223. i := 0;
  224. while i < Length(FiAttribs) do
  225. begin
  226. if FiAttribs[i] = attrib then
  227. begin
  228. FiAttribs[i + 1] := newValue;
  229. Exit;
  230. end;
  231. Inc(i, 2);
  232. end;
  233. AddIAttrib(attrib, newValue);
  234. end;
  235. procedure TgxWinContext.DropIAttrib(attrib: Integer);
  236. var
  237. i: Integer;
  238. begin
  239. i := 0;
  240. while i < Length(FiAttribs) do
  241. begin
  242. if FiAttribs[i] = attrib then
  243. begin
  244. Inc(i, 2);
  245. while i < Length(FiAttribs) do
  246. begin
  247. FiAttribs[i - 2] := FiAttribs[i];
  248. Inc(i);
  249. end;
  250. SetLength(FiAttribs, Length(FiAttribs) - 2);
  251. Exit;
  252. end;
  253. Inc(i, 2);
  254. end;
  255. end;
  256. procedure TgxWinContext.ClearFAttribs;
  257. begin
  258. SetLength(FfAttribs, 1);
  259. FfAttribs[0] := 0;
  260. end;
  261. procedure TgxWinContext.AddFAttrib(attrib, value: Single);
  262. var
  263. n: Integer;
  264. begin
  265. n := Length(FfAttribs);
  266. SetLength(FfAttribs, n + 2);
  267. FfAttribs[n - 1] := attrib;
  268. FfAttribs[n] := value;
  269. FfAttribs[n + 1] := 0;
  270. end;
  271. procedure TgxWinContext.DestructionEarlyWarning(sender: TObject);
  272. begin
  273. if IsValid then
  274. DestroyContext;
  275. end;
  276. procedure TgxWinContext.ChooseWGLFormat(DC: HDC; nMaxFormats: Cardinal; piFormats: PInteger; var nNumFormats: Integer;
  277. BufferCount: Integer);
  278. const
  279. cAAToSamples: array [aaNone .. csa16xHQ] of Integer = (1, 2, 2, 4, 4, 6, 8, 16, 8, 8, 16, 16);
  280. cCSAAToSamples: array [csa8x .. csa16xHQ] of Integer = (4, 8, 4, 8);
  281. procedure ChoosePixelFormat;
  282. begin
  283. if not wglChoosePixelFormatARB(DC, @FiAttribs[0], @FfAttribs[0], 32, PGLint(piFormats), @nNumFormats) then
  284. nNumFormats := 0;
  285. end;
  286. var
  287. float: Boolean;
  288. aa: TgxAntiAliasing;
  289. begin
  290. // request hardware acceleration
  291. case FAcceleration of
  292. chaUnknown:
  293. AddIAttrib(WGL_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB);
  294. chaHardware:
  295. AddIAttrib(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB);
  296. chaSoftware:
  297. AddIAttrib(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB);
  298. end;
  299. float := (ColorBits = 64) or (ColorBits = 128); // float_type
  300. if float then
  301. begin // float_type
  302. if WGL_ATI_pixel_format_float then
  303. begin // NV40 uses ATI_float, with linear filtering
  304. AddIAttrib(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ATI);
  305. end
  306. else
  307. begin
  308. AddIAttrib(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
  309. AddIAttrib(WGL_FLOAT_COMPONENTS_NV, GL_TRUE);
  310. end;
  311. end;
  312. if BufferCount > 1 then
  313. // 1 front buffer + (BufferCount-1) aux buffers
  314. AddIAttrib(WGL_AUX_BUFFERS_ARB, BufferCount - 1);
  315. AddIAttrib(WGL_COLOR_BITS_ARB, ColorBits);
  316. if AlphaBits > 0 then
  317. AddIAttrib(WGL_ALPHA_BITS_ARB, AlphaBits);
  318. AddIAttrib(WGL_DEPTH_BITS_ARB, DepthBits);
  319. if StencilBits > 0 then
  320. AddIAttrib(WGL_STENCIL_BITS_ARB, StencilBits);
  321. if AccumBits > 0 then
  322. AddIAttrib(WGL_ACCUM_BITS_ARB, AccumBits);
  323. if AuxBuffers > 0 then
  324. AddIAttrib(WGL_AUX_BUFFERS_ARB, AuxBuffers);
  325. if (AntiAliasing <> aaDefault) and WGL_ARB_multisample then
  326. begin
  327. if AntiAliasing = aaNone then
  328. AddIAttrib(WGL_SAMPLE_BUFFERS_ARB, GL_FALSE)
  329. else
  330. begin
  331. AddIAttrib(WGL_SAMPLE_BUFFERS_ARB, GL_TRUE);
  332. AddIAttrib(WGL_SAMPLES_ARB, cAAToSamples[AntiAliasing]);
  333. if (AntiAliasing >= csa8x) and (AntiAliasing <= csa16xHQ) then
  334. AddIAttrib(WGL_COLOR_SAMPLES_NV, cCSAAToSamples[AntiAliasing]);
  335. end;
  336. end;
  337. ClearFAttribs;
  338. ChoosePixelFormat;
  339. if (nNumFormats = 0) and (DepthBits >= 32) then
  340. begin
  341. // couldn't find 32+ bits depth buffer, 24 bits one available?
  342. ChangeIAttrib(WGL_DEPTH_BITS_ARB, 24);
  343. ChoosePixelFormat;
  344. end;
  345. if (nNumFormats = 0) and (DepthBits >= 24) then
  346. begin
  347. // couldn't find 24+ bits depth buffer, 16 bits one available?
  348. ChangeIAttrib(WGL_DEPTH_BITS_ARB, 16);
  349. ChoosePixelFormat;
  350. end;
  351. if (nNumFormats = 0) and (ColorBits >= 24) then
  352. begin
  353. // couldn't find 24+ bits color buffer, 16 bits one available?
  354. ChangeIAttrib(WGL_COLOR_BITS_ARB, 16);
  355. ChoosePixelFormat;
  356. end;
  357. if (nNumFormats = 0) and (AntiAliasing <> aaDefault) then
  358. begin
  359. // Restore DepthBits
  360. ChangeIAttrib(WGL_DEPTH_BITS_ARB, DepthBits);
  361. if (AntiAliasing >= csa8x) and (AntiAliasing <= csa16xHQ) then
  362. begin
  363. DropIAttrib(WGL_COLOR_SAMPLES_NV);
  364. case AntiAliasing of
  365. csa8x, csa8xHQ:
  366. AntiAliasing := aa8x;
  367. csa16x, csa16xHQ:
  368. AntiAliasing := aa16x;
  369. end;
  370. ChangeIAttrib(WGL_SAMPLES_ARB, cAAToSamples[AntiAliasing]);
  371. end;
  372. ChoosePixelFormat;
  373. if nNumFormats = 0 then
  374. begin
  375. aa := AntiAliasing;
  376. repeat
  377. Dec(aa);
  378. if aa = aaNone then
  379. begin
  380. // couldn't find AA buffer, try without
  381. DropIAttrib(WGL_SAMPLE_BUFFERS_ARB);
  382. DropIAttrib(WGL_SAMPLES_ARB);
  383. ChoosePixelFormat;
  384. break;
  385. end;
  386. ChangeIAttrib(WGL_SAMPLES_ARB, cAAToSamples[aa]);
  387. ChoosePixelFormat;
  388. until nNumFormats <> 0;
  389. AntiAliasing := aa;
  390. end;
  391. end;
  392. // Check DepthBits again
  393. if (nNumFormats = 0) and (DepthBits >= 32) then
  394. begin
  395. // couldn't find 32+ bits depth buffer, 24 bits one available?
  396. ChangeIAttrib(WGL_DEPTH_BITS_ARB, 24);
  397. ChoosePixelFormat;
  398. end;
  399. if (nNumFormats = 0) and (DepthBits >= 24) then
  400. begin
  401. // couldn't find 24+ bits depth buffer, 16 bits one available?
  402. ChangeIAttrib(WGL_DEPTH_BITS_ARB, 16);
  403. ChoosePixelFormat;
  404. end;
  405. if (nNumFormats = 0) and (ColorBits >= 24) then
  406. begin
  407. // couldn't find 24+ bits color buffer, 16 bits one available?
  408. ChangeIAttrib(WGL_COLOR_BITS_ARB, 16);
  409. ChoosePixelFormat;
  410. end;
  411. if nNumFormats = 0 then
  412. begin
  413. // ok, last attempt: no AA, restored depth and color,
  414. // relaxed hardware-acceleration request
  415. ChangeIAttrib(WGL_COLOR_BITS_ARB, ColorBits);
  416. ChangeIAttrib(WGL_DEPTH_BITS_ARB, DepthBits);
  417. DropIAttrib(WGL_ACCELERATION_ARB);
  418. ChoosePixelFormat;
  419. end;
  420. end;
  421. procedure TgxWinContext.CreateOldContext(aDC: HDC);
  422. begin
  423. if not FLegacyContextsOnly then
  424. begin
  425. case Layer of
  426. clUnderlay2: FRC := wglCreateLayerContext(aDC, -2);
  427. clUnderlay1: FRC := wglCreateLayerContext(aDC, -1);
  428. clMainPlane: FRC := wglCreateContext(aDC);
  429. clOverlay1: FRC := wglCreateLayerContext(aDC, 1);
  430. clOverlay2: FRC := wglCreateLayerContext(aDC, 2);
  431. end;
  432. end
  433. else
  434. FRC := wglCreateContext(aDC);
  435. if FRC = 0 then
  436. RaiseLastOSError;
  437. FDC := aDC;
  438. if not wglMakeCurrent(FDC, FRC) then
  439. raise EVXContext.Create(Format(strContextActivationFailed, [GetLastError, SysErrorMessage(GetLastError)]));
  440. if not FLegacyContextsOnly then
  441. begin
  442. if Assigned(FShareContext) and (FShareContext.RC <> 0) then
  443. begin
  444. if not wglShareLists(FShareContext.RC, FRC) then
  445. {$IFDEF USE_LOGGING}
  446. GLSLogger.LogWarning(strFailedToShare)
  447. {$ENDIF}
  448. else
  449. begin
  450. FSharedContexts.Add(FShareContext);
  451. PropagateSharedContext;
  452. end;
  453. end;
  454. //DebugMode := False;
  455. ReadExtensions(); //FGL.Initialize;
  456. MakeGLCurrent;
  457. // If we are using AntiAliasing, adjust filtering hints
  458. if AntiAliasing in [aa2xHQ, aa4xHQ, csa8xHQ, csa16xHQ] then
  459. // Hint for nVidia HQ modes (Quincunx etc.)
  460. gxStates.MultisampleFilterHint := hintNicest
  461. else
  462. gxStates.MultisampleFilterHint := hintDontCare;
  463. if rcoDebug in Options then
  464. ShowMessage(strDriverNotSupportDebugRC);
  465. if rcoOGL_ES in Options then
  466. ShowMessage(strDriverNotSupportOESRC);
  467. if gxStates.ForwardContext then
  468. ShowMessage(strDriverNotSupportFRC);
  469. gxStates.ForwardContext := False;
  470. end
  471. else
  472. ShowMessage(strTmpRC_Created);
  473. end;
  474. procedure TgxWinContext.CreateNewContext(aDC: HDC);
  475. var
  476. bSuccess, bOES: Boolean;
  477. begin
  478. bSuccess := False;
  479. bOES := False;
  480. try
  481. ClearIAttribs;
  482. // Initialize forward context
  483. if False { gxStates.ForwardContext } then
  484. begin
  485. if GL_VERSION_4_2 then
  486. begin
  487. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
  488. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 2);
  489. end
  490. else if GL_VERSION_4_1 then
  491. begin
  492. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
  493. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 1);
  494. end
  495. else if GL_VERSION_4_0 then
  496. begin
  497. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
  498. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
  499. end
  500. else
  501. Abort;
  502. AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
  503. if rcoOGL_ES in Options then
  504. ShowMessage(strOESvsForwardRC);
  505. end
  506. else if rcoOGL_ES in Options then
  507. begin
  508. if WGL_EXT_create_context_es2_profile then
  509. begin
  510. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 2);
  511. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
  512. AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
  513. bOES := True;
  514. end
  515. else
  516. ShowMessage(strDriverNotSupportOESRC);
  517. end;
  518. if rcoDebug in Options then
  519. begin
  520. AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB);
  521. ///DebugMode := True;
  522. end;
  523. case Layer of
  524. clUnderlay2: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -2);
  525. clUnderlay1: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -1);
  526. clOverlay1: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 1);
  527. clOverlay2: AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 2);
  528. end;
  529. FRC := 0;
  530. if Assigned(FShareContext) then
  531. begin
  532. FRC := wglCreateContextAttribsARB(aDC, FShareContext.RC, @FiAttribs[0]);
  533. if FRC <> 0 then
  534. begin
  535. FSharedContexts.Add(FShareContext);
  536. PropagateSharedContext;
  537. end
  538. else
  539. ShowMessage(strFailedToShare)
  540. end;
  541. if FRC = 0 then
  542. begin
  543. FRC := wglCreateContextAttribsARB(aDC, 0, @FiAttribs[0]);
  544. if FRC = 0 then
  545. begin
  546. if gxStates.ForwardContext then
  547. ShowMessage(Format(strForwardContextFailed,
  548. [GetLastError, SysErrorMessage(GetLastError)]))
  549. else
  550. ShowMessage(Format(strBackwardContextFailed,
  551. [GetLastError, SysErrorMessage(GetLastError)]));
  552. Abort;
  553. end;
  554. end;
  555. FDC := aDC;
  556. if not wglMakeCurrent(FDC, FRC) then
  557. begin
  558. ShowMessage(Format(strContextActivationFailed, [GetLastError, SysErrorMessage(GetLastError)]));
  559. Abort;
  560. end;
  561. InitOpenGL; ///FGL.Initialize;
  562. MakeGLCurrent;
  563. // If we are using AntiAliasing, adjust filtering hints
  564. if AntiAliasing in [aa2xHQ, aa4xHQ, csa8xHQ, csa16xHQ] then
  565. // Hint for nVidia HQ modes (Quincunx etc.)
  566. gxStates.MultisampleFilterHint := hintNicest
  567. else
  568. gxStates.MultisampleFilterHint := hintDontCare;
  569. if gxStates.ForwardContext then
  570. ShowMessage(strFRC_created);
  571. if bOES then
  572. ShowMessage(strOESRC_created);
  573. bSuccess := True;
  574. finally
  575. gxStates.ForwardContext := gxStates.ForwardContext and bSuccess;
  576. PipelineTransformation.LoadMatricesEnabled := not gxStates.ForwardContext;
  577. end;
  578. end;
  579. procedure TgxWinContext.DoCreateContext(ADeviceHandle: THandle);
  580. const
  581. cMemoryDCs = [OBJ_MEMDC, OBJ_METADC, OBJ_ENHMETADC];
  582. cBoolToInt: array [False .. True] of Integer = (GL_FALSE, GL_TRUE);
  583. cLayerToSet: array [TgxContextLayer] of Byte = (32, 16, 0, 1, 2);
  584. var
  585. pfDescriptor: TPixelFormatDescriptor;
  586. pixelFormat, nbFormats, softwarePixelFormat: Integer;
  587. aType: DWORD;
  588. iFormats: array [0 .. 31] of Integer;
  589. tempWnd: HWND;
  590. tempDC: HDC;
  591. localDC: HDC;
  592. localRC: HGLRC;
  593. sharedRC: TgxWinContext;
  594. function CurrentPixelFormatIsHardwareAccelerated: Boolean;
  595. var
  596. localPFD: TPixelFormatDescriptor;
  597. begin
  598. Result := False;
  599. if pixelFormat = 0 then
  600. Exit;
  601. with localPFD do
  602. begin
  603. nSize := SizeOf(localPFD);
  604. nVersion := 1;
  605. end;
  606. DescribePixelFormat(ADeviceHandle, pixelFormat, SizeOf(localPFD), localPFD);
  607. Result := ((localPFD.dwFlags and PFD_GENERIC_FORMAT) = 0);
  608. end;
  609. var
  610. i, iAttrib, iValue: Integer;
  611. begin
  612. if vUseWindowTrackingHook and not FLegacyContextsOnly then
  613. TrackWindow(WindowFromDC(ADeviceHandle), DestructionEarlyWarning);
  614. // Just in case it didn't happen already.
  615. if not InitOpenGL then
  616. RaiseLastOSError;
  617. // Prepare PFD
  618. FillChar(pfDescriptor, SizeOf(pfDescriptor), 0);
  619. with pfDescriptor do
  620. begin
  621. nSize := SizeOf(pfDescriptor);
  622. nVersion := 1;
  623. dwFlags := PFD_SUPPORT_OPENGL;
  624. aType := GetObjectType(ADeviceHandle);
  625. if aType = 0 then
  626. RaiseLastOSError;
  627. if aType in cMemoryDCs then
  628. dwFlags := dwFlags or PFD_DRAW_TO_BITMAP
  629. else
  630. dwFlags := dwFlags or PFD_DRAW_TO_WINDOW;
  631. if rcoDoubleBuffered in Options then
  632. dwFlags := dwFlags or PFD_DOUBLEBUFFER;
  633. if rcoStereo in Options then
  634. dwFlags := dwFlags or PFD_STEREO;
  635. iPixelType := PFD_TYPE_RGBA;
  636. cColorBits := ColorBits;
  637. cDepthBits := DepthBits;
  638. cStencilBits := StencilBits;
  639. cAccumBits := AccumBits;
  640. cAlphaBits := AlphaBits;
  641. cAuxBuffers := AuxBuffers;
  642. case Layer of
  643. clUnderlay2, clUnderlay1:
  644. iLayerType := Byte(PFD_UNDERLAY_PLANE);
  645. clMainPlane:
  646. iLayerType := PFD_MAIN_PLANE;
  647. clOverlay1, clOverlay2:
  648. iLayerType := PFD_OVERLAY_PLANE;
  649. end;
  650. bReserved := cLayerToSet[Layer];
  651. if Layer <> clMainPlane then
  652. dwFlags := dwFlags or PFD_SWAP_LAYER_BUFFERS;
  653. end;
  654. pixelFormat := 0;
  655. // WGL_ARB_pixel_format is used if available
  656. //
  657. if not(IsMesaGL or FLegacyContextsOnly or (aType in cMemoryDCs)) then
  658. begin
  659. // the WGL mechanism is a little awkward: we first create a dummy context
  660. // on the TOP-level DC (ie. screen), to retrieve our pixelformat, create
  661. // our stuff, etc.
  662. tempWnd := CreateTempWnd;
  663. tempDC := GetDC(tempWnd);
  664. localDC := 0;
  665. localRC := 0;
  666. try
  667. SpawnLegacyContext(tempDC);
  668. try
  669. DoActivate;
  670. try
  671. ClearGLError;
  672. if WGL_ARB_pixel_format then
  673. begin
  674. // New pixel format selection via wglChoosePixelFormatARB
  675. ClearIAttribs;
  676. AddIAttrib(WGL_DRAW_TO_WINDOW_ARB, GL_TRUE);
  677. AddIAttrib(WGL_STEREO_ARB, cBoolToInt[rcoStereo in Options]);
  678. AddIAttrib(WGL_DOUBLE_BUFFER_ARB, cBoolToInt[rcoDoubleBuffered in Options]);
  679. ChooseWGLFormat(ADeviceHandle, 32, @iFormats, nbFormats);
  680. if nbFormats > 0 then
  681. begin
  682. if WGL_ARB_multisample and (AntiAliasing in [aaNone, aaDefault])
  683. then
  684. begin
  685. // Pick first non AntiAliased for aaDefault and aaNone modes
  686. iAttrib := WGL_SAMPLE_BUFFERS_ARB;
  687. for i := 0 to nbFormats - 1 do
  688. begin
  689. pixelFormat := iFormats[i];
  690. iValue := GL_FALSE;
  691. wglGetPixelFormatAttribivARB(ADeviceHandle, pixelFormat, 0, 1, @iAttrib, @iValue);
  692. if iValue = GL_FALSE then
  693. break;
  694. end;
  695. end
  696. else
  697. pixelFormat := iFormats[0];
  698. if GetPixelFormat(ADeviceHandle) <> pixelFormat then
  699. begin
  700. if not SetPixelFormat(ADeviceHandle, pixelFormat, @pfDescriptor)
  701. then
  702. RaiseLastOSError;
  703. end;
  704. end;
  705. end;
  706. finally
  707. DoDeactivate;
  708. end;
  709. finally
  710. sharedRC := FShareContext;
  711. DoDestroyContext;
  712. FShareContext := sharedRC;
  713. ShowMessage('Temporary rendering context destroyed');
  714. end;
  715. finally
  716. ReleaseDC(0, tempDC);
  717. DestroyWindow(tempWnd);
  718. FDC := localDC;
  719. FRC := localRC;
  720. end;
  721. end;
  722. if pixelFormat = 0 then
  723. begin
  724. // Legacy pixel format selection
  725. pixelFormat := ChoosePixelFormat(ADeviceHandle, @pfDescriptor);
  726. if (not(aType in cMemoryDCs)) and (not CurrentPixelFormatIsHardwareAccelerated) then
  727. begin
  728. softwarePixelFormat := pixelFormat;
  729. pixelFormat := 0;
  730. end
  731. else
  732. softwarePixelFormat := 0;
  733. if pixelFormat = 0 then
  734. begin
  735. // Failed on default params, try with 16 bits depth buffer
  736. pfDescriptor.cDepthBits := 16;
  737. pixelFormat := ChoosePixelFormat(ADeviceHandle, @pfDescriptor);
  738. if not CurrentPixelFormatIsHardwareAccelerated then
  739. pixelFormat := 0;
  740. if pixelFormat = 0 then
  741. begin
  742. // Failed, try with 16 bits color buffer
  743. pfDescriptor.cColorBits := 16;
  744. pixelFormat := ChoosePixelFormat(ADeviceHandle, @pfDescriptor);
  745. end;
  746. if not CurrentPixelFormatIsHardwareAccelerated then
  747. begin
  748. // Fallback to original, should be supported by software
  749. pixelFormat := softwarePixelFormat;
  750. end;
  751. if pixelFormat = 0 then
  752. RaiseLastOSError;
  753. end;
  754. end;
  755. if GetPixelFormat(ADeviceHandle) <> pixelFormat then
  756. begin
  757. if not SetPixelFormat(ADeviceHandle, pixelFormat, @pfDescriptor) then
  758. RaiseLastOSError;
  759. end;
  760. // Check the properties we just set.
  761. DescribePixelFormat(ADeviceHandle, pixelFormat, SizeOf(pfDescriptor), pfDescriptor);
  762. with pfDescriptor do
  763. begin
  764. if (dwFlags and PFD_NEED_PALETTE) <> 0 then
  765. SetupPalette(ADeviceHandle, pfDescriptor);
  766. FSwapBufferSupported := (dwFlags and PFD_SWAP_LAYER_BUFFERS) <> 0;
  767. if bReserved = 0 then
  768. FLayer := clMainPlane;
  769. end;
  770. if not FLegacyContextsOnly then
  771. begin
  772. if ((pfDescriptor.dwFlags and PFD_GENERIC_FORMAT) > 0) and (FAcceleration = chaHardware) then
  773. begin
  774. FAcceleration := chaSoftware;
  775. ShowMessage(strFailHWRC);
  776. end;
  777. end;
  778. if not FLegacyContextsOnly and WGL_ARB_create_context and (FAcceleration = chaHardware) then
  779. CreateNewContext(ADeviceHandle)
  780. else
  781. CreateOldContext(ADeviceHandle);
  782. if not FLegacyContextsOnly then
  783. begin
  784. // Share identifiers with other context if it deffined
  785. if (ServiceContext <> nil) and (Self <> ServiceContext) then
  786. begin
  787. if wglShareLists(TgxWinContext(ServiceContext).FRC, FRC) then
  788. begin
  789. FSharedContexts.Add(ServiceContext);
  790. PropagateSharedContext;
  791. end
  792. else
  793. ShowMessage('DoCreateContext - Failed to share contexts with resource context');
  794. end;
  795. end;
  796. end;
  797. procedure TgxWinContext.SpawnLegacyContext(aDC: HDC);
  798. begin
  799. try
  800. FLegacyContextsOnly := True;
  801. try
  802. DoCreateContext(aDC);
  803. finally
  804. FLegacyContextsOnly := False;
  805. end;
  806. except
  807. on E: Exception do
  808. begin
  809. raise Exception.Create(strUnableToCreateLegacyContext + #13#10 + E.ClassName + ': ' + E.message);
  810. end;
  811. end;
  812. end;
  813. procedure TgxWinContext.DoCreateMemoryContext(OutputDevice: THandle; Width, Height: Integer; BufferCount: Integer);
  814. var
  815. nbFormats: Integer;
  816. iFormats: array [0 .. 31] of Integer;
  817. iPBufferAttribs: array [0 .. 0] of Integer;
  818. localHPBuffer: Integer;
  819. localRC: HGLRC;
  820. localDC, tempDC: HDC;
  821. tempWnd: HWND;
  822. shareRC: TgxWinContext;
  823. pfDescriptor: TPixelFormatDescriptor;
  824. bOES: Boolean;
  825. begin
  826. localHPBuffer := 0;
  827. localDC := 0;
  828. localRC := 0;
  829. bOES := False;
  830. // the WGL mechanism is a little awkward: we first create a dummy context
  831. // on the TOP-level DC (ie. screen), to retrieve our pixelformat, create
  832. // our stuff, etc.
  833. tempWnd := CreateTempWnd;
  834. tempDC := GetDC(tempWnd);
  835. try
  836. SpawnLegacyContext(tempDC);
  837. try
  838. DoActivate;
  839. try
  840. ClearGLError;
  841. if WGL_ARB_pixel_format and WGL_ARB_pbuffer then
  842. begin
  843. ClearIAttribs;
  844. AddIAttrib(WGL_DRAW_TO_PBUFFER_ARB, 1);
  845. ChooseWGLFormat(tempDC, 32, @iFormats, nbFormats, BufferCount);
  846. if nbFormats = 0 then
  847. raise EPBuffer.Create
  848. ('Format not supported for pbuffer operation.');
  849. iPBufferAttribs[0] := 0;
  850. localHPBuffer := wglCreatePbufferARB(tempDC, iFormats[0], Width,
  851. Height, @iPBufferAttribs[0]);
  852. if localHPBuffer = 0 then
  853. raise EPBuffer.Create('Unabled to create pbuffer.');
  854. try
  855. localDC := wglGetPbufferDCARB(localHPBuffer);
  856. if localDC = 0 then
  857. raise EPBuffer.Create('Unabled to create pbuffer''s DC.');
  858. try
  859. if WGL_ARB_create_context then
  860. begin
  861. // Modern creation style
  862. ClearIAttribs;
  863. // Initialize forward context
  864. if gxStates.ForwardContext then
  865. begin
  866. if GL_VERSION_4_2 then
  867. begin
  868. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
  869. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 2);
  870. end
  871. else if GL_VERSION_4_1 then
  872. begin
  873. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
  874. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 1);
  875. end
  876. else if GL_VERSION_4_0 then
  877. begin
  878. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 4);
  879. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
  880. end
  881. else
  882. Abort;
  883. AddIAttrib(WGL_CONTEXT_FLAGS_ARB,
  884. WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
  885. if rcoOGL_ES in Options then
  886. ShowMessage(strOESvsForwardRC);
  887. end
  888. else if rcoOGL_ES in Options then
  889. begin
  890. if WGL_EXT_create_context_es2_profile then
  891. begin
  892. AddIAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, 2);
  893. AddIAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, 0);
  894. AddIAttrib(WGL_CONTEXT_FLAGS_ARB,
  895. WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
  896. end
  897. else
  898. ShowMessage(strDriverNotSupportOESRC);
  899. end;
  900. if rcoDebug in Options then
  901. begin
  902. AddIAttrib(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB);
  903. ///DebugMode := True;
  904. end;
  905. case Layer of
  906. clUnderlay2:
  907. AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -2);
  908. clUnderlay1:
  909. AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, -1);
  910. clOverlay1:
  911. AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 1);
  912. clOverlay2:
  913. AddIAttrib(WGL_CONTEXT_LAYER_PLANE_ARB, 2);
  914. end;
  915. localRC := wglCreateContextAttribsARB(localDC, 0,
  916. @FiAttribs[0]);
  917. if localRC = 0 then
  918. {$IFDEF USE_LOGGING}
  919. begin
  920. if gxStates.ForwardContext then
  921. GLSLogger.LogErrorFmt(cForwardContextFailed,
  922. [GetLastError, SysErrorMessage(GetLastError)])
  923. else
  924. GLSLogger.LogErrorFmt(cBackwardContextFailed,
  925. [GetLastError, SysErrorMessage(GetLastError)]);
  926. Abort;
  927. end;
  928. {$ELSE}
  929. raise Exception.Create('Unabled to create pbuffer''s RC.');
  930. {$ENDIF}
  931. end
  932. else
  933. begin
  934. // Old creation style
  935. localRC := wglCreateContext(localDC);
  936. if localRC = 0 then
  937. begin
  938. ShowMessage(Format(strBackwardContextFailed,
  939. [GetLastError, SysErrorMessage(GetLastError)]));
  940. Abort;
  941. end;
  942. end;
  943. except
  944. wglReleasePBufferDCARB(localHPBuffer, localDC);
  945. raise;
  946. end;
  947. except
  948. wglDestroyPBufferARB(localHPBuffer);
  949. raise;
  950. end;
  951. end
  952. else
  953. raise EPBuffer.Create('WGL_ARB_pbuffer support required.');
  954. CheckOpenGLError;
  955. finally
  956. DoDeactivate;
  957. end;
  958. finally
  959. shareRC := FShareContext;
  960. DoDestroyContext;
  961. FShareContext := shareRC;
  962. end;
  963. finally
  964. ReleaseDC(0, tempDC);
  965. DestroyWindow(tempWnd);
  966. FHPBUFFER := localHPBuffer;
  967. FDC := localDC;
  968. FRC := localRC;
  969. end;
  970. DescribePixelFormat(FDC, GetPixelFormat(FDC), SizeOf(pfDescriptor),
  971. pfDescriptor);
  972. if ((pfDescriptor.dwFlags and PFD_GENERIC_FORMAT) > 0) and
  973. (FAcceleration = chaHardware) then
  974. begin
  975. FAcceleration := chaSoftware;
  976. ShowMessage(strFailHWRC);
  977. end;
  978. Activate;
  979. InitOpenGL; ///FGL.Initialize;
  980. // If we are using AntiAliasing, adjust filtering hints
  981. if AntiAliasing in [aa2xHQ, aa4xHQ, csa8xHQ, csa16xHQ] then
  982. gxStates.MultisampleFilterHint := hintNicest
  983. else if AntiAliasing in [aa2x, aa4x, csa8x, csa16x] then
  984. gxStates.MultisampleFilterHint := hintFastest
  985. else
  986. gxStates.MultisampleFilterHint := hintDontCare;
  987. // Specific which color buffers are to be drawn into
  988. if BufferCount > 1 then
  989. glDrawBuffers(BufferCount, @MRT_BUFFERS);
  990. if (ServiceContext <> nil) and (Self <> ServiceContext) then
  991. begin
  992. if wglShareLists(TgxWinContext(ServiceContext).FRC, FRC) then
  993. begin
  994. FSharedContexts.Add(ServiceContext);
  995. PropagateSharedContext;
  996. end
  997. else
  998. ShowMessage('DoCreateContext - Failed to share contexts with resource context');
  999. end;
  1000. if Assigned(FShareContext) and (FShareContext.RC <> 0) then
  1001. begin
  1002. if not wglShareLists(FShareContext.RC, FRC) then
  1003. ShowMessage(strFailedToShare)
  1004. else
  1005. begin
  1006. FSharedContexts.Add(FShareContext);
  1007. PropagateSharedContext;
  1008. end;
  1009. end;
  1010. Deactivate;
  1011. if gxStates.ForwardContext then
  1012. ShowMessage('PBuffer ' + strFRC_created);
  1013. if bOES then
  1014. ShowMessage('PBuffer ' + strOESRC_created);
  1015. if not(gxStates.ForwardContext or bOES) then
  1016. ShowMessage(strPBufferRC_created);
  1017. end;
  1018. function TgxWinContext.DoShareLists(aContext: TgxContext): Boolean;
  1019. begin
  1020. if aContext is TgxWinContext then
  1021. begin
  1022. FShareContext := TgxWinContext(aContext);
  1023. if FShareContext.RC <> 0 then
  1024. Result := wglShareLists(FShareContext.RC, RC)
  1025. else
  1026. Result := False;
  1027. end
  1028. else
  1029. raise Exception.Create(strIncompatibleContexts);
  1030. end;
  1031. procedure TgxWinContext.DoDestroyContext;
  1032. begin
  1033. if vUseWindowTrackingHook then
  1034. UnTrackWindow(WindowFromDC(FDC));
  1035. if FHPBUFFER <> 0 then
  1036. begin
  1037. wglReleasePBufferDCARB(FHPBUFFER, FDC);
  1038. wglDestroyPBufferARB(FHPBUFFER);
  1039. FHPBUFFER := 0;
  1040. end;
  1041. if FRC <> 0 then
  1042. if not wglDeleteContext(FRC) then
  1043. ShowMessage(Format(strDeleteContextFailed,
  1044. [GetLastError, SysErrorMessage(GetLastError)]));
  1045. FRC := 0;
  1046. FDC := 0;
  1047. FShareContext := nil;
  1048. end;
  1049. procedure TgxWinContext.DoActivate;
  1050. begin
  1051. if not wglMakeCurrent(FDC, FRC) then
  1052. begin
  1053. ShowMessage(Format(strContextActivationFailed,
  1054. [GetLastError, SysErrorMessage(GetLastError)]));
  1055. Abort;
  1056. end;
  1057. if not LoadOpenGL then
  1058. InitOpenGL; ///FGL.Initialize(CurrentVXContext = nil);
  1059. end;
  1060. procedure TgxWinContext.DoDeactivate;
  1061. begin
  1062. if not wglMakeCurrent(0, 0) then
  1063. begin
  1064. ShowMessage(Format(strContextDeactivationFailed,
  1065. [GetLastError, SysErrorMessage(GetLastError)]));
  1066. Abort;
  1067. end;
  1068. end;
  1069. function TgxWinContext.IsValid: Boolean;
  1070. begin
  1071. Result := (FRC <> 0);
  1072. end;
  1073. procedure TgxWinContext.SwapBuffers;
  1074. begin
  1075. if (FDC <> 0) and (rcoDoubleBuffered in Options) then
  1076. if FSwapBufferSupported then
  1077. begin
  1078. case Layer of
  1079. clUnderlay2:
  1080. wglSwapLayerBuffers(FDC, WGL_SWAP_UNDERLAY2);
  1081. clUnderlay1:
  1082. wglSwapLayerBuffers(FDC, WGL_SWAP_UNDERLAY1);
  1083. clMainPlane: SwapBuffers(); /// Vcl - SwapBuffers(FDC)
  1084. clOverlay1:
  1085. wglSwapLayerBuffers(FDC, WGL_SWAP_OVERLAY1);
  1086. clOverlay2:
  1087. wglSwapLayerBuffers(FDC, WGL_SWAP_OVERLAY2);
  1088. end;
  1089. end
  1090. else
  1091. SwapBuffers(); /// Vcl - SwapBuffers(FDC);
  1092. end;
  1093. function TgxWinContext.RenderOutputDevice: Pointer;
  1094. begin
  1095. Result := Pointer(FDC);
  1096. end;
  1097. initialization // ------------------------------------------------------------
  1098. RegisterContextClass(TgxWinContext);
  1099. end.