x86UNIXGL.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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. #include "platformX86UNIX/platformGL.h"
  23. #include "platformX86UNIX/platformX86UNIX.h"
  24. #include "console/console.h"
  25. #include "math/mMatrix.h"
  26. #include "math/mPoint.h"
  27. #include <dlfcn.h>
  28. #include <SDL/SDL.h>
  29. // declare stub functions
  30. #define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_return stub_##fn_name fn_args{ fn_value }
  31. #include "platform/GLCoreFunc.h"
  32. #include "platform/GLExtFunc.h"
  33. #undef GL_FUNCTION
  34. // point gl function pointers at stub functions
  35. #define GL_FUNCTION(fn_return,fn_name,fn_args, fn_value) fn_return (*fn_name)fn_args = stub_##fn_name;
  36. #include "platform/GLCoreFunc.h"
  37. #include "platform/GLExtFunc.h"
  38. #undef GL_FUNCTION
  39. static void* dlHandle = NULL;
  40. //------------------------------------------------------------------
  41. //bind functions for each function prototype
  42. //------------------------------------------------------------------
  43. //GL_EXT/ARB
  44. enum {
  45. ARB_multitexture = BIT(0),
  46. ARB_texture_compression = BIT(1),
  47. EXT_compiled_vertex_array = BIT(2),
  48. EXT_fog_coord = BIT(3),
  49. EXT_paletted_texture = BIT(4),
  50. NV_vertex_array_range = BIT(5),
  51. EXT_blend_color = BIT(6),
  52. EXT_blend_minmax = BIT(7)
  53. };
  54. //WGL_ARB
  55. enum {
  56. WGL_ARB_extensions_string = BIT(0),
  57. WGL_EXT_swap_control = BIT(1),
  58. WGL_3DFX_gamma_control = BIT(2)
  59. };
  60. static bool isFnOk( const char *name)
  61. {
  62. bool ok = false;
  63. // JMQ: these are specific to torque's d3d->gl wrapper. They are not used under linux.
  64. if (dStrcmp(name, "glAvailableVertexBufferEXT")==0)
  65. ok = true;
  66. else if (dStrcmp(name, "glAllocateVertexBufferEXT")==0)
  67. ok = true;
  68. else if (dStrcmp(name, "glLockVertexBufferEXT")==0)
  69. ok = true;
  70. else if (dStrcmp(name, "glUnlockVertexBufferEXT")==0)
  71. ok = true;
  72. else if (dStrcmp(name, "glSetVertexBufferEXT")==0)
  73. ok = true;
  74. else if (dStrcmp(name, "glOffsetVertexBufferEXT")==0)
  75. ok = true;
  76. else if (dStrcmp(name, "glFillVertexBufferEXT")==0)
  77. ok = true;
  78. else if (dStrcmp(name, "glFreeVertexBufferEXT")==0)
  79. ok = true;
  80. return ok;
  81. }
  82. //------------------------------------------------------------------
  83. //bind functions for each function prototype
  84. //------------------------------------------------------------------
  85. static bool bindGLFunction( void *&fnAddress, const char *name )
  86. {
  87. void* addr = (void*)SDL_GL_GetProcAddress(name);
  88. bool ok = (bool)addr;
  89. if( !ok )
  90. {
  91. if (!isFnOk(name))
  92. Con::errorf(ConsoleLogEntry::General, " Missing OpenGL function '%s'", name);
  93. else
  94. ok = true;
  95. }
  96. else
  97. fnAddress = addr;
  98. return ok;
  99. }
  100. static bool bindEXTFunction( void *&fnAddress, const char *name )
  101. {
  102. void* addr = (void*)SDL_GL_GetProcAddress(name);
  103. if( !addr )
  104. Con::errorf(ConsoleLogEntry::General, " Missing OpenGL extension '%s'", name);
  105. else
  106. fnAddress = addr;
  107. return (addr != NULL);
  108. }
  109. //------------------------------------------------------------------
  110. //binds for each function group
  111. //------------------------------------------------------------------
  112. static bool bindGLFunctions()
  113. {
  114. bool result = true;
  115. #define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) \
  116. result &= bindGLFunction( *(void**)&fn_name, #fn_name);
  117. #include "platform/GLCoreFunc.h"
  118. #undef GL_FUNCTION
  119. return result;
  120. }
  121. static bool bindEXTFunctions(U32 extMask)
  122. {
  123. bool result = true;
  124. #define GL_GROUP_BEGIN( flag ) \
  125. if( extMask & flag ) {
  126. #define GL_GROUP_END() }
  127. #define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) \
  128. result &= bindEXTFunction( *(void**)&fn_name, #fn_name);
  129. #include "platform/GLExtFunc.h"
  130. #undef GL_FUNCTION
  131. #undef GL_GROUP_BEGIN
  132. #undef GL_GROUP_END
  133. return result;
  134. }
  135. static void unbindGLFunctions()
  136. {
  137. // point gl function pointers at stub functions
  138. #define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_name = stub_##fn_name;
  139. #include "platform/GLCoreFunc.h"
  140. #include "platform/GLExtFunc.h"
  141. #undef GL_FUNCTION
  142. }
  143. namespace GLLoader
  144. {
  145. bool OpenGLInit()
  146. {
  147. return OpenGLDLLInit();
  148. }
  149. void OpenGLShutdown()
  150. {
  151. OpenGLDLLShutdown();
  152. }
  153. bool OpenGLDLLInit()
  154. {
  155. OpenGLDLLShutdown();
  156. // load libGL.so
  157. if (SDL_GL_LoadLibrary("libGL.so") == -1 &&
  158. SDL_GL_LoadLibrary("libGL.so.1") == -1)
  159. {
  160. Con::errorf("Error loading GL library: %s", SDL_GetError());
  161. return false;
  162. }
  163. // bind functions
  164. if (!bindGLFunctions())
  165. {
  166. Con::errorf("Error binding GL functions");
  167. OpenGLDLLShutdown();
  168. return false;
  169. }
  170. return true;
  171. }
  172. void OpenGLDLLShutdown()
  173. {
  174. // there is no way to tell SDL to unload the library
  175. if (dlHandle != NULL)
  176. {
  177. dlclose(dlHandle);
  178. dlHandle = NULL;
  179. }
  180. unbindGLFunctions();
  181. }
  182. }
  183. GLState gGLState;
  184. bool gOpenGLDisablePT = false;
  185. bool gOpenGLDisableCVA = false;
  186. bool gOpenGLDisableTEC = false;
  187. bool gOpenGLDisableARBMT = false;
  188. bool gOpenGLDisableFC = false;
  189. bool gOpenGLDisableTCompress = false;
  190. bool gOpenGLNoEnvColor = false;
  191. float gOpenGLGammaCorrection = 0.5;
  192. bool gOpenGLNoDrawArraysAlpha = false;
  193. // JMQTODO: really need a platform-shared version of this nastiness
  194. bool GL_EXT_Init( )
  195. {
  196. // Load extensions...
  197. //
  198. const char* pExtString = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
  199. gGLState.primMode = 0;
  200. U32 extBitMask = 0;
  201. // GL_EXT_paletted_texture
  202. if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_paletted_texture") != NULL)
  203. {
  204. extBitMask |= EXT_paletted_texture;
  205. gGLState.suppPalettedTexture = true;
  206. }
  207. else
  208. gGLState.suppPalettedTexture = false;
  209. // EXT_compiled_vertex_array
  210. if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_compiled_vertex_array") != NULL)
  211. {
  212. extBitMask |= EXT_compiled_vertex_array;
  213. gGLState.suppLockedArrays = true;
  214. }
  215. else
  216. {
  217. gGLState.suppLockedArrays = false;
  218. }
  219. // ARB_multitexture
  220. if (pExtString && dStrstr(pExtString, (const char*)"GL_ARB_multitexture") != NULL)
  221. {
  222. extBitMask |= ARB_multitexture;
  223. gGLState.suppARBMultitexture = true;
  224. } else {
  225. gGLState.suppARBMultitexture = false;
  226. }
  227. // EXT_blend_color
  228. if(pExtString && dStrstr(pExtString, (const char*)"GL_EXT_blend_color") != NULL)
  229. {
  230. extBitMask |= EXT_blend_color;
  231. gGLState.suppEXTblendcolor = true;
  232. } else {
  233. gGLState.suppEXTblendcolor = false;
  234. }
  235. // EXT_blend_minmax
  236. if(pExtString && dStrstr(pExtString, (const char*)"GL_EXT_blend_minmax") != NULL)
  237. {
  238. extBitMask |= EXT_blend_color;
  239. gGLState.suppEXTblendminmax = true;
  240. } else {
  241. gGLState.suppEXTblendminmax = false;
  242. }
  243. // EXT_fog_coord
  244. if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_fog_coord") != NULL)
  245. {
  246. extBitMask |= EXT_fog_coord;
  247. gGLState.suppFogCoord = true;
  248. } else {
  249. gGLState.suppFogCoord = false;
  250. }
  251. // EXT_texture_compression_s3tc
  252. if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_texture_compression_s3tc") != NULL)
  253. gGLState.suppS3TC = true;
  254. else
  255. gGLState.suppS3TC = false;
  256. // ARB_texture_compression
  257. if (pExtString && dStrstr(pExtString, (const char*)"GL_ARB_texture_compression") != NULL)
  258. {
  259. extBitMask |= ARB_texture_compression;
  260. gGLState.suppTextureCompression = true;
  261. } else {
  262. gGLState.suppTextureCompression = false;
  263. }
  264. // NV_vertex_array_range (not on *nix)
  265. gGLState.suppVertexArrayRange = false;
  266. // 3DFX_texture_compression_FXT1
  267. if (pExtString && dStrstr(pExtString, (const char*)"3DFX_texture_compression_FXT1") != NULL)
  268. gGLState.suppFXT1 = true;
  269. else
  270. gGLState.suppFXT1 = false;
  271. if (!bindEXTFunctions(extBitMask))
  272. Con::warnf("You are missing some OpenGL Extensions. You may experience rendering problems.");
  273. // Binary states, i.e., no supporting functions
  274. // EXT_packed_pixels
  275. // EXT_texture_env_combine
  276. //
  277. // dhc note: a number of these can have multiple matching 'versions', private, ext, and arb.
  278. gGLState.suppPackedPixels = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_packed_pixels") != NULL) : false;
  279. gGLState.suppTextureEnvCombine = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_combine") != NULL) : false;
  280. gGLState.suppEdgeClamp = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_edge_clamp") != NULL) : false;
  281. gGLState.suppEdgeClamp |= pExtString? (dStrstr(pExtString, (const char*)"GL_SGIS_texture_edge_clamp") != NULL) : false;
  282. gGLState.suppTexEnvAdd = pExtString? (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_add") != NULL) : false;
  283. gGLState.suppTexEnvAdd |= pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_add") != NULL) : false;
  284. // Anisotropic filtering
  285. gGLState.suppTexAnisotropic = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_filter_anisotropic") != NULL) : false;
  286. if (gGLState.suppTexAnisotropic)
  287. glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGLState.maxAnisotropy);
  288. if (gGLState.suppARBMultitexture)
  289. glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gGLState.maxTextureUnits);
  290. else
  291. gGLState.maxTextureUnits = 1;
  292. // JMQ: vsync/swap interval skipped
  293. gGLState.suppSwapInterval = false;
  294. Con::printf("OpenGL Init: Enabled Extensions");
  295. if (gGLState.suppARBMultitexture) Con::printf(" ARB_multitexture (Max Texture Units: %d)", gGLState.maxTextureUnits);
  296. if (gGLState.suppEXTblendcolor) Con::printf(" EXT_blend_color");
  297. if (gGLState.suppEXTblendminmax) Con::printf(" EXT_blend_minmax");
  298. if (gGLState.suppPalettedTexture) Con::printf(" EXT_paletted_texture");
  299. if (gGLState.suppLockedArrays) Con::printf(" EXT_compiled_vertex_array");
  300. if (gGLState.suppVertexArrayRange) Con::printf(" NV_vertex_array_range");
  301. if (gGLState.suppTextureEnvCombine) Con::printf(" EXT_texture_env_combine");
  302. if (gGLState.suppPackedPixels) Con::printf(" EXT_packed_pixels");
  303. if (gGLState.suppFogCoord) Con::printf(" EXT_fog_coord");
  304. if (gGLState.suppTextureCompression) Con::printf(" ARB_texture_compression");
  305. if (gGLState.suppS3TC) Con::printf(" EXT_texture_compression_s3tc");
  306. if (gGLState.suppFXT1) Con::printf(" 3DFX_texture_compression_FXT1");
  307. if (gGLState.suppTexEnvAdd) Con::printf(" (ARB|EXT)_texture_env_add");
  308. if (gGLState.suppTexAnisotropic) Con::printf(" EXT_texture_filter_anisotropic (Max anisotropy: %f)", gGLState.maxAnisotropy);
  309. if (gGLState.suppSwapInterval) Con::printf(" WGL_EXT_swap_control");
  310. Con::warnf("OpenGL Init: Disabled Extensions");
  311. if (!gGLState.suppARBMultitexture) Con::warnf(" ARB_multitexture");
  312. if (!gGLState.suppEXTblendcolor) Con::warnf(" EXT_blend_color");
  313. if (!gGLState.suppEXTblendminmax) Con::warnf(" EXT_blend_minmax");
  314. if (!gGLState.suppPalettedTexture) Con::warnf(" EXT_paletted_texture");
  315. if (!gGLState.suppLockedArrays) Con::warnf(" EXT_compiled_vertex_array");
  316. if (!gGLState.suppVertexArrayRange) Con::warnf(" NV_vertex_array_range");
  317. if (!gGLState.suppTextureEnvCombine) Con::warnf(" EXT_texture_env_combine");
  318. if (!gGLState.suppPackedPixels) Con::warnf(" EXT_packed_pixels");
  319. if (!gGLState.suppFogCoord) Con::warnf(" EXT_fog_coord");
  320. if (!gGLState.suppTextureCompression) Con::warnf(" ARB_texture_compression");
  321. if (!gGLState.suppS3TC) Con::warnf(" EXT_texture_compression_s3tc");
  322. if (!gGLState.suppFXT1) Con::warnf(" 3DFX_texture_compression_FXT1");
  323. if (!gGLState.suppTexEnvAdd) Con::warnf(" (ARB|EXT)_texture_env_add");
  324. if (!gGLState.suppTexAnisotropic) Con::warnf(" EXT_texture_filter_anisotropic");
  325. if (!gGLState.suppSwapInterval) Con::warnf(" WGL_EXT_swap_control");
  326. Con::printf(" ");
  327. // Set some console variables:
  328. Con::setBoolVariable( "$FogCoordSupported", gGLState.suppFogCoord );
  329. Con::setBoolVariable( "$TextureCompressionSupported", gGLState.suppTextureCompression );
  330. Con::setBoolVariable( "$AnisotropySupported", gGLState.suppTexAnisotropic );
  331. Con::setBoolVariable( "$PalettedTextureSupported", gGLState.suppPalettedTexture );
  332. Con::setBoolVariable( "$SwapIntervalSupported", gGLState.suppSwapInterval );
  333. if (!gGLState.suppPalettedTexture && Con::getBoolVariable("$pref::OpenGL::forcePalettedTexture",false))
  334. {
  335. Con::setBoolVariable("$pref::OpenGL::forcePalettedTexture", false);
  336. Con::setBoolVariable("$pref::OpenGL::force16BitTexture", true);
  337. }
  338. return true;
  339. }
  340. #define CHECK_GL_ERROR() ({ int __error = glGetError(); if(__error) Con::printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); (__error ? 0 : 1); })
  341. // define this to print out glErrors, un-define to get rid of it
  342. #define TEST_FOR_OPENGL_ERRORS CHECK_GL_ERROR();
  343. GLint gluProject( GLdouble objx, GLdouble objy, GLdouble objz, const F64 *model, const F64 * proj, const GLint * vp, F64 * winx, F64 * winy, F64 * winz )
  344. {
  345. Vector4F v = Vector4F( objx, objy, objz, 1.0f );
  346. MatrixF pmat = MatrixF( false );
  347. for (int i=0; i<16; i++) { ((F32*)pmat)[i] = (float)proj[i]; }
  348. MatrixF mmat = MatrixF( false );
  349. for (int i=0; i<16; i++) { ((F32*)mmat)[i] = (float)model[i]; }
  350. mmat.transpose();
  351. pmat.transpose();
  352. (pmat.mul(mmat)).mul(v);
  353. if (v.w == 0.0f) {
  354. return GL_FALSE;
  355. }
  356. F32 invW = 1.0f / v.w;
  357. v.x *= invW;
  358. v.y *= invW;
  359. v.z *= invW;
  360. *winx = (GLfloat)vp[0] + (GLfloat)vp[2] * (v.x + 1.0f) * 0.5f;
  361. *winy = (GLfloat)vp[1] + (GLfloat)vp[3] * (v.y + 1.0f) * 0.5f;
  362. *winz = (v.z + 1.0f) * 0.5f;
  363. int glError;
  364. glError = TEST_FOR_OPENGL_ERRORS
  365. return GL_TRUE;
  366. }