zgl_opengl.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. {
  2. * Copyright (c) 2012 Andrey Kemka
  3. *
  4. * This software is provided 'as-is', without any express or
  5. * implied warranty. In no event will the authors be held
  6. * liable for any damages arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute
  10. * it freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented;
  13. * you must not claim that you wrote the original software.
  14. * If you use this software in a product, an acknowledgment
  15. * in the product documentation would be appreciated but
  16. * is not required.
  17. *
  18. * 2. Altered source versions must be plainly marked as such,
  19. * and must not be misrepresented as being the original software.
  20. *
  21. * 3. This notice may not be removed or altered from any
  22. * source distribution.
  23. !!! modification from Serge 26.02.2022
  24. }
  25. unit zgl_opengl;
  26. {$I zgl_config.cfg}
  27. {$I GLdefine.cfg}
  28. {$IfDef MAC_COCOA}
  29. {$modeswitch objectivec1}
  30. {$EndIf}
  31. {$IFDEF UNIX}
  32. {$DEFINE stdcall := cdecl}
  33. {$ENDIF}
  34. interface
  35. uses
  36. zgl_opengl_all,
  37. zgl_pasOpenGL,
  38. zgl_gltypeconst,
  39. {$IFDEF LINUX}
  40. X, XUtil, xlib,
  41. zgl_glx_wgl
  42. {$ENDIF}
  43. {$IFDEF WINDOWS}
  44. Windows,
  45. zgl_glx_wgl
  46. {$ENDIF}
  47. {$IFDEF MACOSX}{$IfDef MAC_COCOA}
  48. CocoaAll,
  49. {$EndIf}
  50. MacOSAll
  51. {$ENDIF}
  52. ;
  53. const
  54. TARGET_SCREEN = 1; // цель - экран
  55. TARGET_TEXTURE = 2; // цель - часть экрана
  56. // Rus: инициализация OpenGL и подготовка формата пиксела.
  57. // Eng:
  58. function gl_Create: Boolean;
  59. {$IfNDef MAC_COCOA}
  60. // Rus: уничтожение контекста.
  61. // Eng:
  62. procedure gl_Destroy;
  63. {$EndIf}
  64. // Rus: создание контекста.
  65. // Eng:
  66. function gl_Initialize: Boolean;
  67. // Rus: возвращение к первоначальным заданным данным.
  68. // Eng:
  69. procedure gl_ResetState;
  70. // Rus: проверка и загрузка расширений.
  71. // Eng:
  72. procedure gl_LoadEx;
  73. var
  74. oglzDepth : LongWord;
  75. oglStencil : LongWord;
  76. oglFSAA : LongWord;
  77. oglAnisotropy: LongWord;
  78. oglFOVY : Single = 45;
  79. oglzNear : Single = 0.1;
  80. oglzFar : Single = 100;
  81. oglMode : Integer = 2; // 2D/3D Modes
  82. oglTarget : Integer = TARGET_SCREEN;
  83. oglTargetW: Integer;
  84. oglTargetH: Integer;
  85. oglWidth : Integer;
  86. oglHeight : Integer;
  87. oglVRAMUsed: LongWord;
  88. oglRenderer : UTF8String;
  89. oglExtensions : UTF8String;
  90. ogl3DAccelerator: Boolean;
  91. oglCanVSync : Boolean;
  92. oglCanFBO : Boolean;
  93. oglCanPBuffer : Boolean; // для MacOS доделать!!!
  94. oglMaxTexSize : Integer;
  95. oglMaxFBOSize : Integer;
  96. oglMaxAnisotropy: Integer;
  97. oglMaxTexUnits : Integer;
  98. oglSeparate : Boolean;
  99. maxGLVerMajor : Integer = 2;
  100. maxGLVerMinor : Integer = 1;
  101. // переделать
  102. contextAttr : array[0..9] of Integer;
  103. contextFlags : LongWord = 2;
  104. contextMask : LongWord = 2;
  105. oldContext : Boolean = true;
  106. {$IFDEF LINUX}
  107. oglXExtensions: UTF8String;
  108. oglPBufferMode: Integer;
  109. oglContext : GLXContext;
  110. oglVisualInfo : PXVisualInfo;
  111. oglFBConfig : GLXFBConfig;
  112. oglAttr : array[0..31] of Integer = (GLX_RGBA, GL_TRUE, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8,
  113. GLX_DOUBLEBUFFER, GL_TRUE, GLX_DEPTH_SIZE, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  114. {$IfDef GL_VERSION_3_0}
  115. glxAttr : array[0..26] of GLint = (GLX_X_RENDERABLE, GL_TRUE,
  116. GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
  117. GLX_RENDER_TYPE, GLX_RGBA_BIT,
  118. GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
  119. GLX_RED_SIZE, 8,
  120. GLX_GREEN_SIZE, 8,
  121. GLX_BLUE_SIZE, 8,
  122. GLX_ALPHA_SIZE, 8,
  123. GLX_DEPTH_SIZE, 24,
  124. GLX_DOUBLEBUFFER, GL_TRUE,
  125. 0, 0, 0, 0, 0, 0, 0);
  126. {$ENDIF}{$EndIf}
  127. {$IFDEF WINDOWS}
  128. oWGLExtensions: UTF8String;
  129. oglContext : HGLRC;
  130. oglfAttr : array[0..1 ] of Single = (0, 0);
  131. ogliAttr : array[0..31] of Integer = (WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
  132. WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
  133. WGL_COLOR_BITS_ARB, 24, WGL_RED_BITS_ARB, 8, WGL_GREEN_BITS_ARB, 8, WGL_BLUE_BITS_ARB, 8,
  134. WGL_ALPHA_BITS_ARB, 8, WGL_DEPTH_BITS_ARB, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  135. oglFormat : Integer;
  136. oglFormats : LongWord;
  137. oglFormatDesc: TPixelFormatDescriptor;
  138. {$ENDIF}
  139. {$IFDEF MACOSX}{$IfDef MAC_COCOA}
  140. oglContext : NSOpenGLContext;
  141. oglCoreGL : Integer;
  142. oglAttr : array[0..9] of NSOpenGLPixelFormatAttribute = (NSOpenGLPFADoubleBuffer, NSOpenGLPFAColorSize, 32, NSOpenGLPFADepthSize, 32,
  143. NSOpenGLPFAStencilSize, 8, NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy, 0);
  144. {$Else}
  145. oglDevice : GDHandle;
  146. oglContext : TAGLContext;
  147. oglFormat : TAGLPixelFormat;
  148. oglAttr : array[0..31] of LongWord;
  149. {$ENDIF}{$EndIf}
  150. implementation
  151. uses
  152. zgl_screen,
  153. zgl_window,
  154. zgl_log,
  155. zgl_utils;
  156. function gl_Create: Boolean;
  157. var
  158. i, j: Integer;
  159. {$IfDef LINUX}
  160. FBConfig: GLXFBConfig;
  161. PFBConfig: PGLXFBConfig;
  162. fbcount: Integer = 0;
  163. samp_buf: Integer = 0;
  164. samples: Integer = 0;
  165. best_FBconf: Integer = -1;
  166. worst_FBconf: Integer = -1;
  167. best_num_samp: Integer = -1;
  168. worst_num_samp: Integer = 9999;
  169. {$EndIf}
  170. {$IFDEF WINDOWS}
  171. pixelFormat: Integer;
  172. {$ENDIF}
  173. begin
  174. Result := FALSE;
  175. if not InitGL() Then
  176. begin
  177. log_Add('Cannot load GL library');
  178. exit;
  179. end;
  180. {$IFDEF LINUX}
  181. glXGetProcAddressARB := gl_GetProc('glXGetProcAddress');
  182. Init_GLX_WGL;
  183. if not glXQueryExtension(scrDisplay, i, j) Then
  184. begin
  185. u_Error('GLX Extension not found');
  186. exit;
  187. end
  188. else
  189. log_Add('GLX Extension - ok');
  190. // PBUFFER or OpenGL 3+
  191. if GLX_VERSION_1_4 or GLX_VERSION_1_3 then
  192. oglPBufferMode := 1
  193. else
  194. if GLX_SGIX_fbconfig and GLX_SGIX_pbuffer Then
  195. oglPBufferMode := 2
  196. else
  197. oglPBufferMode := 0;
  198. oglCanPBuffer := oglPBufferMode <> 0;
  199. if oglPBufferMode = 2 Then
  200. log_Add('GLX_SGIX_PBUFFER: TRUE')
  201. else
  202. log_Add('GLX_PBUFFER: ' + u_BoolToStr(oglCanPBuffer));
  203. case oglPBufferMode of
  204. 1:
  205. begin
  206. glXGetVisualFromFBConfig := gl_GetProc('glXGetVisualFromFBConfig');
  207. glXChooseFBConfig := gl_GetProc('glXChooseFBConfig');
  208. glXCreatePbuffer := gl_GetProc('glXCreatePbuffer');
  209. glXDestroyPbuffer := gl_GetProc('glXDestroyPbuffer');
  210. end;
  211. 2:
  212. begin
  213. glXGetVisualFromFBConfig := gl_GetProc('glXGetVisualFromFBConfigSGIX');
  214. glXChooseFBConfig := gl_GetProc('glXChooseFBConfigSGIX');
  215. glXCreateGLXPbufferSGIX := gl_GetProc('glXCreateGLXPbufferSGIX');
  216. glXDestroyGLXPbufferSGIX := gl_GetProc('glXDestroyGLXPbufferSGIX');
  217. end;
  218. end;
  219. {$IfDef GL_VERSION_3_0}
  220. if maxGLVerMajor >= 3 then
  221. begin
  222. oldContext := False;
  223. i := 20;
  224. FillChar(glxAttr[20], 5 * 4, None);
  225. if oglStencil > 0 then
  226. begin
  227. glxAttr[i] := GLX_STENCIL_SIZE;
  228. glxAttr[i + 1] := oglStencil;
  229. inc(i, 2);
  230. end;
  231. if oglFSAA > 0 then
  232. begin
  233. glxAttr[i] := GLX_SAMPLES_SGIS;
  234. glxAttr[i + 1] := oglFSAA;
  235. end;
  236. PFBConfig := @FBConfig;
  237. PFBConfig := glXChooseFBConfig(scrDisplay, scrDefault, @glxAttr[0], fbcount);
  238. if not Assigned(PFBConfig) or (fbcount = 0) then
  239. begin
  240. log_Add('Attribs for OpenGL 3+ not used.');
  241. //exit; //????
  242. end;
  243. for i := 0 to fbcount - 1 do
  244. begin
  245. oglVisualInfo := glXGetVisualFromFBConfig(scrDisplay, PFBConfig[i]);
  246. if Assigned(oglVisualInfo) then
  247. begin
  248. glXGetFBConfigAttrib(scrDisplay, PFBConfig[i], GLX_SAMPLE_BUFFERS, samp_buf);
  249. glXGetFBConfigAttrib(scrDisplay, PFBConfig[i], GLX_SAMPLES, samples);
  250. if (best_FBconf < 0) or ((samp_buf and samples) > best_num_samp) then
  251. begin
  252. best_FBconf := i;
  253. best_num_samp := samples;
  254. end;
  255. if (worst_FBconf < 0) or ((not samp_buf or samples) < worst_num_samp) then
  256. begin
  257. worst_FBconf := i;
  258. worst_num_samp := samples;
  259. end;
  260. end;
  261. XFree(oglVisualInfo);
  262. end;
  263. oglFBConfig := PFBConfig[best_FBconf];
  264. XFree(PFBConfig);
  265. oglVisualInfo := glXGetVisualFromFBConfig(scrDisplay, oglFBConfig);
  266. if not Assigned(oglVisualInfo) then
  267. begin
  268. log_Add('Could not create correct visual window fo OpenGL 3+.');
  269. oldContext := true;
  270. end;
  271. if scrDefault <> oglVisualInfo^.screen then
  272. begin
  273. log_Add('screenID(' + u_IntToStr(scrDefault) + ') does not match visual->screen(' + u_IntToStr(oglVisualInfo^.screen) + ').');
  274. oldContext := true;
  275. end;
  276. end;
  277. {$EndIf}
  278. if oldContext then
  279. begin
  280. // for old context
  281. oglzDepth := 24;
  282. repeat
  283. FillChar(oglAttr[14], (32 - 14) * 4, None);
  284. i := 14;
  285. if oglStencil > 0 Then
  286. begin
  287. oglAttr[i] := GLX_STENCIL_SIZE;
  288. oglAttr[i + 1] := oglStencil;
  289. INC(i, 2);
  290. end;
  291. if oglFSAA > 0 Then
  292. begin
  293. oglAttr[i] := GLX_SAMPLES_SGIS;
  294. oglAttr[i + 1] := oglFSAA;
  295. end;
  296. log_Add('glXChooseVisual: zDepth = ' + u_IntToStr(oglzDepth) + '; ' + 'stencil = ' + u_IntToStr(oglStencil) + '; ' + 'fsaa = ' + u_IntToStr(oglFSAA));
  297. oglVisualInfo := glXChooseVisual(scrDisplay, scrDefault, @oglAttr[0]);
  298. if (not Assigned(oglVisualInfo) and (oglzDepth = 1)) Then
  299. begin
  300. if oglFSAA = 0 Then
  301. break
  302. else
  303. begin
  304. oglzDepth := 24;
  305. DEC(oglFSAA, 2);
  306. end;
  307. end else
  308. if not Assigned(oglVisualInfo) Then
  309. DEC(oglzDepth, 8);
  310. if oglzDepth = 0 Then
  311. oglzDepth := 1;
  312. until Assigned(oglVisualInfo);
  313. end;
  314. if not Assigned(oglVisualInfo) Then
  315. begin
  316. u_Error('Cannot choose visual info.');
  317. exit;
  318. end;
  319. {$ENDIF}
  320. {$IFDEF WINDOWS}
  321. wnd_Create();
  322. FillChar(oglFormatDesc, SizeOf(TPixelFormatDescriptor), 0);
  323. with oglFormatDesc do
  324. begin
  325. nSize := SizeOf(TPIXELFORMATDESCRIPTOR);
  326. nVersion := 1;
  327. dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
  328. iPixelType := PFD_TYPE_RGBA;
  329. cColorBits := 24;
  330. cAlphabits := 8;
  331. cDepthBits := 24;
  332. cStencilBits := oglStencil;
  333. iLayerType := PFD_MAIN_PLANE;
  334. end;
  335. pixelFormat := ChoosePixelFormat(wndDC, @oglFormatDesc);
  336. if pixelFormat = 0 Then
  337. begin
  338. u_Error('Cannot choose pixel format');
  339. exit;
  340. end;
  341. if not SetPixelFormat(wndDC, pixelFormat, @oglFormatDesc) Then
  342. begin
  343. u_Error('Cannot set pixel format');
  344. exit;
  345. end;
  346. oglContext := wglCreateContext(wndDC);
  347. if (oglContext = 0) Then
  348. begin
  349. u_Error('Cannot create OpenGL context');
  350. exit;
  351. end;
  352. if not wglMakeCurrent(wndDC, oglContext) Then
  353. begin
  354. u_Error('Cannot set current OpenGL context');
  355. exit;
  356. end;
  357. wglGetExtensionsStringARB := gl_GetProc('wglGetExtensionsString');
  358. if Assigned(wglGetExtensionsStringARB) then
  359. begin
  360. oWGLExtensions := wglGetExtensionsStringARB(wndDC);
  361. log_Add('All extensions: ' + oWGLExtensions);
  362. end;
  363. CheckGLVersion;
  364. log_Add(u_IntToStr(use_glMajorVer) + '.' + u_IntToStr(use_glMinorVer));
  365. oglExtensions := '';
  366. {$IfDef GL_VERSION_3_0}
  367. if use_glMajorVer >= 3 then
  368. begin
  369. if not Assigned(glGetStringi) then
  370. glGetStringi := gl_GetProc('glGetStringi');
  371. if Assigned(glGetStringi) then
  372. begin
  373. glGetIntegerv(GL_NUM_EXTENSIONS, @j);
  374. for i := 0 to j - 1 do
  375. oglExtensions := oglExtensions + PAnsiChar(glGetStringi(GL_EXTENSIONS, i)) + #32;
  376. end;
  377. end;
  378. {$EndIf}
  379. if oglExtensions = '' then
  380. oglExtensions := glGetString(GL_EXTENSIONS);
  381. log_Add(oglExtensions);
  382. Init_GLX_WGL;
  383. LoadOpenGL;
  384. wglChoosePixelFormatARB := gl_GetProc('wglChoosePixelFormat');
  385. if Assigned(wglChoosePixelFormatARB) Then
  386. begin
  387. oglzDepth := 24;
  388. repeat
  389. FillChar(ogliAttr[22], (32 - 22) * 4, 0);
  390. i := 22;
  391. if oglStencil > 0 Then
  392. begin
  393. ogliAttr[i] := WGL_STENCIL_BITS_ARB;
  394. ogliAttr[i + 1] := oglStencil;
  395. inc(i, 2);
  396. end;
  397. if oglFSAA > 0 Then
  398. begin
  399. ogliAttr[i] := WGL_SAMPLE_BUFFERS_ARB;
  400. ogliAttr[i + 1] := GL_TRUE;
  401. ogliAttr[i + 2] := WGL_SAMPLES_ARB;
  402. ogliAttr[i + 3] := oglFSAA;
  403. end;
  404. log_Add('wglChoosePixelFormatARB: zDepth = ' + u_IntToStr(oglzDepth) + '; ' + 'stencil = ' + u_IntToStr(oglStencil) + '; ' + 'fsaa = ' + u_IntToStr(oglFSAA));
  405. wglChoosePixelFormatARB(wndDC, @ogliAttr, @oglfAttr, 1, @oglFormat, @oglFormats);
  406. if (oglFormat = 0) and (oglzDepth < 16) Then
  407. begin
  408. if oglFSAA <= 0 Then
  409. break
  410. else
  411. begin
  412. oglzDepth := 24;
  413. DEC(oglFSAA, 2);
  414. end;
  415. end else
  416. DEC(oglzDepth, 8);
  417. until oglFormat <> 0;
  418. end;
  419. if oglFormat = 0 Then
  420. begin
  421. oglzDepth := 24;
  422. oglFSAA := 0;
  423. oglFormat := pixelFormat;
  424. log_Add('ChoosePixelFormat: zDepth = ' + u_IntToStr(oglzDepth) + '; ' + 'stencil = ' + u_IntToStr(oglStencil));
  425. end;
  426. wglMakeCurrent(wndDC, 0);
  427. wglDeleteContext(oglContext);
  428. wnd_Destroy();
  429. // wndFirst := FALSE;
  430. {$ENDIF}
  431. {$IFDEF MACOSX}{$IfDef MAC_COCOA}
  432. {$Else}
  433. if not InitAGL() Then
  434. begin
  435. log_Add('Cannot load AGL library');
  436. exit;
  437. end;
  438. oglzDepth := 24;
  439. repeat
  440. FillChar(oglAttr[0], Length(oglAttr) * 4, AGL_NONE);
  441. oglAttr[0] := AGL_RGBA;
  442. oglAttr[1] := AGL_RED_SIZE;
  443. oglAttr[2] := 8;
  444. oglAttr[3] := AGL_GREEN_SIZE;
  445. oglAttr[4] := 8;
  446. oglAttr[5] := AGL_BLUE_SIZE;
  447. oglAttr[6] := 8;
  448. oglAttr[7] := AGL_ALPHA_SIZE;
  449. oglAttr[8] := 8;
  450. oglAttr[9] := AGL_DOUBLEBUFFER;
  451. oglAttr[10] := AGL_DEPTH_SIZE;
  452. oglAttr[11] := oglzDepth;
  453. i := 12;
  454. if oglStencil > 0 Then
  455. begin
  456. oglAttr[i] := AGL_STENCIL_SIZE;
  457. oglAttr[i + 1] := oglStencil;
  458. inc(i, 2);
  459. end;
  460. if oglFSAA > 0 Then
  461. begin
  462. oglAttr[i] := AGL_SAMPLE_BUFFERS_ARB;
  463. oglAttr[i + 1] := 1;
  464. oglAttr[i + 2] := AGL_SAMPLES_ARB;
  465. oglAttr[i + 3] := oglFSAA;
  466. end;
  467. log_Add('aglChoosePixelFormat: zDepth = ' + u_IntToStr(oglzDepth) + '; ' + 'stencil = ' + u_IntToStr(oglStencil) + '; ' + 'fsaa = ' + u_IntToStr(oglFSAA));
  468. DMGetGDeviceByDisplayID(DisplayIDType(scrDisplay), oglDevice, FALSE);
  469. oglFormat := aglChoosePixelFormat(@oglDevice, 1, @oglAttr[0]);
  470. if (not Assigned(oglFormat) and (oglzDepth = 1)) Then
  471. begin
  472. if oglFSAA = 0 Then
  473. break
  474. else
  475. begin
  476. oglzDepth := 24;
  477. DEC(oglFSAA, 2);
  478. end;
  479. end else
  480. if not Assigned(oglFormat) Then
  481. DEC(oglzDepth, 8);
  482. if oglzDepth = 0 Then
  483. oglzDepth := 1;
  484. until Assigned(oglFormat);
  485. if not Assigned(oglFormat) Then
  486. begin
  487. u_Error('Cannot choose pixel format.');
  488. exit;
  489. end;
  490. {$ENDIF}{$EndIf}
  491. Result := TRUE;
  492. end;
  493. {$IfNDef MAC_COCOA}
  494. procedure gl_Destroy;
  495. begin
  496. {$IFDEF LINUX}
  497. if not glXMakeCurrent(scrDisplay, None, nil) Then
  498. u_Error('Cannot release current OpenGL context');
  499. glXDestroyContext(scrDisplay, oglContext);
  500. {$ENDIF}
  501. {$IFDEF WINDOWS}
  502. if not wglMakeCurrent(wndDC, 0) Then
  503. u_Error('Cannot release current OpenGL context');
  504. wglDeleteContext(oglContext);
  505. {$ENDIF}
  506. {$IFDEF MACOSX}
  507. aglDestroyPixelFormat(oglFormat);
  508. if aglSetCurrentContext(nil) = GL_FALSE Then
  509. u_Error('Cannot release current OpenGL context');
  510. aglDestroyContext(oglContext);
  511. FreeAGL();
  512. {$ENDIF}
  513. FreeGL();
  514. end;
  515. {$EndIf}
  516. function gl_Initialize: Boolean;
  517. {$IfDef MAC_COCOA}
  518. var
  519. pixfmt: NSOpenGLPixelFormat;
  520. {$EndIf}
  521. begin
  522. Result := FALSE;
  523. {$IFDEF LINUX}
  524. if oldContext then
  525. begin
  526. oglContext := glXCreateContext(scrDisplay, oglVisualInfo, nil, GL_TRUE);
  527. if not Assigned(oglContext) Then
  528. begin
  529. oglContext := glXCreateContext(scrDisplay, oglVisualInfo, nil, GL_FALSE);
  530. if not Assigned(oglContext) Then
  531. begin
  532. u_Error('Cannot create OpenGL context');
  533. exit;
  534. end;
  535. end;
  536. end {$IfDef GL_VERSION_3_0}
  537. else begin
  538. contextAttr[0] := GLX_CONTEXT_MAJOR_VERSION_ARB;
  539. contextAttr[1] := maxGLVerMajor;
  540. contextAttr[2] := GLX_CONTEXT_MINOR_VERSION_ARB;
  541. contextAttr[3] := maxGLVerMinor;
  542. contextAttr[4] := GLX_CONTEXT_FLAGS_ARB;
  543. contextAttr[5] := contextFlags;
  544. contextAttr[6] := GLX_CONTEXT_PROFILE_MASK_ARB;
  545. contextAttr[7] := contextMask;
  546. contextAttr[8] := 0;
  547. if GLX_ARB_create_context then
  548. begin
  549. oglContext := glXCreateContextAttribsARB(scrDisplay, oglFBConfig, nil, true, @contextAttr[0]);
  550. if not Assigned(oglContext) then
  551. oglContext := glXCreateContextAttribsARB(scrDisplay, oglFBConfig, nil, false, @contextAttr[0]);
  552. if not Assigned(oglContext) Then
  553. begin
  554. u_Error('Cannot create OpenGL context');
  555. exit;
  556. end;
  557. end
  558. else begin
  559. oglContext := glXCreateNewContext(scrDisplay, oglFBConfig, GLX_RGBA_TYPE, nil, GL_TRUE);
  560. if not Assigned(oglContext) then
  561. oglContext := glXCreateNewContext(scrDisplay, oglFBConfig, GLX_RGBA_TYPE, nil, GL_FALSE);
  562. if not Assigned(oglContext) Then
  563. begin
  564. u_Error('Cannot create OpenGL context');
  565. exit;
  566. end;
  567. end;
  568. end{$EndIf};
  569. if not glXMakeCurrent(scrDisplay, wndHandle, oglContext) Then
  570. begin
  571. u_Error('Cannot set current OpenGL context');
  572. exit;
  573. end;
  574. CheckGLVersion;
  575. LoadOpenGL;
  576. {$ENDIF}
  577. {$IFDEF WINDOWS}
  578. if not SetPixelFormat(wndDC, oglFormat, @oglFormatDesc) Then
  579. begin
  580. u_Error('Cannot set pixel format');
  581. exit;
  582. end;
  583. oglContext := 0;
  584. {$IfDef GL_VERSION_3_0}
  585. if GL_VERSION_3_0 and Assigned(wglCreateContextAttribsARB) then
  586. begin
  587. contextAttr[0] := WGL_CONTEXT_MAJOR_VERSION_ARB;
  588. contextAttr[1] := use_glMajorVer;
  589. contextAttr[2] := WGL_CONTEXT_MINOR_VERSION_ARB;
  590. contextAttr[3] := use_glMinorVer;
  591. contextAttr[4] := WGL_CONTEXT_PROFILE_MASK_ARB;
  592. contextAttr[5] := contextMask;
  593. contextAttr[6] := WGL_CONTEXT_FLAGS_ARB;
  594. contextAttr[7] := contextFlags;
  595. contextAttr[8] := 0;
  596. oglContext := wglCreateContextAttribsARB(wndDC, 0, @contextAttr[0]);
  597. end;
  598. if oglContext = 0 then
  599. begin
  600. if (GL_ARB_compatibility and (use_glMajorVer >= 3)) or (use_glMajorVer <= 2) then
  601. oglContext := wglCreateContext(wndDC)
  602. else begin
  603. u_Error('Cannot create OpenGL context 3+');
  604. Exit;
  605. end;
  606. end;
  607. {$Else}
  608. oglContext := wglCreateContext(wndDC);
  609. {$EndIf}
  610. if (oglContext = 0) Then
  611. begin
  612. u_Error('Cannot create OpenGL context');
  613. exit;
  614. end;
  615. if not wglMakeCurrent(wndDC, oglContext) Then
  616. begin
  617. u_Error('Cannot set current OpenGL context');
  618. exit;
  619. end;
  620. {$ENDIF}
  621. {$IFDEF MACOSX}{$IfDef MAC_COCOA}
  622. pixfmt := NSOpenGLPixelFormat.alloc.initWithAttributes(@oglAttr);
  623. oglContext := NSOpenGLContext.alloc.initWithFormat_shareContext(pixfmt, nil);
  624. pixfmt.release;
  625. oglContext.makeCurrentContext;
  626. oglContext.setView(zglView);
  627. {$Else}
  628. oglContext := aglCreateContext(oglFormat, nil);
  629. if not Assigned(oglContext) Then
  630. begin
  631. u_Error('Cannot create OpenGL context');
  632. exit;
  633. end;
  634. if aglSetDrawable(oglContext, GetWindowPort(wndHandle)) = GL_FALSE Then
  635. begin
  636. u_Error('Cannot set Drawable');
  637. exit;
  638. end;
  639. if aglSetCurrentContext(oglContext) = GL_FALSE Then
  640. begin
  641. u_Error('Cannot set current OpenGL context');
  642. exit;
  643. end;
  644. {$ENDIF}{$EndIf}
  645. oglRenderer := glGetString(GL_RENDERER);
  646. log_Add('GL_VERSION: ' + glGetString(GL_VERSION));
  647. log_Add('GL_RENDERER: ' + oglRenderer);
  648. {$IFDEF LINUX}
  649. ogl3DAccelerator := oglRenderer <> 'Software Rasterizer';
  650. {$ENDIF}
  651. {$IFDEF WINDOWS}
  652. ogl3DAccelerator := oglRenderer <> 'GDI Generic';
  653. {$ENDIF}
  654. {$IFDEF MACOSX}
  655. ogl3DAccelerator := oglRenderer <> 'Apple Software Renderer';
  656. {$ENDIF}
  657. if not ogl3DAccelerator Then
  658. u_Warning('Cannot find 3D-accelerator! Application run in software-mode, it''s very slow');
  659. gl_LoadEx();
  660. gl_ResetState();
  661. Result := TRUE;
  662. end;
  663. procedure gl_ResetState;
  664. begin
  665. glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  666. glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
  667. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  668. glHint(GL_FOG_HINT, GL_DONT_CARE);
  669. glShadeModel(GL_SMOOTH);
  670. glClearColor(0, 0, 0, 0);
  671. glDepthFunc (GL_LEQUAL);
  672. glClearDepth(1.0);
  673. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  674. glAlphaFunc(GL_GREATER, 0);
  675. if oglSeparate Then
  676. begin
  677. glBlendEquation(GL_FUNC_ADD_EXT);
  678. glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  679. end;
  680. glDisable(GL_BLEND);
  681. glDisable(GL_ALPHA_TEST);
  682. glDisable(GL_DEPTH_TEST);
  683. glDisable(GL_TEXTURE_2D);
  684. glEnable (GL_NORMALIZE);
  685. end;
  686. procedure gl_LoadEx;
  687. begin
  688. // Texture size
  689. glGetIntegerv(GL_MAX_TEXTURE_SIZE, @oglMaxTexSize);
  690. log_Add('GL_MAX_TEXTURE_SIZE: ' + u_IntToStr(oglMaxTexSize));
  691. glCompressedTexImage2D := gl_GetProc('glCompressedTexImage2D');
  692. log_Add('GL_EXT_TEXTURE_COMPRESSION_S3TC: ' + u_BoolToStr(GL_EXT_texture_compression_s3tc));
  693. log_Add('GL_SGIS_GENERATE_MIPMAP: ' + u_BoolToStr(GL_SGIS_generate_mipmap));
  694. // Multitexturing
  695. glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @oglMaxTexUnits);
  696. log_Add('GL_MAX_TEXTURE_UNITS_ARB: ' + u_IntToStr(oglMaxTexUnits));
  697. // Anisotropy
  698. if GL_EXT_texture_filter_anisotropic Then
  699. begin
  700. glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @oglMaxAnisotropy);
  701. oglAnisotropy := oglMaxAnisotropy;
  702. end else
  703. oglAnisotropy := 0;
  704. log_Add('GL_EXT_TEXTURE_FILTER_ANISOTROPIC: ' + u_BoolToStr(GL_EXT_texture_filter_anisotropic));
  705. log_Add('GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: ' + u_IntToStr(oglMaxAnisotropy));
  706. glBlendEquation := gl_GetProc('glBlendEquation');
  707. glBlendFuncSeparate := gl_GetProc('glBlendFuncSeparate');
  708. // separator
  709. oglSeparate := Assigned(glBlendEquation) and Assigned(glBlendFuncSeparate) and GL_EXT_blend_func_separate;
  710. log_Add('GL_EXT_BLEND_FUNC_SEPARATE: ' + u_BoolToStr(oglSeparate));
  711. // FBO
  712. glBindRenderbuffer := gl_GetProc('glBindRenderbuffer');
  713. if Assigned(glBindRenderbuffer) Then
  714. begin
  715. oglCanFBO := TRUE;
  716. glIsRenderbuffer := gl_GetProc('glIsRenderbuffer' );
  717. glDeleteRenderbuffers := gl_GetProc('glDeleteRenderbuffers' );
  718. glGenRenderbuffers := gl_GetProc('glGenRenderbuffers' );
  719. glRenderbufferStorage := gl_GetProc('glRenderbufferStorage' );
  720. glIsFramebuffer := gl_GetProc('glIsFramebuffer' );
  721. glBindFramebuffer := gl_GetProc('glBindFramebuffer' );
  722. glDeleteFramebuffers := gl_GetProc('glDeleteFramebuffers' );
  723. glGenFramebuffers := gl_GetProc('glGenFramebuffers' );
  724. glCheckFramebufferStatus := gl_GetProc('glCheckFramebufferStatus' );
  725. glFramebufferTexture2D := gl_GetProc('glFramebufferTexture2D' );
  726. glFramebufferRenderbuffer := gl_GetProc('glFramebufferRenderbuffer');
  727. glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, @oglMaxFBOSize);
  728. log_Add('GL_MAX_RENDERBUFFER_SIZE: ' + u_IntToStr(oglMaxFBOSize));
  729. end else
  730. oglCanFBO := FALSE;
  731. log_Add('GL_EXT_FRAMEBUFFER_OBJECT: ' + u_BoolToStr(oglCanFBO));
  732. {$IFDEF WINDOWS}
  733. if Assigned(wglCreatePbufferARB) and Assigned(wglChoosePixelFormatARB) Then
  734. begin
  735. oglCanPBuffer := TRUE;
  736. wglGetPbufferDCARB := gl_GetProc('wglGetPbufferDC' );
  737. wglReleasePbufferDCARB := gl_GetProc('wglReleasePbufferDC');
  738. wglDestroyPbufferARB := gl_GetProc('wglDestroyPbuffer' );
  739. wglQueryPbufferARB := gl_GetProc('wglQueryPbuffer');
  740. end else
  741. oglCanPBuffer := FALSE;
  742. log_Add('WGL_PBUFFER: ' + u_BoolToStr(oglCanPBuffer));
  743. {$ENDIF}
  744. {$IFDEF MACOSX}{$IfNDef MAC_COCOA}
  745. oglCanPBuffer := Assigned(aglCreatePBuffer);
  746. log_Add('AGL_PBUFFER: ' + u_BoolToStr(oglCanPBuffer));
  747. {$ENDIF}{$EndIf}
  748. // WaitVSync
  749. {$IFDEF LINUX}
  750. glXSwapIntervalSGI := gl_GetProc('glXSwapIntervalSGI');
  751. oglCanVSync := Assigned(glXSwapIntervalSGI);
  752. {$ENDIF}
  753. {$IFDEF WINDOWS}
  754. wglSwapIntervalEXT := gl_GetProc('wglSwapInterval');
  755. oglCanVSync := Assigned(wglSwapIntervalEXT);
  756. {$ENDIF}
  757. {$IFDEF MACOSX}{$IfNDef MAC_COCOA}
  758. if aglSetInt(oglContext, AGL_SWAP_INTERVAL, 1) = GL_TRUE Then
  759. oglCanVSync := TRUE
  760. else
  761. oglCanVSync := FALSE;
  762. aglSetInt(oglContext, AGL_SWAP_INTERVAL, Byte(scrVSync));
  763. {$ENDIF}{$EndIf}
  764. if oglCanVSync Then
  765. scr_VSync;
  766. log_Add('Support WaitVSync: ' + u_BoolToStr(oglCanVSync));
  767. end;
  768. end.