llrendertarget.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:16k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llrendertarget.cpp
  3.  * @brief LLRenderTarget implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llrendertarget.h"
  34. #include "llrender.h"
  35. #include "llgl.h"
  36. LLRenderTarget* LLRenderTarget::sBoundTarget = NULL;
  37. void check_framebuffer_status()
  38. {
  39. if (gDebugGL)
  40. {
  41. GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  42. switch (status)
  43. {
  44. case GL_FRAMEBUFFER_COMPLETE_EXT:
  45. break;
  46. default:
  47. ll_fail("check_framebuffer_status failed");
  48. break;
  49. }
  50. }
  51. }
  52. BOOL LLRenderTarget::sUseFBO = FALSE;
  53. LLRenderTarget::LLRenderTarget() :
  54. mResX(0),
  55. mResY(0),
  56. mTex(0),
  57. mFBO(0),
  58. mDepth(0),
  59. mStencil(0),
  60. mUseDepth(FALSE),
  61. mRenderDepth(FALSE),
  62. mUsage(LLTexUnit::TT_TEXTURE),
  63. mSamples(0),
  64. mSampleBuffer(NULL)
  65. {
  66. }
  67. LLRenderTarget::~LLRenderTarget()
  68. {
  69. release();
  70. }
  71. void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
  72. {
  73. mSampleBuffer = buffer;
  74. }
  75. void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo)
  76. {
  77. stop_glerror();
  78. mResX = resx;
  79. mResY = resy;
  80. mStencil = stencil;
  81. mUsage = usage;
  82. mUseDepth = depth;
  83. release();
  84. if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
  85. {
  86. if (depth)
  87. {
  88. stop_glerror();
  89. allocateDepth();
  90. stop_glerror();
  91. }
  92. glGenFramebuffersEXT(1, (GLuint *) &mFBO);
  93. if (mDepth)
  94. {
  95. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  96. if (mStencil)
  97. {
  98. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);
  99. stop_glerror();
  100. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);
  101. stop_glerror();
  102. }
  103. else
  104. {
  105. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
  106. stop_glerror();
  107. }
  108. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  109. }
  110. stop_glerror();
  111. }
  112. addColorAttachment(color_fmt);
  113. }
  114. void LLRenderTarget::addColorAttachment(U32 color_fmt)
  115. {
  116. if (color_fmt == 0)
  117. {
  118. return;
  119. }
  120. U32 offset = mTex.size();
  121. if (offset >= 4 ||
  122. (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
  123. {
  124. llerrs << "Too many color attachments!" << llendl;
  125. }
  126. U32 tex;
  127. LLImageGL::generateTextures(1, &tex);
  128. gGL.getTexUnit(0)->bindManual(mUsage, tex);
  129. stop_glerror();
  130. LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  131. stop_glerror();
  132. if (offset == 0)
  133. {
  134. gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
  135. }
  136. else
  137. { //don't filter data attachments
  138. gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
  139. }
  140. if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
  141. {
  142. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
  143. }
  144. else
  145. {
  146. // ATI doesn't support mirrored repeat for rectangular textures.
  147. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
  148. }
  149. if (mFBO)
  150. {
  151. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  152. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset,
  153. LLTexUnit::getInternalType(mUsage), tex, 0);
  154. stop_glerror();
  155. check_framebuffer_status();
  156. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  157. }
  158. mTex.push_back(tex);
  159. }
  160. void LLRenderTarget::allocateDepth()
  161. {
  162. if (mStencil)
  163. {
  164. //use render buffers where stencil buffers are in play
  165. glGenRenderbuffersEXT(1, (GLuint *) &mDepth);
  166. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);
  167. glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mResX, mResY);
  168. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
  169. }
  170. else
  171. {
  172. LLImageGL::generateTextures(1, &mDepth);
  173. gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
  174. U32 internal_type = LLTexUnit::getInternalType(mUsage);
  175. gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
  176. LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32_ARB, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
  177. }
  178. }
  179. void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
  180. {
  181. if (!mFBO || !target.mFBO)
  182. {
  183. llerrs << "Cannot share depth buffer between non FBO render targets." << llendl;
  184. }
  185. if (mDepth)
  186. {
  187. stop_glerror();
  188. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, target.mFBO);
  189. stop_glerror();
  190. if (mStencil)
  191. {
  192. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);
  193. stop_glerror();
  194. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);
  195. stop_glerror();
  196. }
  197. else
  198. {
  199. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
  200. stop_glerror();
  201. if (mStencil)
  202. {
  203. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
  204. stop_glerror();
  205. }
  206. }
  207. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  208. target.mUseDepth = TRUE;
  209. }
  210. }
  211. void LLRenderTarget::release()
  212. {
  213. if (mFBO)
  214. {
  215. glDeleteFramebuffersEXT(1, (GLuint *) &mFBO);
  216. mFBO = 0;
  217. }
  218. if (mTex.size() > 0)
  219. {
  220. LLImageGL::deleteTextures(mTex.size(), &mTex[0]);
  221. mTex.clear();
  222. }
  223. if (mDepth)
  224. {
  225. if (mStencil)
  226. {
  227. glDeleteRenderbuffersEXT(1, (GLuint*) &mDepth);
  228. stop_glerror();
  229. }
  230. else
  231. {
  232. LLImageGL::deleteTextures(1, &mDepth);
  233. stop_glerror();
  234. }
  235. mDepth = 0;
  236. }
  237. mSampleBuffer = NULL;
  238. sBoundTarget = NULL;
  239. }
  240. void LLRenderTarget::bindTarget()
  241. {
  242. if (mFBO)
  243. {
  244. stop_glerror();
  245. if (mSampleBuffer)
  246. {
  247. mSampleBuffer->bindTarget(this);
  248. stop_glerror();
  249. }
  250. else
  251. {
  252. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  253. stop_glerror();
  254. if (gGLManager.mHasDrawBuffers)
  255. { //setup multiple render targets
  256. GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
  257. GL_COLOR_ATTACHMENT1_EXT,
  258. GL_COLOR_ATTACHMENT2_EXT,
  259. GL_COLOR_ATTACHMENT3_EXT};
  260. glDrawBuffersARB(mTex.size(), drawbuffers);
  261. }
  262. if (mTex.empty())
  263. { //no color buffer to draw to
  264. glDrawBuffer(GL_NONE);
  265. glReadBuffer(GL_NONE);
  266. }
  267. check_framebuffer_status();
  268. stop_glerror();
  269. }
  270. }
  271. glViewport(0, 0, mResX, mResY);
  272. sBoundTarget = this;
  273. }
  274. // static
  275. void LLRenderTarget::unbindTarget()
  276. {
  277. if (gGLManager.mHasFramebufferObject)
  278. {
  279. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  280. }
  281. sBoundTarget = NULL;
  282. }
  283. void LLRenderTarget::clear(U32 mask_in)
  284. {
  285. U32 mask = GL_COLOR_BUFFER_BIT;
  286. if (mUseDepth)
  287. {
  288. mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
  289. }
  290. if (mFBO)
  291. {
  292. check_framebuffer_status();
  293. stop_glerror();
  294. glClear(mask & mask_in);
  295. stop_glerror();
  296. }
  297. else
  298. {
  299. LLGLEnable scissor(GL_SCISSOR_TEST);
  300. glScissor(0, 0, mResX, mResY);
  301. stop_glerror();
  302. glClear(mask & mask_in);
  303. }
  304. }
  305. U32 LLRenderTarget::getTexture(U32 attachment) const
  306. {
  307. if (attachment > mTex.size()-1)
  308. {
  309. llerrs << "Invalid attachment index." << llendl;
  310. }
  311. return mTex[attachment];
  312. }
  313. void LLRenderTarget::bindTexture(U32 index, S32 channel)
  314. {
  315. if (index > mTex.size()-1)
  316. {
  317. llerrs << "Invalid attachment index." << llendl;
  318. }
  319. gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]);
  320. }
  321. void LLRenderTarget::flush(BOOL fetch_depth)
  322. {
  323. gGL.flush();
  324. if (!mFBO)
  325. {
  326. gGL.getTexUnit(0)->bind(this);
  327. glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
  328. if (fetch_depth)
  329. {
  330. if (!mDepth)
  331. {
  332. allocateDepth();
  333. }
  334. gGL.getTexUnit(0)->bind(this);
  335. glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
  336. }
  337. gGL.getTexUnit(0)->disable();
  338. }
  339. else
  340. {
  341. #if !LL_DARWIN
  342. stop_glerror();
  343. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  344. stop_glerror();
  345. if (mSampleBuffer)
  346. {
  347. LLGLEnable multisample(GL_MULTISAMPLE_ARB);
  348. stop_glerror();
  349. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  350. stop_glerror();
  351. check_framebuffer_status();
  352. glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO);
  353. check_framebuffer_status();
  354. stop_glerror();
  355. glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
  356. stop_glerror();
  357. if (mTex.size() > 1)
  358. {
  359. for (U32 i = 1; i < mTex.size(); ++i)
  360. {
  361. glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
  362. LLTexUnit::getInternalType(mUsage), mTex[i], 0);
  363. stop_glerror();
  364. glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]);
  365. stop_glerror();
  366. glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);
  367. stop_glerror();
  368. }
  369. for (U32 i = 0; i < mTex.size(); ++i)
  370. {
  371. glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i,
  372. LLTexUnit::getInternalType(mUsage), mTex[i], 0);
  373. stop_glerror();
  374. glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]);
  375. stop_glerror();
  376. }
  377. }
  378. }
  379. #endif
  380. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  381. }
  382. }
  383. void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
  384. S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
  385. {
  386. #if !LL_DARWIN
  387. gGL.flush();
  388. if (!source.mFBO || !mFBO)
  389. {
  390. llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
  391. }
  392. if (mSampleBuffer)
  393. {
  394. mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
  395. }
  396. else
  397. {
  398. if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
  399. {
  400. stop_glerror();
  401. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO);
  402. gGL.getTexUnit(0)->bind(this, true);
  403. stop_glerror();
  404. glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
  405. stop_glerror();
  406. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  407. stop_glerror();
  408. }
  409. else
  410. {
  411. glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
  412. stop_glerror();
  413. glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO);
  414. stop_glerror();
  415. check_framebuffer_status();
  416. stop_glerror();
  417. glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
  418. stop_glerror();
  419. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  420. stop_glerror();
  421. }
  422. }
  423. #endif
  424. }
  425. //static
  426. void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
  427. S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
  428. {
  429. #if !LL_DARWIN
  430. if (!source.mFBO)
  431. {
  432. llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
  433. }
  434. {
  435. glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
  436. stop_glerror();
  437. glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
  438. stop_glerror();
  439. check_framebuffer_status();
  440. stop_glerror();
  441. glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
  442. stop_glerror();
  443. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  444. stop_glerror();
  445. }
  446. #endif
  447. }
  448. BOOL LLRenderTarget::isComplete() const
  449. {
  450. return (!mTex.empty() || mDepth) ? TRUE : FALSE;
  451. }
  452. void LLRenderTarget::getViewport(S32* viewport)
  453. {
  454. viewport[0] = 0;
  455. viewport[1] = 0;
  456. viewport[2] = mResX;
  457. viewport[3] = mResY;
  458. }
  459. //==================================================
  460. // LLMultisampleBuffer implementation
  461. //==================================================
  462. LLMultisampleBuffer::LLMultisampleBuffer()
  463. {
  464. }
  465. LLMultisampleBuffer::~LLMultisampleBuffer()
  466. {
  467. releaseSampleBuffer();
  468. }
  469. void LLMultisampleBuffer::releaseSampleBuffer()
  470. {
  471. if (mFBO)
  472. {
  473. glDeleteFramebuffersEXT(1, (GLuint *) &mFBO);
  474. mFBO = 0;
  475. }
  476. if (mTex.size() > 0)
  477. {
  478. glDeleteRenderbuffersEXT(mTex.size(), (GLuint *) &mTex[0]);
  479. mTex.clear();
  480. }
  481. if (mDepth)
  482. {
  483. glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth);
  484. mDepth = 0;
  485. }
  486. }
  487. void LLMultisampleBuffer::bindTarget()
  488. {
  489. bindTarget(this);
  490. }
  491. void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
  492. {
  493. if (!ref)
  494. {
  495. ref = this;
  496. }
  497. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  498. if (gGLManager.mHasDrawBuffers)
  499. { //setup multiple render targets
  500. GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
  501. GL_COLOR_ATTACHMENT1_EXT,
  502. GL_COLOR_ATTACHMENT2_EXT,
  503. GL_COLOR_ATTACHMENT3_EXT};
  504. glDrawBuffersARB(ref->mTex.size(), drawbuffers);
  505. }
  506. check_framebuffer_status();
  507. glViewport(0, 0, mResX, mResY);
  508. sBoundTarget = this;
  509. }
  510. void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil,  LLTexUnit::eTextureType usage, BOOL use_fbo )
  511. {
  512. allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2);
  513. }
  514. void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil,  LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples )
  515. {
  516. stop_glerror();
  517. mResX = resx;
  518. mResY = resy;
  519. mUsage = usage;
  520. mUseDepth = depth;
  521. mStencil = stencil;
  522. releaseSampleBuffer();
  523. if (!gGLManager.mHasFramebufferMultisample)
  524. {
  525. llerrs << "Attempting to allocate unsupported render target type!" << llendl;
  526. }
  527. mSamples = samples;
  528. if (mSamples <= 1)
  529. {
  530. llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl;
  531. }
  532. stop_glerror();
  533. if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
  534. {
  535. if (depth)
  536. {
  537. stop_glerror();
  538. allocateDepth();
  539. stop_glerror();
  540. }
  541. glGenFramebuffersEXT(1, (GLuint *) &mFBO);
  542. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  543. if (mDepth)
  544. {
  545. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);
  546. if (mStencil)
  547. {
  548. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth);
  549. }
  550. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  551. }
  552. stop_glerror();
  553. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  554. stop_glerror();
  555. }
  556. addColorAttachment(color_fmt);
  557. }
  558. void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
  559. {
  560. #if !LL_DARWIN
  561. if (color_fmt == 0)
  562. {
  563. return;
  564. }
  565. U32 offset = mTex.size();
  566. if (offset >= 4 ||
  567. (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
  568. {
  569. llerrs << "Too many color attachments!" << llendl;
  570. }
  571. U32 tex;
  572. glGenRenderbuffersEXT(1, &tex);
  573. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tex);
  574. glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, color_fmt, mResX, mResY);
  575. stop_glerror();
  576. if (mFBO)
  577. {
  578. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
  579. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, GL_RENDERBUFFER_EXT, tex);
  580. stop_glerror();
  581. GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  582. switch (status)
  583. {
  584. case GL_FRAMEBUFFER_COMPLETE_EXT:
  585. break;
  586. case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
  587. llerrs << "WTF?" << llendl;
  588. break;
  589. default:
  590. llerrs << "WTF?" << llendl;
  591. }
  592. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  593. }
  594. mTex.push_back(tex);
  595. #endif
  596. }
  597. void LLMultisampleBuffer::allocateDepth()
  598. {
  599. #if !LL_DARWIN
  600. glGenRenderbuffersEXT(1, (GLuint* ) &mDepth);
  601. glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);
  602. if (mStencil)
  603. {
  604. glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH24_STENCIL8_EXT, mResX, mResY);
  605. }
  606. else
  607. {
  608. glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY);
  609. }
  610. #endif
  611. }