llrendertarget.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. /**
  2. * @file llrendertarget.cpp
  3. * @brief LLRenderTarget implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, 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 <utility>
  34. #include "llrendertarget.h"
  35. #include "llgl.h"
  36. #include "llimagegl.h"
  37. #include "llrender.h"
  38. // statics
  39. U32 LLRenderTarget::sBytesAllocated = 0;
  40. bool LLRenderTarget::sUseFBO = false;
  41. U32 LLRenderTarget::sCurFBO = 0;
  42. U32 LLRenderTarget::sCurResX = 0;
  43. U32 LLRenderTarget::sCurResY = 0;
  44. static LLRenderTarget* sBoundTarget = NULL;
  45. void check_framebuffer_status()
  46. {
  47. if (gDebugGL)
  48. {
  49. GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
  50. if (status != GL_FRAMEBUFFER_COMPLETE)
  51. {
  52. llwarns << "Frame buffer failed check with status: " << std::hex
  53. << status << std::dec << llendl;
  54. }
  55. stop_glerror();
  56. }
  57. }
  58. LLRenderTarget::LLRenderTarget()
  59. : mPreviousRT(NULL),
  60. mResX(0),
  61. mResY(0),
  62. mFBO(0),
  63. mPreviousFBO(0),
  64. mPreviousResX(0),
  65. mPreviousResY(0),
  66. mDepth(0),
  67. mUsage(LLTexUnit::TT_TEXTURE),
  68. mGenerateMipMaps(LLTexUnit::TMG_NONE),
  69. mMipLevels(0),
  70. mUseDepth(false),
  71. mStencil(false)
  72. {
  73. }
  74. LLRenderTarget::~LLRenderTarget()
  75. {
  76. release();
  77. }
  78. //static
  79. void LLRenderTarget::reset()
  80. {
  81. sCurFBO = 0;
  82. sCurResX = sCurResY = 0;
  83. sBoundTarget = NULL;
  84. }
  85. void LLRenderTarget::resize(U32 resx, U32 resy)
  86. {
  87. // For accounting, get the number of pixels added/subtracted
  88. S32 pix_diff = resx * resy - mResX * mResY;
  89. mResX = resx;
  90. mResY = resy;
  91. llassert(mInternalFormat.size() == mTex.size());
  92. U32 internal_type = LLTexUnit::getInternalType(mUsage);
  93. LLTexUnit* unit0 = gGL.getTexUnit(0);
  94. for (U32 i = 0, size = mTex.size(); i < size; ++i)
  95. {
  96. // Resize color attachments
  97. unit0->bindManual(mUsage, mTex[i]);
  98. LLImageGL::setManualImage(internal_type, 0, mInternalFormat[i],
  99. mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE,
  100. NULL, false);
  101. sBytesAllocated += pix_diff * 4;
  102. }
  103. if (mDepth)
  104. {
  105. // Resize depth attachment
  106. if (mStencil)
  107. {
  108. // Use render buffers where stencil buffers are in play
  109. glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
  110. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
  111. mResX, mResY);
  112. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  113. }
  114. else
  115. {
  116. unit0->bindManual(mUsage, mDepth);
  117. LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24,
  118. mResX, mResY, GL_DEPTH_COMPONENT,
  119. GL_UNSIGNED_INT, NULL, false);
  120. }
  121. sBytesAllocated += pix_diff * 4;
  122. }
  123. }
  124. // Legacy EE renderer version
  125. bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth,
  126. bool stencil, LLTexUnit::eTextureType usage)
  127. {
  128. resx = llmin(resx, gGLManager.mGLMaxTextureSize);
  129. resy = llmin(resy, gGLManager.mGLMaxTextureSize);
  130. release();
  131. stop_glerror();
  132. mResX = resx;
  133. mResY = resy;
  134. mStencil = stencil;
  135. mUsage = usage;
  136. mUseDepth = depth;
  137. if (sUseFBO)
  138. {
  139. if (depth)
  140. {
  141. if (!allocateDepth())
  142. {
  143. llwarns << "Failed to allocate depth buffer for render target."
  144. << llendl;
  145. return false;
  146. }
  147. }
  148. glGenFramebuffers(1, (GLuint*)&mFBO);
  149. if (mDepth)
  150. {
  151. stop_glerror();
  152. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  153. if (mStencil)
  154. {
  155. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  156. GL_RENDERBUFFER, mDepth);
  157. glFramebufferRenderbuffer(GL_FRAMEBUFFER,
  158. GL_STENCIL_ATTACHMENT,
  159. GL_RENDERBUFFER, mDepth);
  160. }
  161. else
  162. {
  163. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  164. LLTexUnit::getInternalType(mUsage),
  165. mDepth, 0);
  166. }
  167. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  168. stop_glerror();
  169. }
  170. }
  171. return addColorAttachment(color_fmt);
  172. }
  173. // New PBR renderer version
  174. bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth,
  175. LLTexUnit::eTextureType usage,
  176. LLTexUnit::eMipGeneration mips_generation)
  177. {
  178. resx = llmin(resx, gGLManager.mGLMaxTextureSize);
  179. resy = llmin(resy, gGLManager.mGLMaxTextureSize);
  180. release();
  181. stop_glerror();
  182. mResX = resx;
  183. mResY = resy;
  184. mUsage = usage;
  185. mStencil = false;
  186. mUseDepth = depth;
  187. mGenerateMipMaps = mips_generation;
  188. if (mips_generation != LLTexUnit::TMG_NONE)
  189. {
  190. mMipLevels = 1 + log2f(F32(llmax(resx, resy)));
  191. }
  192. if (depth && !allocateDepth())
  193. {
  194. llwarns << "Failed to allocate depth buffer for render target."
  195. << llendl;
  196. return false;
  197. }
  198. glGenFramebuffers(1, (GLuint*)&mFBO);
  199. if (mDepth)
  200. {
  201. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  202. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  203. LLTexUnit::getInternalType(mUsage), mDepth, 0);
  204. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  205. stop_glerror();
  206. }
  207. return addColorAttachment(color_fmt);
  208. }
  209. void LLRenderTarget::setColorAttachment(LLImageGL* imgp, U32 use_name)
  210. {
  211. // This method only works when img is not NULL, FBO support is enabled,
  212. // depth buffers are not in use, mTex is empty (binding target should be
  213. // done via LLImageGL).
  214. llassert(imgp && sUseFBO && mDepth == 0 && mTex.empty());
  215. if (!mFBO)
  216. {
  217. glGenFramebuffers(1, (GLuint*)&mFBO);
  218. }
  219. mResX = imgp->getWidth();
  220. mResY = imgp->getHeight();
  221. mUsage = imgp->getTarget();
  222. if (!use_name)
  223. {
  224. use_name = imgp->getTexName();
  225. }
  226. mTex.push_back(use_name);
  227. stop_glerror();
  228. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  229. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  230. LLTexUnit::getInternalType(mUsage), use_name, 0);
  231. check_framebuffer_status();
  232. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  233. stop_glerror();
  234. }
  235. void LLRenderTarget::releaseColorAttachment()
  236. {
  237. // Cannot use releaseColorAttachment with LLRenderTarget managed color
  238. // targets
  239. llassert(mFBO && mTex.size() == 1);
  240. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  241. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  242. LLTexUnit::getInternalType(mUsage), 0, 0);
  243. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  244. mTex.clear();
  245. }
  246. bool LLRenderTarget::addColorAttachment(U32 color_fmt)
  247. {
  248. if (color_fmt == 0)
  249. {
  250. return true;
  251. }
  252. U32 offset = mTex.size();
  253. if (offset >= 4)
  254. {
  255. llwarns << "Too many color attachments !" << llendl;
  256. return false;
  257. }
  258. if (offset > 0 && !mFBO)
  259. {
  260. llwarns << "FBO not in use, aborting." << llendl;
  261. return false;
  262. }
  263. U32 tex;
  264. LLImageGL::generateTextures(1, &tex);
  265. LLTexUnit* unit0 = gGL.getTexUnit(0);
  266. unit0->bindManual(mUsage, tex);
  267. clear_glerror();
  268. U32 internal_type = LLTexUnit::getInternalType(mUsage);
  269. LLImageGL::setManualImage(internal_type, 0, color_fmt, mResX, mResY,
  270. GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
  271. if (glGetError() != GL_NO_ERROR)
  272. {
  273. llwarns << "Could not allocate color buffer for render target."
  274. << llendl;
  275. return false;
  276. }
  277. sBytesAllocated += mResX * mResY * 4;
  278. if (offset == 0)
  279. {
  280. // Use bilinear filtering on single texture render targets that are not
  281. // multisampled
  282. unit0->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
  283. }
  284. else
  285. {
  286. // Do not filter data attachments
  287. unit0->setTextureFilteringOption(LLTexUnit::TFO_POINT);
  288. }
  289. if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
  290. {
  291. unit0->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
  292. }
  293. else
  294. {
  295. // ATI does not support mirrored repeat for rectangular textures.
  296. unit0->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
  297. }
  298. stop_glerror();
  299. if (mFBO)
  300. {
  301. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  302. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + offset,
  303. internal_type, tex, 0);
  304. check_framebuffer_status();
  305. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  306. stop_glerror();
  307. }
  308. mTex.push_back(tex);
  309. mInternalFormat.push_back(color_fmt);
  310. if (gDebugGL)
  311. {
  312. // Bind and unbind to validate target
  313. bindTarget();
  314. flush();
  315. }
  316. return true;
  317. }
  318. bool LLRenderTarget::allocateDepth()
  319. {
  320. if (mStencil)
  321. {
  322. // Use render buffers where stencil buffers are in play
  323. glGenRenderbuffers(1, (GLuint*)&mDepth);
  324. glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
  325. clear_glerror();
  326. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
  327. mResX, mResY);
  328. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  329. }
  330. else
  331. {
  332. LLImageGL::generateTextures(1, &mDepth);
  333. LLTexUnit* unit0 = gGL.getTexUnit(0);
  334. unit0->bindManual(mUsage, mDepth);
  335. clear_glerror();
  336. LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0,
  337. GL_DEPTH_COMPONENT24, mResX, mResY,
  338. GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL,
  339. false);
  340. unit0->setTextureFilteringOption(LLTexUnit::TFO_POINT);
  341. }
  342. if (glGetError() != GL_NO_ERROR)
  343. {
  344. llwarns << "Unable to allocate depth buffer for render target."
  345. << llendl;
  346. return false;
  347. }
  348. sBytesAllocated += mResX * mResY * 4;
  349. return true;
  350. }
  351. void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
  352. {
  353. if (!mFBO || !target.mFBO)
  354. {
  355. llerrs << "Cannot share depth buffer between non FBO render targets."
  356. << llendl;
  357. }
  358. if (target.mDepth)
  359. {
  360. llerrs << "Attempting to override existing depth buffer. Detach existing buffer first."
  361. << llendl;
  362. }
  363. if (target.mUseDepth)
  364. {
  365. llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first."
  366. << llendl;
  367. }
  368. if (mDepth)
  369. {
  370. stop_glerror();
  371. glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
  372. if (mStencil)
  373. {
  374. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  375. GL_RENDERBUFFER, mDepth);
  376. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
  377. GL_RENDERBUFFER, mDepth);
  378. target.mStencil = true;
  379. }
  380. else
  381. {
  382. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  383. LLTexUnit::getInternalType(mUsage),
  384. mDepth, 0);
  385. }
  386. check_framebuffer_status();
  387. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  388. stop_glerror();
  389. target.mUseDepth = true;
  390. }
  391. }
  392. void LLRenderTarget::release()
  393. {
  394. // New PBR renderer version
  395. if (gUsePBRShaders)
  396. {
  397. if (mDepth)
  398. {
  399. LLImageGL::deleteTextures(1, &mDepth);
  400. mDepth = 0;
  401. sBytesAllocated -= mResX * mResY * 4;
  402. }
  403. else if (mFBO)
  404. {
  405. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  406. if (mUseDepth)
  407. {
  408. // Detach shared depth buffer
  409. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  410. LLTexUnit::getInternalType(mUsage),
  411. 0, 0);
  412. mUseDepth = false;
  413. }
  414. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  415. }
  416. size_t tsize = mTex.size();
  417. // Detach any extra color buffers (e.g. SRGB spec buffers)
  418. if (tsize > 1 && mFBO)
  419. {
  420. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  421. U32 internal_type = LLTexUnit::getInternalType(mUsage);
  422. for (size_t z = tsize - 1; z > 0 ; --z)
  423. {
  424. glFramebufferTexture2D(GL_FRAMEBUFFER,
  425. GL_COLOR_ATTACHMENT0 + z,
  426. internal_type, 0, 0);
  427. }
  428. LLImageGL::deleteTextures(tsize - 1, &mTex[1]);
  429. sBytesAllocated -= mResX * mResY * 4 * (tsize - 1);
  430. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  431. }
  432. if (mFBO)
  433. {
  434. if (mFBO == sCurFBO)
  435. {
  436. sCurFBO = 0;
  437. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  438. }
  439. glDeleteFramebuffers(1, (GLuint*)&mFBO);
  440. mFBO = 0;
  441. }
  442. if (tsize)
  443. {
  444. LLImageGL::deleteTextures(1, &mTex[0]);
  445. sBytesAllocated -= mResX * mResY * 4;
  446. }
  447. mTex.clear();
  448. mInternalFormat.clear();
  449. mResX = mResY = 0;
  450. return;
  451. }
  452. // Legacy EE renderer version
  453. if (mDepth)
  454. {
  455. if (mStencil)
  456. {
  457. glDeleteRenderbuffers(1, (GLuint*)&mDepth);
  458. }
  459. else
  460. {
  461. if (mFBO)
  462. {
  463. // Release before delete.
  464. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  465. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  466. LLTexUnit::getInternalType(mUsage),
  467. 0, 0);
  468. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  469. }
  470. LLImageGL::deleteTextures(1, &mDepth);
  471. }
  472. mDepth = 0;
  473. sBytesAllocated -= mResX * mResY * 4;
  474. }
  475. else if (mUseDepth && mFBO)
  476. {
  477. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  478. // Detach shared depth buffer
  479. if (mStencil)
  480. {
  481. // Attached as a renderbuffer
  482. glFramebufferRenderbuffer(GL_FRAMEBUFFER,
  483. GL_STENCIL_ATTACHMENT,
  484. GL_RENDERBUFFER, 0);
  485. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  486. GL_RENDERBUFFER, 0);
  487. mStencil = false;
  488. }
  489. else
  490. {
  491. // Attached as a texture
  492. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  493. LLTexUnit::getInternalType(mUsage), 0, 0);
  494. }
  495. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  496. mUseDepth = false;
  497. }
  498. if (mFBO)
  499. {
  500. glDeleteFramebuffers(1, (GLuint*)&mFBO);
  501. mFBO = 0;
  502. }
  503. stop_glerror();
  504. size_t tsize = mTex.size();
  505. if (tsize > 0)
  506. {
  507. sBytesAllocated -= mResX * mResY * 4 * tsize;
  508. LLImageGL::deleteTextures(tsize, &mTex[0]);
  509. mTex.clear();
  510. mInternalFormat.clear();
  511. }
  512. mResX = mResY = 0;
  513. }
  514. void LLRenderTarget::bindTarget()
  515. {
  516. static const GLenum drawbuffers[] =
  517. {
  518. GL_COLOR_ATTACHMENT0,
  519. GL_COLOR_ATTACHMENT1,
  520. GL_COLOR_ATTACHMENT2,
  521. GL_COLOR_ATTACHMENT3
  522. };
  523. // New PBR renderer version
  524. if (gUsePBRShaders)
  525. {
  526. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  527. sCurFBO = mFBO;
  528. if (mTex.empty())
  529. {
  530. // No color buffer to draw to
  531. glDrawBuffer(GL_NONE);
  532. glReadBuffer(GL_NONE);
  533. }
  534. else
  535. {
  536. // Setup multiple render targets
  537. glDrawBuffers(mTex.size(), drawbuffers);
  538. }
  539. check_framebuffer_status();
  540. glViewport(0, 0, mResX, mResY);
  541. sCurResX = mResX;
  542. sCurResY = mResY;
  543. mPreviousRT = sBoundTarget;
  544. sBoundTarget = this;
  545. return;
  546. }
  547. // Legacy EE renderer version
  548. if (mFBO)
  549. {
  550. mPreviousFBO = sCurFBO;
  551. glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
  552. sCurFBO = mFBO;
  553. if (mTex.empty())
  554. {
  555. // No color buffer to draw to
  556. glDrawBuffer(GL_NONE);
  557. glReadBuffer(GL_NONE);
  558. }
  559. else
  560. {
  561. // Setup multiple render targets
  562. glDrawBuffers(mTex.size(), drawbuffers);
  563. }
  564. check_framebuffer_status();
  565. }
  566. mPreviousResX = sCurResX;
  567. mPreviousResY = sCurResY;
  568. glViewport(0, 0, sCurResX = mResX, sCurResY = mResY);
  569. }
  570. void LLRenderTarget::clear(U32 mask_in)
  571. {
  572. U32 mask = GL_COLOR_BUFFER_BIT;
  573. if (mUseDepth)
  574. {
  575. if (gUsePBRShaders)
  576. {
  577. mask |= GL_DEPTH_BUFFER_BIT;
  578. }
  579. else
  580. {
  581. mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
  582. }
  583. }
  584. if (mFBO)
  585. {
  586. check_framebuffer_status();
  587. glClear(mask & mask_in);
  588. }
  589. else
  590. {
  591. LLGLEnable scissor(GL_SCISSOR_TEST);
  592. glScissor(0, 0, mResX, mResY);
  593. glClear(mask & mask_in);
  594. }
  595. stop_glerror();
  596. }
  597. U32 LLRenderTarget::getTexture(U32 attachment) const
  598. {
  599. if (attachment > mTex.size() - 1)
  600. {
  601. llerrs << "Invalid attachment index." << llendl;
  602. }
  603. return mTex.empty() ? 0 : mTex[attachment];
  604. }
  605. void LLRenderTarget::bindTexture(U32 index, S32 channel,
  606. LLTexUnit::eTextureFilterOptions filter_opt)
  607. {
  608. LLTexUnit* unitp = gGL.getTexUnit(channel);
  609. bool has_mips = gUsePBRShaders &&
  610. (filter_opt == LLTexUnit::TFO_TRILINEAR ||
  611. filter_opt == LLTexUnit::TFO_ANISOTROPIC);
  612. unitp->bindManual(mUsage, getTexture(index), has_mips);
  613. unitp->setTextureFilteringOption(filter_opt);
  614. if (index < mInternalFormat.size())
  615. {
  616. U32 format = mInternalFormat[index];
  617. LLTexUnit::eTextureColorSpace space;
  618. if (format == GL_SRGB || format == GL_SRGB8 ||
  619. format == GL_SRGB_ALPHA || format == GL_SRGB8_ALPHA8)
  620. {
  621. space = LLTexUnit::TCS_SRGB;
  622. }
  623. else
  624. {
  625. space = LLTexUnit::TCS_LINEAR;
  626. }
  627. unitp->setTextureColorSpace(space);
  628. }
  629. else
  630. {
  631. llwarns << "Out of range 'index': " << index << " (max is "
  632. << mInternalFormat.size() - 1 << ")" << llendl;
  633. llassert_always(!gDebugGL);
  634. unitp->setTextureColorSpace(LLTexUnit::TCS_LINEAR);
  635. }
  636. }
  637. void LLRenderTarget::flush(bool fetch_depth)
  638. {
  639. gGL.flush();
  640. // New PBR renderer version
  641. if (gUsePBRShaders)
  642. {
  643. if (mGenerateMipMaps == LLTexUnit::TMG_AUTO)
  644. {
  645. bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR);
  646. glGenerateMipmap(GL_TEXTURE_2D);
  647. }
  648. if (mPreviousRT)
  649. {
  650. // *HACK: pop the RT stack back two frames and push the previous
  651. // frame back on to play nice with the GL state machine.
  652. sBoundTarget = mPreviousRT->mPreviousRT;
  653. mPreviousRT->bindTarget();
  654. }
  655. else
  656. {
  657. sBoundTarget = NULL;
  658. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  659. sCurFBO = 0;
  660. sCurResX = gGLViewport[2];
  661. sCurResY = gGLViewport[3];
  662. glViewport(gGLViewport[0], gGLViewport[1], sCurResX, sCurResY);
  663. glReadBuffer(GL_BACK);
  664. glDrawBuffer(GL_BACK);
  665. }
  666. return;
  667. }
  668. // Legacy EE renderer version
  669. if (!mFBO)
  670. {
  671. LLTexUnit* unit0 = gGL.getTexUnit(0);
  672. unit0->bind(this);
  673. U32 internal_type = LLTexUnit::getInternalType(mUsage);
  674. glCopyTexSubImage2D(internal_type, 0, 0, 0, 0, 0, mResX, mResY);
  675. if (fetch_depth)
  676. {
  677. if (!mDepth)
  678. {
  679. allocateDepth();
  680. }
  681. unit0->bind(this, true);
  682. glCopyTexSubImage2D(internal_type, 0, 0, 0, 0, 0, mResX, mResY);
  683. }
  684. unit0->disable();
  685. }
  686. else
  687. {
  688. glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO);
  689. sCurFBO = mPreviousFBO;
  690. if (mPreviousFBO)
  691. {
  692. glViewport(0, 0, sCurResX = mPreviousResX, sCurResY = mPreviousResY);
  693. mPreviousFBO = 0;
  694. }
  695. else
  696. {
  697. glViewport(gGLViewport[0], gGLViewport[1],
  698. sCurResX = gGLViewport[2], sCurResY = gGLViewport[3]);
  699. }
  700. }
  701. stop_glerror();
  702. }
  703. void LLRenderTarget::copyContents(LLRenderTarget& source,
  704. S32 src_x0, S32 src_y0,
  705. S32 src_x1, S32 src_y1,
  706. S32 dst_x0, S32 dst_y0,
  707. S32 dst_x1, S32 dst_y1,
  708. U32 mask, U32 filter)
  709. {
  710. GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? GL_TRUE : GL_FALSE;
  711. LLGLDepthTest depth(write_depth, write_depth);
  712. gGL.flush();
  713. if (!source.mFBO || !mFBO)
  714. {
  715. llwarns << "Cannot copy framebuffer contents for non FBO render targets."
  716. << llendl;
  717. return;
  718. }
  719. stop_glerror();
  720. if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
  721. {
  722. glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
  723. check_framebuffer_status();
  724. gGL.getTexUnit(0)->bind(this, true);
  725. glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0,
  726. src_x0, src_y0, dst_x0, dst_y0, dst_x1, dst_y1);
  727. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  728. }
  729. else
  730. {
  731. glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
  732. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
  733. check_framebuffer_status();
  734. glBlitFramebuffer(src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0,
  735. dst_x1, dst_y1, mask, filter);
  736. glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
  737. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  738. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  739. }
  740. stop_glerror();
  741. }
  742. //static
  743. void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source,
  744. S32 src_x0, S32 src_y0,
  745. S32 src_x1, S32 src_y1,
  746. S32 dst_x0, S32 dst_y0,
  747. S32 dst_x1, S32 dst_y1,
  748. U32 mask, U32 filter)
  749. {
  750. if (!source.mFBO)
  751. {
  752. llwarns << "Cannot copy framebuffer contents for non FBO render targets."
  753. << llendl;
  754. return;
  755. }
  756. GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
  757. LLGLDepthTest depth(write_depth, write_depth);
  758. stop_glerror();
  759. glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
  760. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  761. check_framebuffer_status();
  762. glBlitFramebuffer(src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1,
  763. dst_y1, mask, filter);
  764. glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
  765. stop_glerror();
  766. }
  767. bool LLRenderTarget::isComplete() const
  768. {
  769. return !mTex.empty() || mDepth;
  770. }
  771. void LLRenderTarget::getViewport(S32* viewport)
  772. {
  773. viewport[0] = viewport[1] = 0;
  774. viewport[2] = mResX;
  775. viewport[3] = mResY;
  776. }
  777. void LLRenderTarget::swapFBORefs(LLRenderTarget& other)
  778. {
  779. if (mResX != other.mResX || mResY != other.mResY)
  780. {
  781. llwarns_sparse << "FBOs sizes do not match." << llendl;
  782. llassert(false);
  783. return;
  784. }
  785. if (mUsage != other.mUsage || mUseDepth != other.mUseDepth ||
  786. mDepth != other.mDepth || mMipLevels != other.mMipLevels ||
  787. mGenerateMipMaps != other.mGenerateMipMaps ||
  788. mTex.size() != other.mTex.size() ||
  789. mInternalFormat.size() != other.mInternalFormat.size())
  790. {
  791. llwarns_sparse << "FBOs parameters do not match." << llendl;
  792. llassert(false);
  793. return;
  794. }
  795. std::swap(mFBO, other.mFBO);
  796. std::swap(mTex, other.mTex);
  797. }