From fd21197d2a48c4225e048fe025ca19a9224f4c4c Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 25 Feb 2013 12:59:17 -0600 Subject: [PATCH] Wedged high-res non-tiled deferred snapshot logic into LLViewerWindow::rawRawSnapshot --- indra/llrender/llrendertarget.cpp | 61 ++++++++++++++++++------------- indra/llrender/llrendertarget.h | 5 +-- indra/newview/llviewerwindow.cpp | 49 +++++++++++++++++++++++-- indra/newview/pipeline.cpp | 8 ++-- 4 files changed, 85 insertions(+), 38 deletions(-) diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index aa6278417..977245b6e 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -51,11 +51,13 @@ void check_framebuffer_status() } bool LLRenderTarget::sUseFBO = false; +U32 LLRenderTarget::sCurFBO = 0; LLRenderTarget::LLRenderTarget() : mResX(0), mResY(0), mFBO(0), + mPreviousFBO(0), mDepth(0), mStencil(0), mUseDepth(false), @@ -117,6 +119,9 @@ void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo) { + resx = llmin(resx, (U32) 4096); + resy = llmin(resy, (U32) 4096); + stop_glerror(); release(); stop_glerror(); @@ -156,7 +161,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); } stop_glerror(); @@ -173,10 +178,19 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } U32 offset = mTex.size(); - if (offset >= 4 || - (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) + + if( offset >= 4 ) { - llerrs << "Too many color attachments!" << llendl; + llwarns << "Too many color attachments" << llendl; + llassert( offset < 4 ); + return false; + } + if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) ) + { + llwarns << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << llendl; + llassert( mFBO != 0 ); + llassert( gGLManager.mHasDrawBuffers ); + return false; } U32 tex; @@ -234,7 +248,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); } mTex.push_back(tex); @@ -329,7 +343,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); target.mUseDepth = true; } @@ -400,14 +414,18 @@ void LLRenderTarget::bindTarget() if (mFBO) { stop_glerror(); + mPreviousFBO = sCurFBO; if (mSampleBuffer) { mSampleBuffer->bindTarget(this); + sCurFBO = mSampleBuffer->mFBO; stop_glerror(); } else { glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + sCurFBO = mFBO; + stop_glerror(); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets @@ -434,16 +452,6 @@ void LLRenderTarget::bindTarget() sBoundTarget = this; } -// static -void LLRenderTarget::unbindTarget() -{ - if (gGLManager.mHasFramebufferObject) - { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } - sBoundTarget = NULL; -} - void LLRenderTarget::clear(U32 mask_in) { U32 mask = GL_COLOR_BUFFER_BIT; @@ -512,10 +520,7 @@ void LLRenderTarget::flush(bool fetch_depth) else { stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - stop_glerror(); - - if (mSampleBuffer) + if(mSampleBuffer) { LLGLEnable multisample(GL_MULTISAMPLE); stop_glerror(); @@ -570,10 +575,14 @@ void LLRenderTarget::flush(bool fetch_depth) stop_glerror(); }*/ } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } + glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO); + sCurFBO = mPreviousFBO; + stop_glerror(); } } + void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { @@ -604,7 +613,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, stop_glerror(); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); } else @@ -627,7 +636,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, stop_glerror(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); } } @@ -661,7 +670,7 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 if(mask) glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); } } @@ -810,7 +819,7 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth } stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); @@ -889,7 +898,7 @@ bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt) glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex); check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); } mTex.push_back(tex); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 14eea5a4a..c2696aae6 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -65,6 +65,7 @@ public: //whether or not to use FBO implementation static bool sUseFBO; static U32 sBytesAllocated; + static U32 sCurFBO; LLRenderTarget(); virtual ~LLRenderTarget(); @@ -101,9 +102,6 @@ public: //applies appropriate viewport virtual void bindTarget(); - //unbind target for rendering - static void unbindTarget(); - //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode void clear(U32 mask = 0xFFFFFFFF); @@ -156,6 +154,7 @@ protected: std::vector mTex; std::vector mInternalFormat; U32 mFBO; + U32 mPreviousFBO; U32 mDepth; bool mStencil; bool mUseDepth; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b44870e21..ce337fce0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4349,8 +4349,8 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // Copy screen to a buffer LLRect const window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); - S32 const window_width = window_rect.getWidth(); - S32 const window_height = window_rect.getHeight(); + S32 window_width = window_rect.getWidth(); + S32 window_height = window_rect.getHeight(); // SNAPSHOT @@ -4378,7 +4378,7 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, S32 buffer_x_offset = 0; S32 buffer_y_offset = 0; - F32 scale_factor; + F32 scale_factor = 1.0f; S32 image_buffer_x; S32 image_buffer_y; @@ -4386,6 +4386,36 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // snapshot fits precisely inside window, it is the portion of the window with the correct aspect. F32 snapshot_width = (snapshot_aspect > window_aspect) ? (F32)window_width : window_height * snapshot_aspect; F32 snapshot_height = (snapshot_aspect < window_aspect) ? (F32)window_height : window_width / snapshot_aspect; + + //This is what I would classify as a hack. If in deferred then do not tile (window_*=snapshot_*=image_*, ratio=scale_factor=1.f) + S32 original_width = 0; + S32 original_height = 0; + bool reset_deferred = false; + LLRenderTarget scratch_space; + if ((image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) + { + if (scratch_space.allocate(image_width, image_height, GL_RGBA, true, true)) + { + original_width = gPipeline.mDeferredScreen.getWidth(); + original_height = gPipeline.mDeferredScreen.getHeight(); + + if (gPipeline.allocateScreenBuffer(image_width, image_height)) + { + image_width = snapshot_width = window_width = scratch_space.getWidth(); + image_height = snapshot_height = window_height = scratch_space.getHeight(); + reset_deferred = true; + mWindowRectRaw.set(0, image_height, image_width, 0); + scratch_space.bindTarget(); + } + else + { + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + } + } + } + + // ratio is the ratio snapshot/image', where image' is a rectangle with aspect snapshot_aspect that precisely contains image. // Thus image_width' / image_height' == aspect ==> snapshot_width / image_width' == snapshot_height / image_height'. // Since image' precisely contains image, one of them is equal (ie, image_height' = image_height) and the other is larger @@ -4406,7 +4436,7 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, image_buffer_x = llround(snapshot_width * scale_factor); image_buffer_y = llround(snapshot_height * scale_factor); if (llmax(image_buffer_x, image_buffer_y) > max_size && // Boundary check to avoid memory overflow. - internal_scale <= 1.f) // SHY_MOD: If supersampling... Don't care about max_size. + internal_scale <= 1.f && !reset_deferred) // SHY_MOD: If supersampling... Don't care about max_size. { // Too big, clamp. continue; @@ -4414,6 +4444,8 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // Done. break; } + + // Center the buffer. buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f); @@ -4577,6 +4609,15 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // objects on them. gPipeline.resetDrawOrders(); } + + if (reset_deferred) + { + mWindowRectRaw = window_rect; + scratch_space.flush(); + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + + } if (is_tiling) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index fff60e992..55ad60a5c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1020,7 +1020,7 @@ void LLPipeline::createGLBuffers() { mGlow[i].bindTarget(); mGlow[i].clear(); - mGlow[i].unbindTarget(); + mGlow[i].flush(); } } @@ -6728,11 +6728,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGlowProgram.unbind(); - if (LLRenderTarget::sUseFBO) + /*if (LLRenderTarget::sUseFBO) { LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); glBindFramebuffer(GL_FRAMEBUFFER, 0); - } + }*/ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; @@ -8414,8 +8414,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; - LLRenderTarget::unbindTarget(); - LLPipeline::sReflectionRender = FALSE; if (!LLRenderTarget::sUseFBO)