bool LLRenderTarget::allocateDepth() { if (mStencil) { //use render buffers where stencil buffers are in play glGenRenderbuffers(1, (GLuint *) &mDepth); glBindRenderbuffer(GL_RENDERBUFFER, mDepth); stop_glerror(); clear_glerror(); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); glBindRenderbuffer(GL_RENDERBUFFER, 0); } else { LLImageGL::generateTextures(1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); stop_glerror(); clear_glerror(); LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } sBytesAllocated += mResX*mResY*4; if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate depth buffer for render target." << llendl; return false; } return true; }
bool LLMultisampleBuffer::allocateDepth() { glGenRenderbuffers(1, (GLuint* ) &mDepth); glBindRenderbuffer(GL_RENDERBUFFER, mDepth); stop_glerror(); clear_glerror(); if (mStencil) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); } else { glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT24, mResX, mResY); } if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate depth buffer for multisample render target." << llendl; return false; } sBytesAllocated += mResX*mResY*4; return true; }
bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return true; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; glGenRenderbuffers(1, &tex); glBindRenderbuffer(GL_RENDERBUFFER, tex); stop_glerror(); clear_glerror(); glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY); if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate color buffer for multisample render target." << llendl; release(); return false; } sBytesAllocated += mResX*mResY*4; if (mFBO) { glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex); check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); return true; }
bool LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return true; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); { clear_glerror(); LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); if (glGetError() != GL_NO_ERROR) { llwarns << "Could not allocate color buffer for render target." << llendl; return false; } } sBytesAllocated += mResX*mResY*4; stop_glerror(); if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); stop_glerror(); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); stop_glerror(); } if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); stop_glerror(); } else { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } if (mFBO) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); if (gDebugGL) { //bind and unbind to validate target bindTarget(); flush(); } return true; }
bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) { release(); stop_glerror(); if (!gGLManager.mHasFramebufferMultisample || !gGLManager.mHasFramebufferObject || !(sUseFBO || use_fbo)) return false; if(color_fmt != GL_RGBA) { llwarns << "Unsupported color format: " << color_fmt << llendl; return false; } //Restrict to valid sample count { mSamples = samples; //mSamples = llmin(mSamples, (U32)4); //Cap to prevent memory bloat. mSamples = llmin(mSamples, (U32) gGLManager.mMaxSamples); } if (mSamples <= 1) return false; mResX = resx; mResY = resy; mUsage = usage; mUseDepth = depth; mStencil = stencil; mColorFormat = color_fmt; { if (depth) { stop_glerror(); if(!allocateDepth()) { release(); return false; } stop_glerror(); } glGenFramebuffers(1, (GLuint *) &mFBO); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); clear_glerror(); if (mDepth) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); if (mStencil) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); } } stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } return addColorAttachment(color_fmt); }