osxGL.mm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. // Many OSX frameworks include OpenTransport, and OT's new operator conflicts
  23. // with our redefinition of 'new', so we have to pre-include platformMacCarb.h,
  24. // which contains the workaround.
  25. #include <OpenGL/OpenGL.h>
  26. #include "platformOSX/platformOSX.h"
  27. #include "platformOSX/platformGL.h"
  28. #include "console/console.h"
  29. #include "graphics/dgl.h"
  30. GLState gGLState;
  31. bool gOpenGLDisablePT = false;
  32. bool gOpenGLDisableCVA = false;
  33. bool gOpenGLDisableTEC = false;
  34. bool gOpenGLDisableARBMT = false;
  35. bool gOpenGLDisableFC = true; //false;
  36. bool gOpenGLDisableTCompress = false;
  37. bool gOpenGLNoEnvColor = false;
  38. float gOpenGLGammaCorrection = 0.5;
  39. bool gOpenGLNoDrawArraysAlpha = false;
  40. //-----------------------------------------------------------------------------
  41. /// These stubs are legacy stuff for the d3d wrapper layer.
  42. // The code that requires these stubs should probably be ifdef'd out of any non w32 build
  43. //-----------------------------------------------------------------------------
  44. GLboolean glAvailableVertexBufferEXT() { return(false); }
  45. GLint glAllocateVertexBufferEXT(GLsizei size, GLint format, GLboolean preserve) { return(0); }
  46. void* glLockVertexBufferEXT(GLint handle, GLsizei size) { return(NULL); }
  47. void glUnlockVertexBufferEXT(GLint handle) {}
  48. void glSetVertexBufferEXT(GLint handle) {}
  49. void glOffsetVertexBufferEXT(GLint handle, GLuint offset) {}
  50. void glFillVertexBufferEXT(GLint handle, GLint first, GLsizei count) {}
  51. void glFreeVertexBufferEXT(GLint handle) {}
  52. //-----------------------------------------------------------------------------
  53. /// Change FSAA level.
  54. /// Currently, this will only work for ATI Radeon chipsets.
  55. /// On other chipsets, this has no effect.
  56. /// Pass in 1 for normal/no-AA, 2 for 2x-AA, 4 for 4x-AA.
  57. //-----------------------------------------------------------------------------
  58. void dglSetFSAASamples(GLint aasamp)
  59. {
  60. if (gGLState.maxFSAASamples < 2)
  61. return;
  62. // fix out of range values
  63. if (aasamp < 1)
  64. aasamp = 1;
  65. else if (aasamp == 3)
  66. aasamp = 2;
  67. else if (aasamp > 4)
  68. aasamp = 4;
  69. /*
  70. THIS IS CARBON
  71. aglSetInteger(platState.ctx, ATI_FSAA_LEVEL, &aasamp);
  72. IT NEEDS OT BE REPLACED WITH SOMETHING LIKE THIS:
  73. const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  74. if (strstr(glRenderer, "ATI"))
  75. {
  76. NSOpenGLContext* testContext; /// <<< Need to get ahold of the current context
  77. [testContext setValues:&aasamp forParameter:ATI_FSAA_LEVEL];
  78. }
  79. */
  80. Con::printf(">>Number of FSAA samples is now [%d].", aasamp);
  81. Con::setIntVariable("$pref::OpenGL::numFSAASamples", aasamp);
  82. }
  83. //-----------------------------------------------------------------------------
  84. // helper function for getGLCapabilities.
  85. // returns a new CGL context for platState.hDisplay
  86. CGLContextObj getContextForCapsCheck()
  87. {
  88. // silently create an opengl context on the current display, so that
  89. // we can get valid renderer and capability info
  90. // some of the following code is from:
  91. // http://developer.apple.com/technotes/tn2002/tn2080.html#TAN55
  92. osxPlatState * platState = [osxPlatState sharedPlatState];
  93. // From the CG display id, we can create a pixel format & context
  94. // and with that context we can check opengl capabilities
  95. CGOpenGLDisplayMask cglDisplayMask = CGDisplayIDToOpenGLDisplayMask([platState cgDisplay]);
  96. CGLPixelFormatAttribute attribs[] = {kCGLPFADisplayMask, (CGLPixelFormatAttribute)cglDisplayMask, (CGLPixelFormatAttribute) NULL};
  97. // create the pixel format. we will not use numPixelFormats, but the docs
  98. // do not say we're allowed to pass NULL for the 3rd arg.
  99. GLint numPixelFormats = 0;
  100. CGLPixelFormatObj pixelFormat = NULL;
  101. CGLChoosePixelFormat(attribs, &pixelFormat, &numPixelFormats);
  102. if (pixelFormat)
  103. {
  104. // create a context. we don't need the pixel format once the context is created.
  105. CGLContextObj ctx;
  106. CGLCreateContext(pixelFormat, NULL, &ctx);
  107. CGLDestroyPixelFormat(pixelFormat);
  108. if (ctx)
  109. return ctx;
  110. }
  111. // if we can't get a good context, we can't check caps... this won't be good.
  112. Con::errorf("getContextForCapsCheck could not create a cgl context on the display for gl capabilities checking!");
  113. return NULL;
  114. }
  115. // Find out which extensions are available for this renderer.
  116. void getGLCapabilities()
  117. {
  118. osxPlatState * platState;
  119. platState = [osxPlatState sharedPlatState];
  120. AssertFatal([platState cgDisplay], "getGLCapabilities() was called before a monitor was chosen!");
  121. // silently create an opengl context on the current display,
  122. // so that we can get valid renderer and capability info.
  123. // we save off the current context so that we can silently restore it.
  124. // the user should not be aware of this little shuffle.
  125. CGLContextObj curr_ctx = CGLGetCurrentContext ();
  126. CGLContextObj temp_ctx = getContextForCapsCheck();
  127. if (!temp_ctx)
  128. {
  129. Con::errorf("OpenGL may not be set up correctly!");
  130. return;
  131. }
  132. CGLSetCurrentContext(temp_ctx);
  133. // Get the OpenGL info strings we'll need
  134. const char* pVendString = (const char*) glGetString(GL_VENDOR);
  135. const char* pRendString = (const char*) glGetString(GL_RENDERER);
  136. const char* pVersString = (const char*) glGetString(GL_VERSION);
  137. const char* pExtString = (const char*) glGetString(GL_EXTENSIONS);
  138. // Output some driver info to the console:
  139. Con::printf("OpenGL driver information:");
  140. if (pVendString)
  141. Con::printf(" Vendor: %s", pVendString);
  142. if (pRendString)
  143. Con::printf(" Renderer: %s", pRendString);
  144. if (pVersString)
  145. Con::printf(" Version: %s", pVersString);
  146. // pre-clear the structure
  147. dMemset(&gGLState, 0, sizeof(gGLState));
  148. if (pExtString)
  149. {
  150. // EXT_paletted_texture ========================================
  151. if (dStrstr(pExtString, (const char*)"GL_EXT_paletted_texture") != NULL)
  152. gGLState.suppPalettedTexture = true;
  153. // EXT_compiled_vertex_array ========================================
  154. gGLState.suppLockedArrays = false;
  155. if (dStrstr(pExtString, (const char*)"GL_EXT_compiled_vertex_array") != NULL)
  156. gGLState.suppLockedArrays = true;
  157. // ARB_multitexture ========================================
  158. if (dStrstr(pExtString, (const char*)"GL_ARB_multitexture") != NULL)
  159. gGLState.suppARBMultitexture = true;
  160. // EXT_blend_color
  161. if (dStrstr(pExtString, (const char*)"GL_EXT_blend_color") != NULL)
  162. gGLState.suppEXTblendcolor = true;
  163. // EXT_blend_minmax
  164. if (dStrstr(pExtString, (const char*)"GL_EXT_blend_minmax") != NULL)
  165. gGLState.suppEXTblendminmax = true;
  166. // NV_vertex_array_range ========================================
  167. // does not appear to be supported by apple, at all. (as of 10.4.3)
  168. // GL_APPLE_vertex_array_range is similar, and may be nearly identical.
  169. if (dStrstr(pExtString, (const char*)"GL_NV_vertex_array_range") != NULL)
  170. gGLState.suppVertexArrayRange = true;
  171. // EXT_fog_coord ========================================
  172. if (dStrstr(pExtString, (const char*)"GL_EXT_fog_coord") != NULL)
  173. gGLState.suppFogCoord = true;
  174. // ARB_texture_compression ========================================
  175. if (dStrstr(pExtString, (const char*)"GL_ARB_texture_compression") != NULL)
  176. gGLState.suppTextureCompression = true;
  177. // 3DFX_texture_compression_FXT1 ========================================
  178. if (dStrstr(pExtString, (const char*)"GL_3DFX_texture_compression_FXT1") != NULL)
  179. gGLState.suppFXT1 = true;
  180. // EXT_texture_compression_S3TC ========================================
  181. if (dStrstr(pExtString, (const char*)"GL_EXT_texture_compression_s3tc") != NULL)
  182. gGLState.suppS3TC = true;
  183. // EXT_vertex_buffer ========================================
  184. // This extension is deprecated, and not supported by Apple. (10.4.3)
  185. // Instead, the ARB Vertex Buffer extension is supported.
  186. // The new extension has a different API, so TGE should be updated to use it.
  187. if (dStrstr(pExtString, (const char*)"GL_EXT_vertex_buffer") != NULL)
  188. gGLState.suppVertexBuffer = true;
  189. // Anisotropic filtering ========================================
  190. gGLState.suppTexAnisotropic = (dStrstr(pExtString, (const char*)"GL_EXT_texture_filter_anisotropic") != NULL);
  191. if (gGLState.suppTexAnisotropic)
  192. glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGLState.maxAnisotropy);
  193. // Binary states, i.e., no supporting functions ========================================
  194. // NOTE:
  195. // Some of these have multiple representations, via EXT and|or ARB and|or NV and|or SGIS ... etc.
  196. // Check all relative versions.
  197. gGLState.suppPackedPixels = (dStrstr(pExtString, (const char*)"GL_EXT_packed_pixels") != NULL);
  198. gGLState.suppPackedPixels |= (dStrstr(pExtString, (const char*)"GL_APPLE_packed_pixel") != NULL);
  199. gGLState.suppTextureEnvCombine = (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_combine") != NULL);
  200. gGLState.suppTextureEnvCombine |= (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_combine") != NULL);
  201. gGLState.suppEdgeClamp = (dStrstr(pExtString, (const char*)"GL_EXT_texture_edge_clamp") != NULL);
  202. gGLState.suppEdgeClamp |= (dStrstr(pExtString, (const char*)"GL_SGIS_texture_edge_clamp") != NULL);
  203. gGLState.suppEdgeClamp |= (dStrstr(pExtString, (const char*)"GL_ARB_texture_border_clamp") != NULL);
  204. gGLState.suppTexEnvAdd = (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_add") != NULL);
  205. gGLState.suppTexEnvAdd |= (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_add") != NULL);
  206. }
  207. // Texture combine units ========================================
  208. if (gGLState.suppARBMultitexture)
  209. glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gGLState.maxTextureUnits);
  210. else
  211. gGLState.maxTextureUnits = 1;
  212. // Swap interval ========================================
  213. // Mac inherently supports a swap interval via AGL-set-integer.
  214. gGLState.suppSwapInterval = true;
  215. // FSAA support, TODO: check for ARB multisample support
  216. // multisample support should be checked via CGL
  217. gGLState.maxFSAASamples = 4;
  218. // dump found extensions to the console...
  219. Con::printf("OpenGL Init: Enabled Extensions");
  220. if (gGLState.suppARBMultitexture)
  221. Con::printf(" ARB_multitexture (Max Texture Units: %d)", gGLState.maxTextureUnits);
  222. if (gGLState.suppEXTblendcolor)
  223. Con::printf(" EXT_blend_color");
  224. if (gGLState.suppEXTblendminmax)
  225. Con::printf(" EXT_blend_minmax");
  226. if (gGLState.suppPalettedTexture)
  227. Con::printf(" EXT_paletted_texture");
  228. if (gGLState.suppLockedArrays)
  229. Con::printf(" EXT_compiled_vertex_array");
  230. if (gGLState.suppVertexArrayRange)
  231. Con::printf(" NV_vertex_array_range");
  232. if (gGLState.suppTextureEnvCombine)
  233. Con::printf(" EXT_texture_env_combine");
  234. if (gGLState.suppPackedPixels)
  235. Con::printf(" EXT_packed_pixels");
  236. if (gGLState.suppFogCoord)
  237. Con::printf(" EXT_fog_coord");
  238. if (gGLState.suppTextureCompression)
  239. Con::printf(" ARB_texture_compression");
  240. if (gGLState.suppS3TC)
  241. Con::printf(" EXT_texture_compression_s3tc");
  242. if (gGLState.suppFXT1)
  243. Con::printf(" 3DFX_texture_compression_FXT1");
  244. if (gGLState.suppTexEnvAdd)
  245. Con::printf(" (ARB|EXT)_texture_env_add");
  246. if (gGLState.suppTexAnisotropic)
  247. Con::printf(" EXT_texture_filter_anisotropic (Max anisotropy: %f)", gGLState.maxAnisotropy);
  248. if (gGLState.suppSwapInterval)
  249. Con::printf(" Vertical Sync");
  250. if (gGLState.maxFSAASamples)
  251. Con::printf(" ATI_FSAA");
  252. Con::warnf("OpenGL Init: Disabled Extensions");
  253. if (!gGLState.suppARBMultitexture)
  254. Con::warnf(" ARB_multitexture");
  255. if (!gGLState.suppEXTblendcolor)
  256. Con::warnf(" EXT_blend_color");
  257. if (!gGLState.suppEXTblendminmax)
  258. Con::warnf(" EXT_blend_minmax");
  259. if (!gGLState.suppPalettedTexture)
  260. Con::warnf(" EXT_paletted_texture");
  261. if (!gGLState.suppLockedArrays)
  262. Con::warnf(" EXT_compiled_vertex_array");
  263. if (!gGLState.suppVertexArrayRange)
  264. Con::warnf(" NV_vertex_array_range");
  265. if (!gGLState.suppTextureEnvCombine)
  266. Con::warnf(" EXT_texture_env_combine");
  267. if (!gGLState.suppPackedPixels)
  268. Con::warnf(" EXT_packed_pixels");
  269. if (!gGLState.suppFogCoord)
  270. Con::warnf(" EXT_fog_coord");
  271. if (!gGLState.suppTextureCompression)
  272. Con::warnf(" ARB_texture_compression");
  273. if (!gGLState.suppS3TC)
  274. Con::warnf(" EXT_texture_compression_s3tc");
  275. if (!gGLState.suppFXT1)
  276. Con::warnf(" 3DFX_texture_compression_FXT1");
  277. if (!gGLState.suppTexEnvAdd)
  278. Con::warnf(" (ARB|EXT)_texture_env_add");
  279. if (!gGLState.suppTexAnisotropic)
  280. Con::warnf(" EXT_texture_filter_anisotropic");
  281. if (!gGLState.suppSwapInterval)
  282. Con::warnf(" Vertical Sync");
  283. if (!gGLState.maxFSAASamples)
  284. Con::warnf(" ATI_FSAA");
  285. Con::printf("");
  286. // Set some console variables:
  287. Con::setBoolVariable("$FogCoordSupported", gGLState.suppFogCoord);
  288. Con::setBoolVariable("$TextureCompressionSupported", gGLState.suppTextureCompression);
  289. Con::setBoolVariable("$AnisotropySupported", gGLState.suppTexAnisotropic);
  290. Con::setBoolVariable("$PalettedTextureSupported", gGLState.suppPalettedTexture);
  291. Con::setBoolVariable("$SwapIntervalSupported", gGLState.suppSwapInterval);
  292. if (!gGLState.suppPalettedTexture && Con::getBoolVariable("$pref::OpenGL::forcePalettedTexture",false))
  293. {
  294. Con::setBoolVariable("$pref::OpenGL::forcePalettedTexture", false);
  295. Con::setBoolVariable("$pref::OpenGL::force16BitTexture", true);
  296. }
  297. // get fsaa samples. default to normal, no antialiasing
  298. // TODO: clamp this against ARB_multisample capabilities.
  299. gFSAASamples = Con::getIntVariable("$pref::OpenGL::numFSAASamples", 1);
  300. // done. silently restore the old cgl context.
  301. CGLSetCurrentContext(curr_ctx);
  302. CGLDestroyContext(temp_ctx);
  303. }