diff options
Diffstat (limited to 'indra/llrender/llrendertarget.cpp')
-rw-r--r-- | indra/llrender/llrendertarget.cpp | 394 |
1 files changed, 98 insertions, 296 deletions
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index cd2556d435..53c85e6c64 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -44,6 +44,7 @@ void check_framebuffer_status() case GL_FRAMEBUFFER_COMPLETE: break; default: + llwarns << "Bad framebuffer status: " << std::hex << status << llendl; ll_fail("check_framebuffer_status failed"); break; } @@ -62,8 +63,7 @@ LLRenderTarget::LLRenderTarget() : mUseDepth(false), mRenderDepth(false), mUsage(LLTexUnit::TT_TEXTURE), - mSamples(0), - mSampleBuffer(NULL) + mSamples(0) { } @@ -72,13 +72,7 @@ LLRenderTarget::~LLRenderTarget() release(); } - -void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) -{ - mSampleBuffer = buffer; -} - -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo) +void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { stop_glerror(); mResX = resx; @@ -87,6 +81,21 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo mStencil = stencil; mUsage = usage; mUseDepth = depth; + mSamples = samples; + + mSamples = llmin(mSamples, (U32) gGLManager.mMaxColorTextureSamples); + + if (mSamples > 0 && gGLManager.mHasTextureMultisample) + { + mSamples = llmin(mSamples, (U32) gGLManager.mMaxColorTextureSamples); + mUsage = LLTexUnit::TT_MULTISAMPLE_TEXTURE; + //no support for multisampled stencil targets yet + mStencil = false; + } + else + { + mSamples = 0; + } release(); @@ -145,29 +154,47 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) stop_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - stop_glerror(); - - if (offset == 0) + if (mSamples > 0) { - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE); } else - { //don't filter data attachments - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } - else - { - // ATI doesn't support mirrored repeat for rectangular textures. - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + stop_glerror(); + + if (mSamples == 0) + { + 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); @@ -196,9 +223,16 @@ void LLRenderTarget::allocateDepth() { LLImageGL::generateTextures(1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); - U32 internal_type = LLTexUnit::getInternalType(mUsage); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + if (mSamples == 0) + { + U32 internal_type = LLTexUnit::getInternalType(mUsage); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + } + else + { + glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE); + } } } @@ -288,7 +322,6 @@ void LLRenderTarget::release() mTex.clear(); } - mSampleBuffer = NULL; sBoundTarget = NULL; } @@ -297,34 +330,27 @@ void LLRenderTarget::bindTarget() if (mFBO) { stop_glerror(); - if (mSampleBuffer) - { - mSampleBuffer->bindTarget(this); - stop_glerror(); + + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + stop_glerror(); + if (gGLManager.mHasDrawBuffers) + { //setup multiple render targets + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3}; + glDrawBuffersARB(mTex.size(), drawbuffers); } - else - { - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - stop_glerror(); - if (gGLManager.mHasDrawBuffers) - { //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, - GL_COLOR_ATTACHMENT1, - GL_COLOR_ATTACHMENT2, - GL_COLOR_ATTACHMENT3}; - glDrawBuffersARB(mTex.size(), drawbuffers); - } - if (mTex.empty()) - { //no color buffer to draw to - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } + if (mTex.empty()) + { //no color buffer to draw to + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } - check_framebuffer_status(); + check_framebuffer_status(); - stop_glerror(); - } + stop_glerror(); } glViewport(0, 0, mResX, mResY); @@ -406,50 +432,8 @@ void LLRenderTarget::flush(bool fetch_depth) else { stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - stop_glerror(); - - if (mSampleBuffer) - { - LLGLEnable multisample(GL_MULTISAMPLE); - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - stop_glerror(); - check_framebuffer_status(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO); - check_framebuffer_status(); - - stop_glerror(); - glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - stop_glerror(); - - if (mTex.size() > 1) - { - for (U32 i = 1; i < mTex.size(); ++i) - { - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - LLTexUnit::getInternalType(mUsage), mTex[i], 0); - stop_glerror(); - glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); - stop_glerror(); - glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); - stop_glerror(); - } - - for (U32 i = 0; i < mTex.size(); ++i) - { - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, - LLTexUnit::getInternalType(mUsage), mTex[i], 0); - stop_glerror(); - glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); - stop_glerror(); - } - } - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); } } @@ -466,37 +450,31 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } - if (mSampleBuffer) + + if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) { - mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + stop_glerror(); + + glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO); + gGL.getTexUnit(0)->bind(this, true); + stop_glerror(); + glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + stop_glerror(); } else { - if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) - { - stop_glerror(); - - glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO); - gGL.getTexUnit(0)->bind(this, true); - stop_glerror(); - glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - stop_glerror(); - } - else - { - glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); - stop_glerror(); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO); - stop_glerror(); - check_framebuffer_status(); - stop_glerror(); - glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - stop_glerror(); - } + glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); + stop_glerror(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO); + stop_glerror(); + check_framebuffer_status(); + stop_glerror(); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + stop_glerror(); } } @@ -539,179 +517,3 @@ void LLRenderTarget::getViewport(S32* viewport) viewport[3] = mResY; } -//================================================== -// LLMultisampleBuffer implementation -//================================================== -LLMultisampleBuffer::LLMultisampleBuffer() -{ - -} - -LLMultisampleBuffer::~LLMultisampleBuffer() -{ - release(); -} - -void LLMultisampleBuffer::release() -{ - if (mFBO) - { - glDeleteFramebuffers(1, (GLuint *) &mFBO); - mFBO = 0; - } - - if (mTex.size() > 0) - { - glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]); - mTex.clear(); - } - - if (mDepth) - { - glDeleteRenderbuffers(1, (GLuint *) &mDepth); - mDepth = 0; - } -} - -void LLMultisampleBuffer::bindTarget() -{ - bindTarget(this); -} - -void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) -{ - if (!ref) - { - ref = this; - } - - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - if (gGLManager.mHasDrawBuffers) - { //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, - GL_COLOR_ATTACHMENT1, - GL_COLOR_ATTACHMENT2, - GL_COLOR_ATTACHMENT3}; - glDrawBuffersARB(ref->mTex.size(), drawbuffers); - } - - check_framebuffer_status(); - - glViewport(0, 0, mResX, mResY); - - sBoundTarget = this; -} - -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo ) -{ - allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); -} - -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) -{ - stop_glerror(); - mResX = resx; - mResY = resy; - - mUsage = usage; - mUseDepth = depth; - mStencil = stencil; - - release(); - - mSamples = samples; - - if (mSamples <= 1) - { - llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; - } - - stop_glerror(); - - if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) - { - - if (depth) - { - stop_glerror(); - allocateDepth(); - stop_glerror(); - } - - glGenFramebuffers(1, (GLuint *) &mFBO); - - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - - 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(); - } - - addColorAttachment(color_fmt); -} - -void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) -{ - if (color_fmt == 0) - { - return; - } - - 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); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY); - stop_glerror(); - - if (mFBO) - { - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex); - stop_glerror(); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - switch (status) - { - case GL_FRAMEBUFFER_COMPLETE: - break; - default: - llerrs << "WTF? " << std::hex << status << llendl; - break; - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } - - mTex.push_back(tex); -} - -void LLMultisampleBuffer::allocateDepth() -{ - glGenRenderbuffers(1, (GLuint* ) &mDepth); - glBindRenderbuffer(GL_RENDERBUFFER, mDepth); - if (mStencil) - { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); - } - else - { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16, mResX, mResY); - } -} - |