GLS.WindowsContext.pas 36 KB

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