BsGLRenderTexture.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include "BsGLRenderTexture.h"
  2. #include "BsGLPixelFormat.h"
  3. #include "BsGLPixelBuffer.h"
  4. #include "BsTextureView.h"
  5. namespace BansheeEngine
  6. {
  7. #define PROBE_SIZE 16
  8. static const GLenum depthFormats[] =
  9. {
  10. GL_NONE,
  11. GL_DEPTH_COMPONENT16,
  12. GL_DEPTH_COMPONENT32,
  13. GL_DEPTH24_STENCIL8,
  14. GL_DEPTH32F_STENCIL8
  15. };
  16. static const UINT32 depthBits[] =
  17. {
  18. 0, 16, 32, 24, 32
  19. };
  20. #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum))
  21. GLRenderTexture::GLRenderTexture()
  22. :mFB(nullptr)
  23. {
  24. }
  25. GLRenderTexture::~GLRenderTexture()
  26. {
  27. }
  28. void GLRenderTexture::destroy_internal()
  29. {
  30. if(mFB != nullptr)
  31. bs_delete<PoolAlloc>(mFB);
  32. RenderTexture::destroy_internal();
  33. }
  34. void GLRenderTexture::initialize_internal()
  35. {
  36. if(mFB != nullptr)
  37. bs_delete<PoolAlloc>(mFB);
  38. mFB = bs_new<GLFrameBufferObject, PoolAlloc>();
  39. GLSurfaceDesc surfaceDesc;
  40. surfaceDesc.numSamples = mMultisampleCount;
  41. surfaceDesc.zoffset = 0;
  42. GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
  43. surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
  44. mFB->bindSurface(0, surfaceDesc);
  45. GLTexture* glDepthStencilTexture = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
  46. GLPixelBufferPtr depthStencilBuffer =
  47. glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip());
  48. mFB->bindDepthStencil(depthStencilBuffer);
  49. RenderTexture::initialize_internal();
  50. }
  51. void GLRenderTexture::getCustomAttribute(const String& name, void* pData) const
  52. {
  53. if(name=="FBO")
  54. {
  55. *static_cast<GLFrameBufferObject **>(pData) = mFB;
  56. }
  57. else if (name == "GL_FBOID" || name == "GL_MULTISAMPLEFBOID")
  58. {
  59. *static_cast<GLuint*>(pData) = mFB->getGLFBOID();
  60. }
  61. }
  62. GLRTTManager::GLRTTManager()
  63. {
  64. detectFBOFormats();
  65. glGenFramebuffersEXT(1, &mTempFBO);
  66. }
  67. GLRTTManager::~GLRTTManager()
  68. {
  69. glDeleteFramebuffersEXT(1, &mTempFBO);
  70. }
  71. bool GLRTTManager::_tryFormat(GLenum depthFormat, GLenum stencilFormat)
  72. {
  73. GLuint status, depthRB = 0, stencilRB = 0;
  74. bool failed = false;
  75. if(depthFormat != GL_NONE)
  76. {
  77. // Generate depth renderbuffer
  78. glGenRenderbuffersEXT(1, &depthRB);
  79. // Bind it to FBO
  80. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRB);
  81. // Allocate storage for depth buffer
  82. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormat,
  83. PROBE_SIZE, PROBE_SIZE);
  84. // Attach depth
  85. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
  86. GL_RENDERBUFFER_EXT, depthRB);
  87. }
  88. if(stencilFormat != GL_NONE)
  89. {
  90. // Generate stencil renderbuffer
  91. glGenRenderbuffersEXT(1, &stencilRB);
  92. // Bind it to FBO
  93. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencilRB);
  94. glGetError();
  95. // Allocate storage for stencil buffer
  96. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, stencilFormat,
  97. PROBE_SIZE, PROBE_SIZE);
  98. if(glGetError() != GL_NO_ERROR)
  99. failed = true;
  100. // Attach stencil
  101. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
  102. GL_RENDERBUFFER_EXT, stencilRB);
  103. if(glGetError() != GL_NO_ERROR)
  104. failed = true;
  105. }
  106. status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  107. // Detach and destroy
  108. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
  109. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
  110. if (depthRB)
  111. glDeleteRenderbuffersEXT(1, &depthRB);
  112. if (stencilRB)
  113. glDeleteRenderbuffersEXT(1, &stencilRB);
  114. return status == GL_FRAMEBUFFER_COMPLETE_EXT && !failed;
  115. }
  116. bool GLRTTManager::_tryPackedFormat(GLenum packedFormat)
  117. {
  118. GLuint packedRB = 0;
  119. bool failed = false; // flag on GL errors
  120. // Generate renderbuffer
  121. glGenRenderbuffersEXT(1, &packedRB);
  122. // Bind it to FBO
  123. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, packedRB);
  124. // Allocate storage for buffer
  125. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, packedFormat, PROBE_SIZE, PROBE_SIZE);
  126. glGetError();
  127. // Attach depth
  128. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
  129. GL_RENDERBUFFER_EXT, packedRB);
  130. if(glGetError() != GL_NO_ERROR)
  131. failed = true;
  132. // Attach stencil
  133. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
  134. GL_RENDERBUFFER_EXT, packedRB);
  135. if(glGetError() != GL_NO_ERROR)
  136. failed = true;
  137. GLuint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  138. // Detach and destroy
  139. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
  140. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
  141. glDeleteRenderbuffersEXT(1, &packedRB);
  142. return status == GL_FRAMEBUFFER_COMPLETE_EXT && !failed;
  143. }
  144. void GLRTTManager::detectFBOFormats()
  145. {
  146. // Try all formats, and report which ones work as target
  147. GLuint fb = 0, tid = 0;
  148. GLint old_drawbuffer = 0, old_readbuffer = 0;
  149. GLenum target = GL_TEXTURE_2D;
  150. glGetIntegerv (GL_DRAW_BUFFER, &old_drawbuffer);
  151. glGetIntegerv (GL_READ_BUFFER, &old_readbuffer);
  152. for(size_t x=0; x<PF_COUNT; ++x)
  153. {
  154. mProps[x].valid = false;
  155. // Fetch GL format token
  156. GLenum fmt = GLPixelUtil::getGLInternalFormat((PixelFormat)x);
  157. if(fmt == GL_NONE && x!=0)
  158. continue;
  159. // No test for compressed formats
  160. if(PixelUtil::isCompressed((PixelFormat)x))
  161. continue;
  162. // Create and attach framebuffer
  163. glGenFramebuffersEXT(1, &fb);
  164. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
  165. if (fmt!=GL_NONE && !PixelUtil::isDepth((PixelFormat)x))
  166. {
  167. // Create and attach texture
  168. glGenTextures(1, &tid);
  169. glBindTexture(target, tid);
  170. // Set some default parameters so it won't fail on NVidia cards
  171. if (GLEW_VERSION_1_2)
  172. glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
  173. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  174. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  175. glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  176. glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  177. glTexImage2D(target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
  178. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
  179. target, tid, 0);
  180. }
  181. else
  182. {
  183. // Draw to nowhere -- stencil/depth only
  184. glDrawBuffer(GL_NONE);
  185. glReadBuffer(GL_NONE);
  186. }
  187. // Check status
  188. GLuint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  189. // Ignore status in case of fmt==GL_NONE, because no implementation will accept
  190. // a buffer without *any* attachment. Buffers with only stencil and depth attachment
  191. // might still be supported, so we must continue probing.
  192. if(fmt == GL_NONE || status == GL_FRAMEBUFFER_COMPLETE_EXT)
  193. {
  194. mProps[x].valid = true;
  195. // For each depth/stencil formats
  196. for (UINT32 depth = 0; depth < DEPTHFORMAT_COUNT; ++depth)
  197. {
  198. if (depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT && depthFormats[depth] != GL_DEPTH32F_STENCIL8)
  199. {
  200. if (_tryFormat(depthFormats[depth], GL_NONE))
  201. {
  202. /// Add mode to allowed modes
  203. FormatProperties::Mode mode;
  204. mode.depth = depth;
  205. mode.stencil = 0;
  206. mProps[x].modes.push_back(mode);
  207. }
  208. }
  209. else
  210. {
  211. // Packed depth/stencil format
  212. if (_tryPackedFormat(depthFormats[depth]))
  213. {
  214. /// Add mode to allowed modes
  215. FormatProperties::Mode mode;
  216. mode.depth = depth;
  217. mode.stencil = 0; // unuse
  218. mProps[x].modes.push_back(mode);
  219. }
  220. }
  221. }
  222. }
  223. // Delete texture and framebuffer
  224. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  225. glDeleteFramebuffersEXT(1, &fb);
  226. glFinish();
  227. if (fmt!=GL_NONE)
  228. glDeleteTextures(1, &tid);
  229. }
  230. // It seems a bug in nVidia driver: glBindFramebufferEXT should restore
  231. // draw and read buffers, but in some unclear circumstances it won't.
  232. glDrawBuffer(old_drawbuffer);
  233. glReadBuffer(old_readbuffer);
  234. String fmtstring = "";
  235. for(size_t x=0; x<PF_COUNT; ++x)
  236. {
  237. if(mProps[x].valid)
  238. fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" ";
  239. }
  240. }
  241. PixelFormat GLRTTManager::getSupportedAlternative(PixelFormat format)
  242. {
  243. if(checkFormat(format))
  244. return format;
  245. // Find first alternative
  246. PixelComponentType pct = PixelUtil::getElementType(format);
  247. switch(pct)
  248. {
  249. case PCT_BYTE: format = PF_A8R8G8B8; break;
  250. case PCT_FLOAT16: format = PF_FLOAT16_RGBA; break;
  251. case PCT_FLOAT32: format = PF_FLOAT32_RGBA; break;
  252. case PCT_COUNT: break;
  253. }
  254. if(checkFormat(format))
  255. return format;
  256. // If none at all, return to default
  257. return PF_A8R8G8B8;
  258. }
  259. }