Adds support for multisampled GLContexts, esp. EGL, WGL paths
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 19 Oct 2011 15:09:57 -0400
changeset 79599 01ec87781de74a8fe199ada2b90ac34a760ceee8
parent 79598 18244ca9345757ce10854cd92623d9b86bea8bb4
child 79600 e393f548f8cbf2a9c0c21886a2294774230382a1
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone10.0a1
Adds support for multisampled GLContexts, esp. EGL, WGL paths
gfx/layers/basic/BasicLayers.cpp
gfx/thebes/GLContext.cpp
gfx/thebes/GLContext.h
gfx/thebes/GLContextProviderCGL.mm
gfx/thebes/GLContextProviderEGL.cpp
gfx/thebes/GLContextProviderWGL.cpp
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -1106,17 +1106,17 @@ BasicCanvasLayer::UpdateSurface(gfxASurf
                    "Destination surface must be ImageSurface type");
       return;
     }
 
     // We need to read from the GLContext
     mGLContext->MakeCurrent();
 
 #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
-    mGLContext->fFinish();
+    mGLContext->Finish();
     gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface();
 
     // XRender can only blend premuliplied alpha, so only allow xrender
     // path if we have premultiplied alpha or opaque content.
     if (offscreenSurface && (mGLBufferIsPremultiplied || (GetContentFlags() & CONTENT_OPAQUE))) {  
         mSurface = offscreenSurface;
         mNeedsYFlip = false;
     }
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -464,16 +464,17 @@ static const char *sExtensionNames[] = {
     "GL_OES_texture_float",
     "GL_ARB_texture_float",
     "GL_EXT_unpack_subimage",
     "GL_OES_standard_derivatives",
     "GL_EXT_framebuffer_blit",
     "GL_ANGLE_framebuffer_blit",
     "GL_EXT_framebuffer_multisample",
     "GL_ANGLE_framebuffer_multisample",
+    "GL_OES_rgb8_rgba8",
     NULL
 };
 
 void
 GLContext::InitExtensions()
 {
     MakeCurrent();
     const GLubyte *extensions = fGetString(LOCAL_GL_EXTENSIONS);
@@ -1012,26 +1013,35 @@ void TiledTextureImage::Resize(const nsI
 }
 
 PRUint32 TiledTextureImage::GetTileCount()
 {
     return mImages.Length();
 }
 
 bool
-GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
+GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO)
 {
     if (!IsOffscreenSizeAllowed(aSize))
         return false;
 
     MakeCurrent();
 
     const bool alpha = mCreationFormat.alpha > 0;
     const int depth = mCreationFormat.depth;
     const int stencil = mCreationFormat.stencil;
+    int samples = mCreationFormat.samples;
+
+    const bool useDrawMSFBO = (samples > 0) && SupportsFramebufferMultisample();
+
+    if (!useDrawMSFBO && !aUseReadFBO)
+        return true;
+
+    if (!useDrawMSFBO)
+        samples = 0;
 
     const bool firstTime = (mOffscreenDrawFBO == 0 && mOffscreenReadFBO == 0);
 
     GLuint curBoundFramebufferDraw = 0;
     GLuint curBoundFramebufferRead = 0;
     GLuint curBoundRenderbuffer = 0;
     GLuint curBoundTexture = 0;
 
@@ -1044,89 +1054,124 @@ GLContext::ResizeOffscreenFBO(const gfxI
     curBoundFramebufferDraw = GetBoundDrawFBO();
     curBoundFramebufferRead = GetBoundReadFBO();
     fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*) &curBoundRenderbuffer);
     fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
     fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
 
     // the context format of what we're defining
     // This becomes mActualFormat on success
-    ContextFormat cf;
+    ContextFormat cf(mCreationFormat);
 
     // Create everything we need for the resize, so if it fails, we haven't broken anything
     // If successful, these new resized objects will replace their associated member vars in GLContext
     GLuint newOffscreenDrawFBO = 0;
     GLuint newOffscreenReadFBO = 0;
     GLuint newOffscreenTexture = 0;
+    GLuint newOffscreenColorRB = 0;
     GLuint newOffscreenDepthRB = 0;
     GLuint newOffscreenStencilRB = 0;
 
-    fGenFramebuffers(1, &newOffscreenReadFBO);
-    newOffscreenDrawFBO = newOffscreenReadFBO;
-    fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO);
+    // Create the buffers and texture
+    if (aUseReadFBO) {
+        fGenFramebuffers(1, &newOffscreenReadFBO);
+        fGenTextures(1, &newOffscreenTexture);
+    }
 
-    fGenTextures(1, &newOffscreenTexture);
-    fBindTexture(LOCAL_GL_TEXTURE_2D, newOffscreenTexture);
-    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
-    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+    if (useDrawMSFBO) {
+        fGenFramebuffers(1, &newOffscreenDrawFBO);
+        fGenRenderbuffers(1, &newOffscreenColorRB);
+    } else {
+        newOffscreenDrawFBO = newOffscreenReadFBO;
+    }
 
     if (depth && stencil && useDepthStencil) {
         fGenRenderbuffers(1, &newOffscreenDepthRB);
     } else {
         if (depth) {
             fGenRenderbuffers(1, &newOffscreenDepthRB);
         }
 
         if (stencil) {
             fGenRenderbuffers(1, &newOffscreenStencilRB);
         }
     }
 
-    // resize the FBO components
-    if (alpha) {
-        fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                    0,
-                    LOCAL_GL_RGBA,
-                    aSize.width, aSize.height,
-                    0,
-                    LOCAL_GL_RGBA,
-                    LOCAL_GL_UNSIGNED_BYTE,
-                    NULL);
+   // Allocate texture
+    if (aUseReadFBO) {
+        fBindTexture(LOCAL_GL_TEXTURE_2D, newOffscreenTexture);
+        fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+        fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+
+        if (alpha) {
+            fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                        0,
+                        LOCAL_GL_RGBA,
+                        aSize.width, aSize.height,
+                        0,
+                        LOCAL_GL_RGBA,
+                        LOCAL_GL_UNSIGNED_BYTE,
+                        NULL);
 
-        cf.red = cf.green = cf.blue = cf.alpha = 8;
-    } else {
-        fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                    0,
-                    LOCAL_GL_RGB,
-                    aSize.width, aSize.height,
-                    0,
-                    LOCAL_GL_RGB,
+            cf.red = cf.green = cf.blue = cf.alpha = 8;
+        } else {
+            fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                        0,
+                        LOCAL_GL_RGB,
+                        aSize.width, aSize.height,
+                        0,
+                        LOCAL_GL_RGB,
 #ifdef XP_WIN
-                    LOCAL_GL_UNSIGNED_BYTE,
+                        LOCAL_GL_UNSIGNED_BYTE,
 #else
-                    mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
-                             : LOCAL_GL_UNSIGNED_BYTE,
+                        mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
+                                 : LOCAL_GL_UNSIGNED_BYTE,
 #endif
-                    NULL);
+                        NULL);
 
 #ifdef XP_WIN
-        cf.red = cf.green = cf.blue = 8;
+            cf.red = cf.green = cf.blue = 8;
 #else
-        cf.red = 5;
-        cf.green = 6;
-        cf.blue = 5;
+            cf.red = 5;
+            cf.green = 6;
+            cf.blue = 5;
 #endif
-        cf.alpha = 0;
+            cf.alpha = 0;
+        }
+    }
+    cf.samples = samples;
+
+    // Allocate color buffer
+    if (useDrawMSFBO) {
+        GLenum colorFormat;
+        if (!mIsGLES2 || IsExtensionSupported(OES_rgb8_rgba8))
+            colorFormat = alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
+        else
+            colorFormat = alpha ? LOCAL_GL_RGBA4 : LOCAL_GL_RGB565;
+
+        fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenColorRB);
+        fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
+                                        samples,
+                                        colorFormat,
+                                        aSize.width, aSize.height);
     }
 
+    // Allocate depth and stencil buffers
     if (depth && stencil && useDepthStencil) {
         fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB);
-        fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
-                             LOCAL_GL_DEPTH24_STENCIL8,
-                             aSize.width, aSize.height);
+        if (useDrawMSFBO) {
+            fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
+                                            samples,
+                                            LOCAL_GL_DEPTH24_STENCIL8,
+                                            aSize.width, aSize.height);
+        } else {
+            fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
+                                 LOCAL_GL_DEPTH24_STENCIL8,
+                                 aSize.width, aSize.height);
+        }
         cf.depth = 24;
         cf.stencil = 8;
     } else {
         if (depth) {
             GLenum depthType;
             if (mIsGLES2) {
                 if (IsExtensionSupported(OES_depth32)) {
                     depthType = LOCAL_GL_DEPTH_COMPONENT32;
@@ -1139,35 +1184,52 @@ GLContext::ResizeOffscreenFBO(const gfxI
                    cf.depth = 16;
                 }
             } else {
                 depthType = LOCAL_GL_DEPTH_COMPONENT24;
                 cf.depth = 24;
             }
 
             fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB);
-            fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, depthType,
-                                 aSize.width, aSize.height);
+            if (useDrawMSFBO) {
+                fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
+                                                samples,
+                                                depthType,
+                                                aSize.width, aSize.height);
+            } else {
+                fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
+                                     depthType,
+                                     aSize.width, aSize.height);
+            }
         }
 
         if (stencil) {
             fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenStencilRB);
-            fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
-                                 LOCAL_GL_STENCIL_INDEX8,
-                                 aSize.width, aSize.height);
+            if (useDrawMSFBO) {
+                fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
+                                                samples,
+                                                LOCAL_GL_STENCIL_INDEX8,
+                                                aSize.width, aSize.height);
+            } else {
+                fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
+                                     LOCAL_GL_STENCIL_INDEX8,
+                                     aSize.width, aSize.height);
+            }
             cf.stencil = 8;
         }
     }
 
     // Now assemble the FBO
-    fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
-                          LOCAL_GL_COLOR_ATTACHMENT0,
-                          LOCAL_GL_TEXTURE_2D,
-                          newOffscreenTexture,
-                          0);
+    fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO);    // If we're not using a separate draw FBO, this will be the read FBO
+    if (useDrawMSFBO) {
+        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                 LOCAL_GL_COLOR_ATTACHMENT0,
+                                 LOCAL_GL_RENDERBUFFER,
+                                 newOffscreenColorRB);
+    }
 
     if (depth && stencil && useDepthStencil) {
         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
                                  LOCAL_GL_DEPTH_ATTACHMENT,
                                  LOCAL_GL_RENDERBUFFER,
                                  newOffscreenDepthRB);
         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
                                  LOCAL_GL_STENCIL_ATTACHMENT,
@@ -1184,16 +1246,25 @@ GLContext::ResizeOffscreenFBO(const gfxI
         if (stencil) {
             fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
                                      LOCAL_GL_STENCIL_ATTACHMENT,
                                      LOCAL_GL_RENDERBUFFER,
                                      newOffscreenStencilRB);
         }
     }
 
+    if (aUseReadFBO) {
+        fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO);
+        fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
+                              LOCAL_GL_COLOR_ATTACHMENT0,
+                              LOCAL_GL_TEXTURE_2D,
+                              newOffscreenTexture,
+                              0);
+    }
+
     // We should be all resized.  Check for framebuffer completeness.
     GLenum status;
     bool framebuffersComplete = true;
 
     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO);
     status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
         NS_WARNING("DrawFBO: Incomplete");
@@ -1215,67 +1286,72 @@ GLContext::ResizeOffscreenFBO(const gfxI
 
     if (!framebuffersComplete) {
         NS_WARNING("Error resizing offscreen framebuffer -- framebuffer(s) not complete");
 
         // Clean up the mess
         fDeleteFramebuffers(1, &newOffscreenDrawFBO);
         fDeleteFramebuffers(1, &newOffscreenReadFBO);
         fDeleteTextures(1, &newOffscreenTexture);
+        fDeleteRenderbuffers(1, &newOffscreenColorRB);
         fDeleteRenderbuffers(1, &newOffscreenDepthRB);
         fDeleteRenderbuffers(1, &newOffscreenStencilRB);
 
         BindReadFBO(curBoundFramebufferRead);
         BindDrawFBO(curBoundFramebufferDraw);
         fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
         fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
         fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
 
         return false;
     }
 
     // Success, so delete the old and busted
     fDeleteFramebuffers(1, &mOffscreenDrawFBO);
     fDeleteFramebuffers(1, &mOffscreenReadFBO);
     fDeleteTextures(1, &mOffscreenTexture);
+    fDeleteRenderbuffers(1, &mOffscreenColorRB);
     fDeleteRenderbuffers(1, &mOffscreenDepthRB);
     fDeleteRenderbuffers(1, &mOffscreenStencilRB);
 
     // Update currently bound references if we're changing what they were point to
     // This way we don't rebind to old buffers when we're done here
     if (curBoundFramebufferDraw == mOffscreenDrawFBO)
         curBoundFramebufferDraw = newOffscreenDrawFBO;
     if (curBoundFramebufferRead == mOffscreenReadFBO)
         curBoundFramebufferRead = newOffscreenReadFBO;
     if (curBoundTexture == mOffscreenTexture)
         curBoundTexture = newOffscreenTexture;
-    if (curBoundRenderbuffer == mOffscreenDepthRB)
+    if (curBoundRenderbuffer == mOffscreenColorRB)
+        curBoundRenderbuffer = newOffscreenColorRB;
+    else if (curBoundRenderbuffer == mOffscreenDepthRB)
         curBoundRenderbuffer = newOffscreenDepthRB;
     else if (curBoundRenderbuffer == mOffscreenStencilRB)
         curBoundRenderbuffer = newOffscreenStencilRB;
 
     // Replace with the new hotness
     mOffscreenDrawFBO = newOffscreenDrawFBO;
     mOffscreenReadFBO = newOffscreenReadFBO;
     mOffscreenTexture = newOffscreenTexture;
+    mOffscreenColorRB = newOffscreenColorRB;
     mOffscreenDepthRB = newOffscreenDepthRB;
     mOffscreenStencilRB = newOffscreenStencilRB;
 
     mOffscreenSize = aSize;
     mOffscreenActualSize = aSize;
 
     mActualFormat = cf;
 
 #ifdef DEBUG
     if (mDebugMode) {
-        printf_stderr("%s %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d\n",
+        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.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);
@@ -1302,22 +1378,24 @@ GLContext::ResizeOffscreenFBO(const gfxI
 }
 
 void
 GLContext::DeleteOffscreenFBO()
 {
     fDeleteFramebuffers(1, &mOffscreenDrawFBO);
     fDeleteFramebuffers(1, &mOffscreenReadFBO);
     fDeleteTextures(1, &mOffscreenTexture);
+    fDeleteRenderbuffers(1, &mOffscreenColorRB);
     fDeleteRenderbuffers(1, &mOffscreenDepthRB);
     fDeleteRenderbuffers(1, &mOffscreenStencilRB);
 
     mOffscreenDrawFBO = 0;
     mOffscreenReadFBO = 0;
     mOffscreenTexture = 0;
+    mOffscreenColorRB = 0;
     mOffscreenDepthRB = 0;
     mOffscreenStencilRB = 0;
 }
 
 void
 GLContext::ClearSafely()
 {
     // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -546,16 +546,17 @@ public:
         mSharedContext(aSharedContext),
         mOffscreenTexture(0),
         mFlipped(false),
         mBlitProgram(0),
         mBlitFramebuffer(0),
         mOffscreenDrawFBO(0),
         mOffscreenReadFBO(0),
         mOffscreenFBOsDirty(false),
+        mOffscreenColorRB(0),
         mOffscreenDepthRB(0),
         mOffscreenStencilRB(0)
 #ifdef DEBUG
         , mGLError(LOCAL_GL_NO_ERROR)
 #endif
     {
         mUserData.Init();
     }
@@ -748,17 +749,17 @@ public:
      * If it returns false, the context should be treated as unusable
      * and should be recreated.  After the resize, the viewport is not
      * changed; glViewport should be called as appropriate.
      *
      * Only valid if IsOffscreen() returns true.
      */
     virtual bool ResizeOffscreen(const gfxIntSize& aNewSize) {
         if (mOffscreenDrawFBO || mOffscreenReadFBO)
-            return ResizeOffscreenFBO(aNewSize);
+            return ResizeOffscreenFBO(aNewSize, mOffscreenReadFBO != 0);
         return false;
     }
 
     /*
      * Return size of this offscreen context.
      *
      * Only valid if IsOffscreen() returns true.
      */
@@ -1235,16 +1236,17 @@ public:
         OES_texture_float,
         ARB_texture_float,
         EXT_unpack_subimage,
         OES_standard_derivatives,
         EXT_framebuffer_blit,
         ANGLE_framebuffer_blit,
         EXT_framebuffer_multisample,
         ANGLE_framebuffer_multisample,
+        OES_rgb8_rgba8,
         Extensions_Max
     };
 
     bool IsExtensionSupported(GLExtensions aKnownExtension) {
         return mAvailableExtensions[aKnownExtension];
     }
 
     // for unknown extensions
@@ -1314,20 +1316,21 @@ protected:
 
     // lazy-initialized things
     GLuint mBlitProgram, mBlitFramebuffer;
     void UseBlitProgram();
     void SetBlitFramebufferForDestTexture(GLuint aTexture);
 
     // helper to create/resize an offscreen FBO,
     // for offscreen implementations that use FBOs.
-    bool ResizeOffscreenFBO(const gfxIntSize& aSize);
+    bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO);
     void DeleteOffscreenFBO();
     GLuint mOffscreenDrawFBO;
     GLuint mOffscreenReadFBO;
+    GLuint mOffscreenColorRB;
     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.
--- a/gfx/thebes/GLContextProviderCGL.mm
+++ b/gfx/thebes/GLContextProviderCGL.mm
@@ -562,26 +562,28 @@ GLContextProviderCGL::CreateOffscreen(co
                                       const ContextFormat& aFormat)
 {
     nsRefPtr<GLContextCGL> glContext;
     
     NS_ENSURE_TRUE(Preferences::GetRootBranch(), nsnull);
     const bool preferFBOs = Preferences::GetBool("cgl.prefer-fbo", false);
     if (!preferFBOs)
     {
-	    glContext = CreateOffscreenPBufferContext(aSize, aFormat);
-	    if (glContext &&
-	        glContext->Init())
-	    {
-	        glContext->mOffscreenSize = aSize;
-	        glContext->mOffscreenActualSize = aSize;
+        glContext = CreateOffscreenPBufferContext(aSize, aFormat);
+        if (glContext &&
+            glContext->Init())
+        {
+            glContext->mOffscreenSize = aSize;
+            glContext->mOffscreenActualSize = aSize;
 
-	        return glContext.forget();
-	    }
-	}
+            printf("GL Offscreen: CGL+PBuffer\n");
+
+            return glContext.forget();
+        }
+    }
 
     // try a FBO as second choice
     glContext = CreateOffscreenFBOContext(aSize, aFormat);
     if (glContext &&
         glContext->Init() &&
         glContext->ResizeOffscreenFBO(aSize))
     {
         return glContext.forget();
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1065,19 +1065,22 @@ GLContextEGL::ResizeOffscreen(const gfxI
                                                  mPBufferCanBindToTexture
                                                  ? (mCreationFormat.minAlpha
                                                     ? LOCAL_EGL_TEXTURE_RGBA
                                                     : LOCAL_EGL_TEXTURE_RGB)
                                                  : LOCAL_EGL_NONE,
                                                  pbsize);
         if (!surface) {
             NS_WARNING("Failed to resize pbuffer");
-            return nsnull;
+            return false;
         }
 
+        if (!ResizeOffscreenFBO(aNewSize, false))
+            return false;
+
         SetOffscreenSize(aNewSize, pbsize);
 
         if (mSurface && !mPlatformContext) {
             sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
         }
 
         mSurface = surface;
 
@@ -1112,27 +1115,30 @@ GLContextEGL::ResizeOffscreen(const gfxI
 
         EGLSurface surface;
         EGLConfig config = 0;
         int depth = gfxUtils::ImageFormatToDepth(gfxPlatform::GetPlatform()->GetOffscreenFormat());
         surface = CreateEGLSurfaceForXSurface(xsurface, &config, depth);
         if (!config) {
             return false;
         }
+        if (!ResizeOffscreenFBO(aNewSize, false))
+            return false;
+
         mThebesSurface = xsurface;
 
         return true;
     }
 #endif
 
 #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
     return ResizeOffscreenPixmapSurface(aNewSize);
 #endif
 
-    return ResizeOffscreenFBO(aNewSize);
+    return ResizeOffscreenFBO(aNewSize, true);
 }
 
 
 static GLContextEGL *
 GetGlobalContextEGL()
 {
     return static_cast<GLContextEGL*>(GLContextProviderEGL::GetGlobalContext());
 }
@@ -1997,23 +2003,25 @@ GLContextEGL::CreateEGLPBufferOffscreenC
     // if we're running under ANGLE, we can't set BIND_TO_TEXTURE --
     // it's not supported, and we have dx interop pbuffers anyway
     if (sEGLLibrary.IsANGLE())
         configCanBindToTexture = false;
 
     nsTArray<EGLint> attribs(32);
     int attribAttempt = 0;
 
+    int tryDepthSize = (aFormat.depth > 0) ? 24 : 0;
+
 TRY_ATTRIBS_AGAIN:
     switch (attribAttempt) {
     case 0:
-        FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, 8, 24);
+        FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, 8, tryDepthSize);
         break;
     case 1:
-        FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, -1, 24);
+        FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, -1, tryDepthSize);
         break;
     case 2:
         FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, -1, -1);
         break;
     }
 
     if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
                                    &attribs[0],
@@ -2237,35 +2245,56 @@ already_AddRefed<GLContext>
 GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
                                       const ContextFormat& aFormat)
 {
     if (!sEGLLibrary.EnsureInitialized()) {
         return nsnull;
     }
     
     ContextFormat actualFormat(aFormat);
-    actualFormat.samples = 0;
+    // actualFormat.samples = 0;
 
 #if defined(ANDROID) || defined(XP_WIN)
-    return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, actualFormat);
+    nsRefPtr<GLContextEGL> glContext =
+        GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, actualFormat);
+
+    if (!glContext)
+        return nsnull;
+
+    if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), false))
+        return nsnull;
+ 
+     printf("GL Offscreen: EGL+PBuffer\n");
+     return glContext.forget();
+
 #elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
-    return GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, actualFormat);
+    nsRefPtr<GLContextEGL> glContext =
+        GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, actualFormat);
+
+    if (!glContext)
+        return nsnull;
+
+    if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true))
+        return nsnull;
+    
+    printf("GL Offscreen: EGL+Pixmap\n");
+    return glContext.forget();
 #elif defined(MOZ_X11)
     nsRefPtr<GLContextEGL> glContext =
         GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, actualFormat, true);
 
     if (!glContext) {
         return nsnull;
     }
     if (!glContext->GetSharedContext()) {
         // no point in returning anything if sharing failed, we can't
         // render from this
         return nsnull;
     }
-    if (!gUseBackingSurface && !glContext->ResizeOffscreenFBO(aSize)) {
+    if (!gUseBackingSurface && !glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true)) {
         // we weren't able to create the initial
         // offscreen FBO, so this is dead
         return nsnull;
     }
     return glContext.forget();
 #else
     return nsnull;
 #endif
--- a/gfx/thebes/GLContextProviderWGL.cpp
+++ b/gfx/thebes/GLContextProviderWGL.cpp
@@ -464,20 +464,20 @@ GLContextWGL::ResizeOffscreen(const gfxI
         mDC = sWGLLibrary.fGetPbufferDC(mPBuffer);
 
         mOffscreenSize = aNewSize;
         mOffscreenActualSize = aNewSize;
 
         MakeCurrent();
         ClearSafely();
 
-        return true;
+        return ResizeOffscreenFBO(aNewSize, false);
     }
 
-    return ResizeOffscreenFBO(aNewSize);
+    return ResizeOffscreenFBO(aNewSize, true);
 }
 
 static GLContextWGL *
 GetGlobalContextWGL()
 {
     return static_cast<GLContextWGL*>(GLContextProviderWGL::GetGlobalContext());
 }
 
@@ -646,17 +646,17 @@ already_AddRefed<GLContext>
 GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize,
                                       const ContextFormat& aFormat)
 {
     if (!sWGLLibrary.EnsureInitialized()) {
         return nsnull;
     }
 
     ContextFormat actualFormat(aFormat);
-    actualFormat.samples = 0;
+    // actualFormat.samples = 0;
 
     nsRefPtr<GLContextWGL> glContext;
 
     // Always try to create a pbuffer context first, because we
     // want the context isolation.
     NS_ENSURE_TRUE(Preferences::GetRootBranch(), nsnull);
     const bool preferFBOs = Preferences::GetBool("wgl.prefer-fbo", false);
     if (!preferFBOs &&
@@ -672,25 +672,22 @@ GLContextProviderWGL::CreateOffscreen(co
     }
 
     if (!glContext ||
         !glContext->Init())
     {
         return nsnull;
     }
 
+    if (!glContext->ResizeOffscreenFBO(aSize, !glContext->mPBuffer))
+        return nsnull;
+
     glContext->mOffscreenSize = aSize;
     glContext->mOffscreenActualSize = aSize;
 
-    if (!glContext->mPBuffer &&
-        !glContext->ResizeOffscreenFBO(aSize))
-    {
-        return nsnull;
-    }
-
     return glContext.forget();
 }
 
 already_AddRefed<GLContext>
 GLContextProviderWGL::CreateForNativePixmapSurface(gfxASurface *aSurface)
 {
     return nsnull;
 }