Bug 701269 - Deguarantee that ResizeOffscreenFBO clears its buffers - r=bjacob
authorJeff Gilbert <jgilbert@mozilla.com>
Mon, 19 Dec 2011 15:47:54 -0800
changeset 84718 91141088eb7dd73c75961cc9947594e5387a29f1
parent 84717 d9ec0c88fb8686d6c007ac4ab24439a013da44d9
child 84719 63d94ab75606268c75bbbf63bdf193215cb8478e
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs701269
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 701269 - Deguarantee that ResizeOffscreenFBO clears its buffers - r=bjacob
content/canvas/src/WebGLContext.cpp
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -466,23 +466,28 @@ WebGLContext::SetDimensions(PRInt32 widt
     // Zero-sized surfaces can cause problems.
     if (width == 0 || height == 0) {
         width = 1;
         height = 1;
     }
 
     // If we already have a gl context, then we just need to resize it
     if (gl) {
+        MakeContextCurrent();
+
         gl->ResizeOffscreen(gfxIntSize(width, height)); // Doesn't matter if it succeeds (soft-fail)
         // It's unlikely that we'll get a proper-sized context if we recreate if we didn't on resize
 
         // everything's good, we're done here
         mWidth = gl->OffscreenActualSize().width;
         mHeight = gl->OffscreenActualSize().height;
         mResetLayer = true;
+
+        gl->ClearSafely();
+
         return NS_OK;
     }
 
     /*** end of early success return cases ***/
 
     ScopedGfxFeatureReporter reporter("WebGL");
 
     // At this point we know that the old context is not going to survive, even though we still don't
@@ -664,21 +669,23 @@ WebGLContext::SetDimensions(PRInt32 widt
     }
 #endif
 
     MakeContextCurrent();
 
     // Make sure that we clear this out, otherwise
     // we'll end up displaying random memory
     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, gl->GetOffscreenFBO());
+
     gl->fViewport(0, 0, mWidth, mHeight);
     gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     gl->fClearDepth(1.0f);
     gl->fClearStencil(0);
-    gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
+
+    gl->ClearSafely();
 
     reporter.SetSuccessful();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f)
 {
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -1081,18 +1081,20 @@ GLContext::ResizeOffscreenFBO(const gfxI
     GLint maxSamples = 0;
     if (SupportsFramebufferMultisample() && !aDisableAA)
         fGetIntegerv(LOCAL_GL_MAX_SAMPLES, &maxSamples);
 
     samples = NS_MIN(samples, maxSamples);
 
     const bool useDrawMSFBO = (samples > 0);
 
-    if (!useDrawMSFBO && !aUseReadFBO)
+    if (!useDrawMSFBO && !aUseReadFBO) {
+        // Early out, as no FBO resize work is necessary.
         return true;
+    }
 
     const bool firstTime = (mOffscreenDrawFBO == 0 && mOffscreenReadFBO == 0);
 
     GLuint curBoundFramebufferDraw = 0;
     GLuint curBoundFramebufferRead = 0;
     GLuint curBoundRenderbuffer = 0;
     GLuint curBoundTexture = 0;
 
@@ -1396,38 +1398,31 @@ GLContext::ResizeOffscreenFBO(const gfxI
         printf_stderr("%s %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n",
                       firstTime ? "Created" : "Resized",
                       mOffscreenActualSize.width, mOffscreenActualSize.height,
                       mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
                       mActualFormat.depth, mActualFormat.stencil, mActualFormat.samples);
     }
 #endif
 
-    // We're good, and the framebuffer is already attached, so let's
-    // clear out our new framebuffer; otherwise we'll end up displaying
-    // random memory.  We saved all of these things earlier so that we
-    // can restore them.
-    fViewport(0, 0, aSize.width, aSize.height);
-
     // Make sure we know that the buffers are new and thus dirty:
     ForceDirtyFBOs();
 
-    // Clear the new framebuffer with the full viewport
-    fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, GetOffscreenFBO());
-    ClearSafely();
-
-    // Ok, now restore the GL state back to what it was before the resize took place.
+    // We're good, and the framebuffer is already attached.
+    // Now restore the GL state back to what it was before the resize took place.
     BindDrawFBO(curBoundFramebufferDraw);
     BindReadFBO(curBoundFramebufferRead);
     fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
     fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
 
     // -don't- restore the viewport the first time through this, since
     // the previous one isn't valid.
-    if (!firstTime)
+    if (firstTime)
+        fViewport(0, 0, aSize.width, aSize.height); // XXX This is coming out in 711642
+    else
         fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
 
     return true;
 }
 
 void
 GLContext::DeleteOffscreenFBO()
 {
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -737,26 +737,26 @@ public:
         return aOffscreen->mOffscreenTexture == 0;
     }
 
     virtual bool BindTex2DOffscreen(GLContext *aOffscreen) {
         if (aOffscreen->GetContextType() != GetContextType()) {
           return false;
         }
 
-        if (!aOffscreen->mOffscreenDrawFBO && !aOffscreen->mOffscreenReadFBO) {
-            return false;
-        }
-
         if (!aOffscreen->mSharedContext ||
             aOffscreen->mSharedContext != mSharedContext)
         {
             return false;
         }
 
+        if (!aOffscreen->mOffscreenTexture) {
+            return false;
+        }
+
         fBindTexture(LOCAL_GL_TEXTURE_2D, aOffscreen->mOffscreenTexture);
 
         return true;
     }
 
     virtual void UnbindTex2DOffscreen(GLContext *aOffscreen) { }
 
     bool IsOffscreen() {
@@ -765,17 +765,18 @@ public:
 
 protected:
     bool mFlushGuaranteesResolve;
 
 public:
     void SetFlushGuaranteesResolve(bool aFlushGuaranteesResolve) {
         mFlushGuaranteesResolve = aFlushGuaranteesResolve;
     }
-
+    
+    // Before reads from offscreen texture
     void GuaranteeResolve() {
         if (mFlushGuaranteesResolve) {
             BlitDirtyFBOs();
             fFlush();
         } else {
             fFinish();
         }
     }
@@ -1048,17 +1049,16 @@ public:
 
         BeforeGLReadCall();
         // no-op; we just want to make sure the Read FBO is updated if it needs to be
         AfterGLReadCall();
 
         BindReadFBO(read);
     }
 
-    // Before reads from offscreen texture
     void fFinish() {
         BeforeGLReadCall();
         raw_fFinish();
         AfterGLReadCall();
     }
 
     // Draw/Read
     void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
@@ -1418,18 +1418,19 @@ protected:
     GLuint mOffscreenTexture;
     bool mFlipped;
 
     // lazy-initialized things
     GLuint mBlitProgram, mBlitFramebuffer;
     void UseBlitProgram();
     void SetBlitFramebufferForDestTexture(GLuint aTexture);
 
-    // helper to create/resize an offscreen FBO,
+    // Helper to create/resize an offscreen FBO,
     // for offscreen implementations that use FBOs.
+    // Note that it does -not- clear the resized buffers.
     bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA);
     bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO) {
         if (ResizeOffscreenFBO(aSize, aUseReadFBO, false))
             return true;
 
         if (!mCreationFormat.samples)
             return false;
 
@@ -1446,18 +1447,21 @@ protected:
     GLuint mOffscreenDepthRB;
     GLuint mOffscreenStencilRB;
 
     ExtensionBitset<Extensions_Max> mAvailableExtensions;
 
     // Clear to transparent black, with 0 depth and stencil,
     // while preserving current ClearColor etc. values.
     // Useful for resizing offscreen buffers.
+public:
     void ClearSafely();
 
+protected:
+
     nsDataHashtable<nsVoidPtrHashKey, void*> mUserData;
 
     void SetIsGLES2(bool aIsGLES2) {
         NS_ASSERTION(!mInitialized, "SetIsGLES2 can only be called before initialization!");
         mIsGLES2 = aIsGLES2;
     }
 
     bool InitWithPrefix(const char *prefix, bool trygl);