Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

355 lines
9.4 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // cglmfbo.cpp
  4. //
  5. //===============================================================================
  6. #include "glmgr/glmgr.h"
  7. #include "glmgr/cglmfbo.h"
  8. // #include "../shaderapidx9/dxabstract.h"
  9. // memdbgon -must- be the last include file in a .cpp file.
  10. #include "tier0/memdbgon.h"
  11. CGLMFBO::CGLMFBO( GLMContext *ctx )
  12. {
  13. m_ctx = ctx;
  14. m_ctx->CheckCurrent();
  15. glGenFramebuffersEXT( 1, &m_name );
  16. GLMCheckError();
  17. memset( m_attach, 0, sizeof( m_attach ) );
  18. m_sizeX = m_sizeY = 0;
  19. }
  20. CGLMFBO::~CGLMFBO( )
  21. {
  22. m_ctx->CheckCurrent();
  23. // detach all known attached textures first... necessary ?
  24. for( int index = 0; index < kAttCount; index++)
  25. {
  26. if (m_attach[ index ].m_tex)
  27. {
  28. TexDetach( (EGLMFBOAttachment)index );
  29. GLMCheckError();
  30. }
  31. }
  32. glDeleteFramebuffersEXT( 1, &m_name );
  33. GLMCheckError();
  34. m_name = 0;
  35. m_ctx = NULL;
  36. }
  37. // the tex attach path should also select a specific slice of the texture...
  38. // and we need a way to make renderbuffers..
  39. static GLenum EncodeAttachmentFBO( EGLMFBOAttachment index )
  40. {
  41. if (index < kAttDepth)
  42. {
  43. return GL_COLOR_ATTACHMENT0_EXT + (int) index;
  44. }
  45. else
  46. {
  47. switch( index )
  48. {
  49. case kAttDepth:
  50. return GL_DEPTH_ATTACHMENT_EXT;
  51. break;
  52. case kAttStencil:
  53. return GL_STENCIL_ATTACHMENT_EXT;
  54. break;
  55. case kAttDepthStencil:
  56. return GL_DEPTH_STENCIL_ATTACHMENT_EXT;
  57. break;
  58. default:
  59. GLMStop(); // bad news
  60. break;
  61. }
  62. }
  63. }
  64. void CGLMFBO::TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint )
  65. {
  66. // force our parent context to be current
  67. m_ctx->MakeCurrent();
  68. // bind to context (will cause FBO object creation on first use)
  69. m_ctx->BindFBOToCtx( this, fboBindPoint );
  70. // it's either a plain 2D, a 2D face of a cube map, or a slice of a 3D.
  71. CGLMTex *tex = params->m_tex;
  72. // always detach what is currently there, if anything
  73. this->TexDetach( attachIndex, fboBindPoint );
  74. if (!tex)
  75. {
  76. // andif they pass NULL to us, then we are done.
  77. return;
  78. }
  79. GLMTexLayout *layout = tex->m_layout;
  80. GLenum target = tex->m_layout->m_key.m_texGLTarget;
  81. GLenum attachIndexGL = EncodeAttachmentFBO( attachIndex );
  82. switch( target )
  83. {
  84. case GL_TEXTURE_2D:
  85. {
  86. // we will attach the underlying RBO on a multisampled tex, iff the tex hasone, **and** we're not being asked to attach it to the read buffer.
  87. // if we get a req to attach an MSAA tex to the read buffer, chances are it's BlitTex calling, andit has already resolved the tex, so in those
  88. // cases you really do want to attach the texture and not the RBO to the FBO in question.
  89. bool useRBO = false; // initial state
  90. if (layout->m_key.m_texFlags & kGLMTexMultisampled)
  91. {
  92. // it is an MSAA tex
  93. if (fboBindPoint == GL_READ_FRAMEBUFFER_EXT)
  94. {
  95. // I think you just want to read a resolved tex.
  96. // But I will check that it is resolved first..
  97. Assert( tex->m_rboDirty == false );
  98. }
  99. else
  100. {
  101. // you want to draw into it. You get the RBO bound instead of the tex.
  102. useRBO = true;
  103. }
  104. }
  105. if (useRBO)
  106. {
  107. // MSAA path - attach the RBO, not the texture, and mark the RBO dirty
  108. if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
  109. {
  110. // you have to attach it both places...
  111. // http://www.opengl.org/wiki/GL_EXT_framebuffer_object
  112. // bind the RBO to the GL_RENDERBUFFER_EXT target
  113. glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, tex->m_rboName );
  114. GLMCheckError();
  115. // attach the GL_RENDERBUFFER_EXT target to the depth and stencil attach points
  116. glFramebufferRenderbufferEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tex->m_rboName);
  117. GLMCheckError();
  118. glFramebufferRenderbufferEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tex->m_rboName);
  119. GLMCheckError();
  120. // no need to leave the RBO hanging on
  121. glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
  122. GLMCheckError();
  123. }
  124. else
  125. {
  126. // color attachment (likely 0)
  127. glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, tex->m_rboName );
  128. GLMCheckError();
  129. glFramebufferRenderbufferEXT( fboBindPoint, attachIndexGL, GL_RENDERBUFFER_EXT, tex->m_rboName);
  130. GLMCheckError();
  131. glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
  132. GLMCheckError();
  133. }
  134. tex->m_rboDirty = true;
  135. }
  136. else
  137. {
  138. // regular path - attaching a texture2d
  139. if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
  140. {
  141. // you have to attach it both places...
  142. // http://www.opengl.org/wiki/GL_EXT_framebuffer_object
  143. glFramebufferTexture2DEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, target, tex->m_texName, params->m_mip );
  144. GLMCheckError();
  145. glFramebufferTexture2DEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, target, tex->m_texName, params->m_mip );
  146. GLMCheckError();
  147. }
  148. else
  149. {
  150. glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip );
  151. GLMCheckError();
  152. }
  153. }
  154. }
  155. break;
  156. case GL_TEXTURE_3D:
  157. {
  158. glFramebufferTexture3DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip, params->m_zslice );
  159. GLMCheckError();
  160. }
  161. break;
  162. case GL_TEXTURE_CUBE_MAP:
  163. {
  164. // adjust target to steer to the proper face of the cube map
  165. target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + params->m_face;
  166. glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip );
  167. GLMCheckError();
  168. }
  169. break;
  170. }
  171. // log the attached tex
  172. m_attach[ attachIndex ] = *params;
  173. // indicate that the tex has been bound to an RT
  174. tex->m_rtAttachCount++;
  175. }
  176. void CGLMFBO::TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint )
  177. {
  178. // force our parent context to be current
  179. m_ctx->MakeCurrent();
  180. // bind to context (will cause FBO object creation on first use)
  181. m_ctx->BindFBOToCtx( this, fboBindPoint );
  182. if (m_attach[ attachIndex ].m_tex)
  183. {
  184. CGLMTex *tex = m_attach[ attachIndex ].m_tex;
  185. GLMTexLayout *layout = tex->m_layout;
  186. GLenum target = tex->m_layout->m_key.m_texGLTarget;
  187. GLenum attachIndexGL = EncodeAttachmentFBO( attachIndex );
  188. switch( target )
  189. {
  190. case GL_TEXTURE_2D:
  191. {
  192. if (layout->m_key.m_texFlags & kGLMTexMultisampled)
  193. {
  194. // MSAA path - detach the RBO, not the texture
  195. // (is this the right time to resolve? probably better to wait until someone tries to sample the texture)
  196. glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
  197. GLMCheckError();
  198. if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
  199. {
  200. // detach the GL_RENDERBUFFER_EXT target at depth and stencil attach points
  201. glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
  202. GLMCheckError();
  203. glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
  204. GLMCheckError();
  205. }
  206. else
  207. {
  208. // color attachment (likely 0)
  209. glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachIndexGL, GL_RENDERBUFFER_EXT, 0);
  210. GLMCheckError();
  211. }
  212. }
  213. else
  214. {
  215. // plain tex detach
  216. if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
  217. {
  218. // you have to detach it both places...
  219. // http://www.opengl.org/wiki/GL_EXT_framebuffer_object
  220. glFramebufferTexture2DEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, 0,0,0 );
  221. glFramebufferTexture2DEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, 0,0,0 );
  222. }
  223. else
  224. {
  225. glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, 0, 0, 0 );
  226. }
  227. }
  228. }
  229. break;
  230. case GL_TEXTURE_3D:
  231. {
  232. glFramebufferTexture3DEXT( fboBindPoint, attachIndexGL, 0, 0, 0, 0 );
  233. GLMCheckError();
  234. }
  235. break;
  236. case GL_TEXTURE_CUBE_MAP:
  237. {
  238. glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, 0, 0, 0 );
  239. GLMCheckError();
  240. }
  241. break;
  242. }
  243. // un-log the attached tex
  244. memset( &m_attach[ attachIndex ], 0, sizeof( m_attach[0] ) );
  245. // drop the RT attach count
  246. tex->m_rtAttachCount--;
  247. }
  248. else
  249. {
  250. //Debugger(); // odd, but not harmful - typ comes from D3D code passing NULL into SetRenderTarget
  251. }
  252. }
  253. void CGLMFBO::TexScrub( CGLMTex *tex )
  254. {
  255. // see if it's attached anywhere
  256. for( int attachIndex = 0; attachIndex < kAttCount; attachIndex++ )
  257. {
  258. if (m_attach[ attachIndex ].m_tex == tex)
  259. {
  260. // blammo
  261. TexDetach( (EGLMFBOAttachment)attachIndex, GL_DRAW_FRAMEBUFFER_EXT );
  262. }
  263. }
  264. }
  265. bool CGLMFBO::IsReady( void )
  266. {
  267. bool result = false;
  268. // ensure our parent context is current
  269. m_ctx->CheckCurrent();
  270. // bind to context (will cause FBO object creation on first use)
  271. m_ctx->BindFBOToCtx( this );
  272. GLenum status;
  273. status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  274. switch(status)
  275. {
  276. case GL_FRAMEBUFFER_COMPLETE_EXT:
  277. result = true;
  278. break;
  279. case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
  280. result = false;
  281. Debugger();
  282. /* choose different formats */
  283. break;
  284. default:
  285. result = false;
  286. Debugger();
  287. /* programming error; will fail on all hardware */
  288. break;
  289. }
  290. return result;
  291. }