Commits

davep  committed cae2f41

MAINT-628 Fix for seams in high res snapshots when lighting and shadows is enabled.

  • Participants
  • Parent commits 013b732

Comments (0)

Files changed (6)

File indra/llrender/llrendertarget.cpp

 }
 
 bool LLRenderTarget::sUseFBO = false;
+U32 LLRenderTarget::sCurFBO = 0;
 
 LLRenderTarget::LLRenderTarget() :
 	mResX(0),
 	mResY(0),
 	mFBO(0),
+	mPreviousFBO(0),
 	mDepth(0),
 	mStencil(0),
 	mUseDepth(false),
 
 bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
 {
+	resx = llmin(resx, (U32) 4096);
+	resy = llmin(resy, (U32) 4096);
+
 	stop_glerror();
 	release();
 	stop_glerror();
 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
 				stop_glerror();
 			}
-			glBindFramebuffer(GL_FRAMEBUFFER, 0);
+			glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
 		}
 		
 		stop_glerror();
 
 		check_framebuffer_status();
 		
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
 	}
 
 	mTex.push_back(tex);
 
 		check_framebuffer_status();
 
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
 
 		target.mUseDepth = true;
 	}
 {
 	if (mFBO)
 	{
+		mPreviousFBO = sCurFBO;
+
 		stop_glerror();
 		
 		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+		sCurFBO = mFBO;
+
 		stop_glerror();
 		if (gGLManager.mHasDrawBuffers)
 		{ //setup multiple render targets
 	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;
 	else
 	{
 		stop_glerror();
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO);
+		sCurFBO = mPreviousFBO;
 		stop_glerror();
 	}
 }
 		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
 		stop_glerror();
 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 		stop_glerror();
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
 		stop_glerror();
 	}
 }
 		stop_glerror();
 		glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
 		stop_glerror();
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
 		stop_glerror();
 	}
 }

File indra/llrender/llrendertarget.h

 	//whether or not to use FBO implementation
 	static bool sUseFBO; 
 	static U32 sBytesAllocated;
+	static U32 sCurFBO;
 
 	LLRenderTarget();
 	~LLRenderTarget();
 	//applies appropriate viewport
 	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);
 	std::vector<U32> mTex;
 	std::vector<U32> mInternalFormat;
 	U32 mFBO;
+	U32 mPreviousFBO;
 	U32 mDepth;
 	bool mStencil;
 	bool mUseDepth;

File indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl

 uniform vec2 rcp_screen_res;
 uniform vec4 rcp_frame_opt;
 uniform vec4 rcp_frame_opt2;
-uniform vec2 screen_res;
 VARYING vec2 vary_fragcoord;
 VARYING vec2 vary_tc;
 

File indra/newview/llviewerwindow.cpp

 		image_height = llmin(image_height, window_height);
 	}
 
+	S32 original_width = 0;
+	S32 original_height = 0;
+	bool reset_deferred = false;
+
+	LLRenderTarget scratch_space;
+
 	F32 scale_factor = 1.0f ;
 	if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height))
 	{	
-		// if image cropping or need to enlarge the scene, compute a scale_factor
-		F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
-		snapshot_width  = (S32)(ratio * image_width) ;
-		snapshot_height = (S32)(ratio * image_height) ;
-		scale_factor = llmax(1.0f, 1.0f / ratio) ;
+		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))
+				{
+					window_width = image_width;
+					window_height = image_height;
+					snapshot_width = image_width;
+					snapshot_height = image_height;
+					reset_deferred = true;
+					mWorldViewRectRaw.set(0, image_height, image_width, 0);
+					scratch_space.bindTarget();
+				}
+				else
+				{
+					scratch_space.release();
+					gPipeline.allocateScreenBuffer(original_width, original_height);
+				}
+			}
+		}
+
+		if (!reset_deferred)
+		{
+			// if image cropping or need to enlarge the scene, compute a scale_factor
+			F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
+			snapshot_width  = (S32)(ratio * image_width) ;
+			snapshot_height = (S32)(ratio * image_height) ;
+			scale_factor = llmax(1.0f, 1.0f / ratio) ;
+		}
 	}
 	
 	if (show_ui && scale_factor > 1.f)
 		gPipeline.resetDrawOrders();
 	}
 
+	if (reset_deferred)
+	{
+		mWorldViewRectRaw = window_rect;
+		scratch_space.flush();
+		scratch_space.release();
+		gPipeline.allocateScreenBuffer(original_width, original_height);
+		
+	}
+
 	if (high_res)
 	{
 		send_agent_resume();
 	}
-
+	
 	return ret;
 }
 

File indra/newview/pipeline.cpp

 	}
 }
 
-void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
+bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 {
 	refreshCachedSettings();
 	U32 samples = RenderFSAASamples;
 	// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
 	// Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state
 
+	bool ret = true;
+
 	if (!allocateScreenBuffer(resX, resY, samples))
 	{
+		//failed to allocate at requested specification, return false
+		ret = false;
+
 		releaseScreenBuffers();
 		//reduce number of samples 
 		while (samples > 0)
 			samples /= 2;
 			if (allocateScreenBuffer(resX, resY, samples))
 			{ //success
-				return;
+				return ret;
 			}
 			releaseScreenBuffers();
 		}
 			resY /= 2;
 			if (allocateScreenBuffer(resX, resY, samples))
 			{
-				return;
+				return ret;
 			}
 			releaseScreenBuffers();
 
 			resX /= 2;
 			if (allocateScreenBuffer(resX, resY, samples))
 			{
-				return;
+				return ret;
 			}
 			releaseScreenBuffers();
 		}
 
 		llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;
 	}
+
+	return ret;
 }
 
 
 		if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (samples > 0)
 		{
-			if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
+			if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
 		}
 		else
 		{
 			}
 		}
 
-		U32 width = nhpo2(U32(resX*scale))/2;
+		U32 width = resX*scale;
 		U32 height = width;
 
 		if (shadow_detail > 1)
 
 	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;
 		gGL.popMatrix();
 		stop_glerror();
 
-		//copy depth and stencil from deferred screen
-		//mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-		//					0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
 		mScreen.bindTarget();
 		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
 		glClearColor(0,0,0,0);
 		}
 		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
 
-		LLRenderTarget::unbindTarget();
-
 		LLPipeline::sReflectionRender = FALSE;
 
 		if (!LLRenderTarget::sUseFBO)

File indra/newview/pipeline.h

 	void createGLBuffers();
 	void createLUTBuffers();
 
-	void allocateScreenBuffer(U32 resX, U32 resY);
+	//allocate the largest screen buffer possible up to resX, resY
+	//returns true if full size buffer allocated, false if some other size is allocated
+	bool allocateScreenBuffer(U32 resX, U32 resY);
+
+	//attempt to allocate screen buffers at resX, resY
+	//returns true if allocation successful, false otherwise
 	bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples);
+
 	void allocatePhysicsBuffer();
 	
 	void resetVertexBuffers(LLDrawable* drawable);