gfxGLUtils.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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. #ifndef TORQUE_GFX_GL_GFXGLUTILS_H_
  23. #define TORQUE_GFX_GL_GFXGLUTILS_H_
  24. #include "core/util/preprocessorHelpers.h"
  25. #include "gfx/gl/gfxGLEnumTranslate.h"
  26. #include "gfx/gl/gfxGLStateCache.h"
  27. #include "gfx/bitmap/imageUtils.h"
  28. inline U32 getMaxMipmaps(U32 width, U32 height, U32 depth)
  29. {
  30. return getMax( getBinLog2(depth), getMax(getBinLog2(width), getBinLog2(height))) + 1;
  31. }
  32. inline GLenum minificationFilter(U32 minFilter, U32 mipFilter, U32 /*mipLevels*/)
  33. {
  34. // the compiler should interpret this as array lookups
  35. switch( minFilter )
  36. {
  37. case GFXTextureFilterLinear:
  38. switch( mipFilter )
  39. {
  40. case GFXTextureFilterLinear:
  41. return GL_LINEAR_MIPMAP_LINEAR;
  42. case GFXTextureFilterPoint:
  43. return GL_LINEAR_MIPMAP_NEAREST;
  44. default:
  45. return GL_LINEAR;
  46. }
  47. default:
  48. switch( mipFilter ) {
  49. case GFXTextureFilterLinear:
  50. return GL_NEAREST_MIPMAP_LINEAR;
  51. case GFXTextureFilterPoint:
  52. return GL_NEAREST_MIPMAP_NEAREST;
  53. default:
  54. return GL_NEAREST;
  55. }
  56. }
  57. }
  58. //Get the surface size of a compressed mip map level - see ddsLoader.cpp
  59. inline U32 getCompressedSurfaceSize(GFXFormat format,U32 width, U32 height, U32 mipLevel=0 )
  60. {
  61. if(!ImageUtil::isCompressedFormat(format))
  62. return 0;
  63. // Bump by the mip level.
  64. height = getMax(U32(1), height >> mipLevel);
  65. width = getMax(U32(1), width >> mipLevel);
  66. U32 sizeMultiple = 0;
  67. if(format == GFXFormatBC1 || format == GFXFormatBC1_SRGB)
  68. sizeMultiple = 8;
  69. else
  70. sizeMultiple = 16;
  71. return getMax(U32(1), width/4) * getMax(U32(1), height/4) * sizeMultiple;
  72. }
  73. /// Simple class which preserves a given GL integer.
  74. /// This class determines the integer to preserve on construction and restores
  75. /// it on destruction.
  76. class GFXGLPreserveInteger
  77. {
  78. public:
  79. typedef void(STDCALL *BindFn)(GLenum, GLuint);
  80. /// Preserve the integer.
  81. /// @param binding The binding which should be set on destruction.
  82. /// @param getBinding The parameter to be passed to glGetIntegerv to determine
  83. /// the integer to be preserved.
  84. /// @param binder The gl function to call to restore the integer.
  85. GFXGLPreserveInteger(GLenum binding, GLint getBinding, BindFn binder) :
  86. mBinding(binding), mPreserved(0), mBinder(binder)
  87. {
  88. AssertFatal(mBinder, "GFXGLPreserveInteger - Need a valid binder function");
  89. mPreserved = GFXGL->getOpenglCache()->getCacheBinded(mBinding);
  90. #if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
  91. GLint bindedOnOpenglDriver;
  92. glGetIntegerv(getBinding, &bindedOnOpenglDriver);
  93. AssertFatal( mPreserved == bindedOnOpenglDriver, "GFXGLPreserveInteger - GFXGLDevice/OpenGL mismatch on cache binded resource.");
  94. #endif
  95. }
  96. /// Restores the integer.
  97. ~GFXGLPreserveInteger()
  98. {
  99. mBinder(mBinding, mPreserved);
  100. }
  101. private:
  102. GLenum mBinding;
  103. GLint mPreserved;
  104. BindFn mBinder;
  105. };
  106. class GFXGLPreserveTexture
  107. {
  108. public:
  109. typedef void(STDCALL *BindFn)(GLenum, GLuint);
  110. GFXGLPreserveTexture(GLenum binding, GLint getBinding, BindFn binder) :
  111. mBinding(binding), mPreserved(0), mBinder(binder)
  112. {
  113. AssertFatal(mBinder, "GFXGLPreserveTexture - Need a valid binder function");
  114. GFXGLDevice *gfx = GFXGL;
  115. mPreserved = gfx->getOpenglCache()->getCacheBinded(mBinding);
  116. mActiveTexture = gfx->getOpenglCache()->getCacheActiveTexture();
  117. #if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
  118. GLint activeTextureOnOpenglDriver, bindedTextureOnOpenglDriver;
  119. glGetIntegerv(getBinding, &bindedTextureOnOpenglDriver);
  120. glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureOnOpenglDriver);
  121. activeTextureOnOpenglDriver -= GL_TEXTURE0;
  122. AssertFatal( mPreserved == bindedTextureOnOpenglDriver, "GFXGLPreserveTexture - GFXGLDevice/OpenGL mismatch on cache binded resource.");
  123. AssertFatal( activeTextureOnOpenglDriver == mActiveTexture, "GFXGLPreserveTexture - GFXGLDevice/OpenGL mismatch on cache binded resource.");
  124. #endif
  125. }
  126. /// Restores the texture.
  127. ~GFXGLPreserveTexture()
  128. {
  129. #if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
  130. GLint activeTextureOnOpenglDriver;
  131. glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureOnOpenglDriver);
  132. activeTextureOnOpenglDriver -= GL_TEXTURE0;
  133. GLint cacheActiveTexture = GFXGL->getOpenglCache()->getCacheActiveTexture();
  134. AssertFatal( cacheActiveTexture == activeTextureOnOpenglDriver, "GFXGLPreserveTexture - GFXGLDevice/OpenGL mismatch on cache ActiveTexture.");
  135. #endif
  136. mBinder(mBinding, mPreserved);
  137. }
  138. private:
  139. GLenum mBinding;
  140. GLint mPreserved;
  141. BindFn mBinder;
  142. S16 mActiveTexture;
  143. };
  144. /// Helper macro to preserve the current VBO binding.
  145. #define PRESERVE_VERTEX_BUFFER() \
  146. GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_ARRAY_BUFFER, GL_ARRAY_BUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindBuffer)
  147. /// Helper macro to preserve the current element array binding.
  148. #define PRESERVE_INDEX_BUFFER() \
  149. GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_ELEMENT_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindBuffer)
  150. #define _GET_BUFFER_BINDING( BINDING ) \
  151. BINDING == GL_ARRAY_BUFFER ? GL_ARRAY_BUFFER_BINDING : ( BINDING == GL_ELEMENT_ARRAY_BUFFER ? GL_ELEMENT_ARRAY_BUFFER_BINDING : 0 )
  152. /// Helper macro to preserve the current element array binding.
  153. #define PRESERVE_BUFFER( BINDING ) \
  154. GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (BINDING, _GET_BUFFER_BINDING(BINDING), (GFXGLPreserveInteger::BindFn)glBindBuffer)
  155. /// ASSERT: Never call glActiveTexture for a "bind to modify" or in a PRESERVER_TEXTURE MACRO scope.
  156. /// Helper macro to preserve the current 1D texture binding.
  157. #define PRESERVE_1D_TEXTURE() \
  158. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, (GFXGLPreserveInteger::BindFn)glBindTexture)
  159. /// Helper macro to preserve the current 2D texture binding.
  160. #define PRESERVE_2D_TEXTURE() \
  161. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, (GFXGLPreserveInteger::BindFn)glBindTexture)
  162. /// Helper macro to preserve the current 3D texture binding.
  163. #define PRESERVE_3D_TEXTURE() \
  164. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, (GFXGLPreserveInteger::BindFn)glBindTexture)
  165. /// Helper macro to preserve the current 3D texture binding.
  166. #define PRESERVE_CUBEMAP_TEXTURE() \
  167. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, (GFXGLPreserveInteger::BindFn)glBindTexture)
  168. #define PRESERVE_CUBEMAP_ARRAY_TEXTURE() \
  169. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, (GFXGLPreserveInteger::BindFn)glBindTexture)
  170. #define PRESERVE_2D_TEXTURE_ARRAY() \
  171. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, (GFXGLPreserveInteger::BindFn)glBindTexture)
  172. #define _GET_TEXTURE_BINDING(binding) \
  173. binding == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : (binding == GL_TEXTURE_3D ? GL_TEXTURE_BINDING_3D : GL_TEXTURE_BINDING_1D )
  174. #define PRESERVE_TEXTURE(binding) \
  175. GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (binding, _GET_TEXTURE_BINDING(binding), (GFXGLPreserveInteger::BindFn)glBindTexture)
  176. #define PRESERVE_FRAMEBUFFER() \
  177. GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_READ_FRAMEBUFFER, GL_READ_FRAMEBUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindFramebuffer);\
  178. GFXGLPreserveInteger TORQUE_CONCAT(preserve2_, __LINE__) (GL_DRAW_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindFramebuffer)
  179. #ifdef TORQUE_DEBUG
  180. // Handy macro for checking the status of a framebuffer. Framebuffers can fail in
  181. // all sorts of interesting ways, these are just the most common. Further, no existing GL profiling
  182. // tool catches framebuffer errors when the framebuffer is created, so we actually need this.
  183. #define CHECK_FRAMEBUFFER_STATUS()\
  184. {\
  185. GLenum status;\
  186. status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\
  187. switch(status) {\
  188. case GL_FRAMEBUFFER_COMPLETE:\
  189. break;\
  190. case GL_FRAMEBUFFER_UNSUPPORTED:\
  191. AssertFatal(false, "Unsupported FBO");\
  192. break;\
  193. case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\
  194. AssertFatal(false, "Incomplete FBO Attachment");\
  195. break;\
  196. case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\
  197. AssertFatal(false, "Incomplete FBO Missing Attachment");\
  198. break;\
  199. case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:\
  200. AssertFatal(false, "Incomplete FBO Draw buffer");\
  201. break;\
  202. case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:\
  203. AssertFatal(false, "Incomplete FBO Read buffer");\
  204. break;\
  205. default:\
  206. /* programming error; will fail on all hardware */\
  207. AssertFatal(false, "Something really bad happened with an FBO");\
  208. }\
  209. }
  210. #else
  211. #define CHECK_FRAMEBUFFER_STATUS()
  212. #endif //TORQUE_DEBUG
  213. #endif