Bug 726396 - Repair ANGLE d3d share handle fetching an PBuffer creation behavior - r=bjacob
authorJeff Gilbert <jgilbert@mozilla.com>
Mon, 12 Mar 2012 15:10:38 -0700
changeset 88832 6610af68b24c8b525cf2562902cb1b7c15e391fd
parent 88831 2bc1574aa91ed48ba780b72e4f74b91322f3f25b
child 88833 c3a8909af7073595cb3e75778bbe465b023d9487
push id7040
push userjgilbert@mozilla.com
push dateMon, 12 Mar 2012 22:11:39 +0000
treeherdermozilla-inbound@6610af68b24c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs726396
milestone13.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 726396 - Repair ANGLE d3d share handle fetching an PBuffer creation behavior - r=bjacob
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderCGL.mm
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/gl/GLContextProviderWGL.cpp
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -18,16 +18,17 @@
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Vladimir Vukicevic <vladimir@pobox.com>
  *   Mark Steele <mwsteele@gmail.com>
  *   Bas Schouten <bschouten@mozilla.com>
+ *   Jeff Gilbert <jgilbert@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -551,16 +552,17 @@ GLContext::InitWithPrefix(const char *pr
         sDebugMode |= DebugAbortOnError;
 #endif
 
     if (mInitialized)
         reporter.SetSuccessful();
     else {
         // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
         mSymbols.Zero();
+        NS_WARNING("InitWithPrefix failed!");
     }
 
     return mInitialized;
 }
 
 void
 GLContext::InitExtensions()
 {
@@ -1162,18 +1164,18 @@ GLContext::ResizeOffscreenFBO(const gfxI
     GLuint curBoundTexture = 0;
 
     GLint viewport[4];
 
     const bool useDepthStencil =
             !mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
 
     // save a few things for later restoring
-    curBoundFramebufferDraw = GetBoundDrawFBO();
-    curBoundFramebufferRead = GetBoundReadFBO();
+    curBoundFramebufferDraw = GetUserBoundDrawFBO();
+    curBoundFramebufferRead = GetUserBoundReadFBO();
     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(mCreationFormat);
 
@@ -1331,17 +1333,17 @@ GLContext::ResizeOffscreenFBO(const gfxI
                                      LOCAL_GL_STENCIL_INDEX8,
                                      aSize.width, aSize.height);
             }
             cf.stencil = 8;
         }
     }
 
     // Now assemble the FBO
-    fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO);    // If we're not using a separate draw FBO, this will be the read FBO
+    BindInternalFBO(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) {
@@ -1365,39 +1367,39 @@ GLContext::ResizeOffscreenFBO(const gfxI
             fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
                                      LOCAL_GL_STENCIL_ATTACHMENT,
                                      LOCAL_GL_RENDERBUFFER,
                                      newOffscreenStencilRB);
         }
     }
 
     if (aUseReadFBO) {
-        fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO);
+        BindInternalFBO(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);
+    BindInternalFBO(newOffscreenDrawFBO);
     status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
         NS_WARNING("DrawFBO: Incomplete");
 #ifdef DEBUG
         printf_stderr("Framebuffer status: %X\n", status);
 #endif
         framebuffersComplete = false;
     }
 
-    fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO);
+    BindInternalFBO(newOffscreenReadFBO);
     status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
         NS_WARNING("ReadFBO: Incomplete");
 #ifdef DEBUG
         printf_stderr("Framebuffer status: %X\n", status);
 #endif
         framebuffersComplete = false;
     }
@@ -1408,18 +1410,18 @@ GLContext::ResizeOffscreenFBO(const gfxI
         // 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);
+        BindUserDrawFBO(curBoundFramebufferDraw);
+        BindUserReadFBO(curBoundFramebufferRead);
         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
@@ -1462,29 +1464,29 @@ GLContext::ResizeOffscreenFBO(const gfxI
     if (DebugMode()) {
         printf_stderr("Resized %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n",
                       mOffscreenActualSize.width, mOffscreenActualSize.height,
                       mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
                       mActualFormat.depth, mActualFormat.stencil, mActualFormat.samples);
     }
 #endif
 
-    // Make sure we know that the buffers are new and thus dirty:
-    ForceDirtyFBOs();
-
     // We're good, and the framebuffer is already attached.
     // Now restore the GL state back to what it was before the resize took place.
     // If the user was using fb 0, this will bind the offscreen framebuffer we
     // just created.
-    BindDrawFBO(curBoundFramebufferDraw);
-    BindReadFBO(curBoundFramebufferRead);
+    BindUserDrawFBO(curBoundFramebufferDraw);
+    BindUserReadFBO(curBoundFramebufferRead);
     fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
     fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
     fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
 
+    // Make sure we know that the buffers are new and thus dirty:
+    ForceDirtyFBOs();
+
     return true;
 }
 
 void
 GLContext::DeleteOffscreenFBO()
 {
     fDeleteFramebuffers(1, &mOffscreenDrawFBO);
     fDeleteFramebuffers(1, &mOffscreenReadFBO);
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -18,16 +18,17 @@
  *   Mozilla Corporation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Vladimir Vukicevic <vladimir@pobox.com>
  *   Mark Steele <mwsteele@gmail.com>
  *   Bas Schouten <bschouten@mozilla.com>
+ *   Jeff Gilbert <jgilbert@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -540,16 +541,20 @@ public:
     GLContext(const ContextFormat& aFormat,
               bool aIsOffscreen = false,
               GLContext *aSharedContext = nsnull)
       : mFlushGuaranteesResolve(false),
         mUserBoundDrawFBO(0),
         mUserBoundReadFBO(0),
         mInternalBoundDrawFBO(0),
         mInternalBoundReadFBO(0),
+#ifdef DEBUG
+        mInInternalBindingMode_DrawFBO(true),
+        mInInternalBindingMode_ReadFBO(true),
+#endif
         mOffscreenFBOsDirty(false),
         mInitialized(false),
         mIsOffscreen(aIsOffscreen),
 #ifdef USE_GLES2
         mIsGLES2(true),
 #else
         mIsGLES2(false),
 #endif
@@ -928,92 +933,155 @@ public:
             break;
 
           default:
             raw_fBindFramebuffer(target, framebuffer);
             break;
         }
     }
 
-    GLuint GetBoundDrawFBO() {
+#ifdef DEBUG
+    // See comment near BindInternalDrawFBO()
+    bool mInInternalBindingMode_DrawFBO;
+    bool mInInternalBindingMode_ReadFBO;
+#endif
+
+    GLuint GetUserBoundDrawFBO() {
 #ifdef DEBUG
         GLint ret = 0;
         // Don't need a branch here, because:
         // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6
         // We use raw_ here because this is debug code and we need to see what
         // the driver thinks.
         raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
 
+        bool abort = false;
+
+        if (mInInternalBindingMode_DrawFBO) {
+            NS_ERROR("Draw FBO still bound internally!");
+            printf_stderr("Current internal draw FBO: %d, user: %d)\n", ret, mUserBoundDrawFBO);
+            abort = true;
+        }
+
         if (mInternalBoundDrawFBO != (GLuint)ret) {
-          printf_stderr("!!! Draw FBO mismatch: Was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO);
-          NS_ABORT();
+            NS_ERROR("Draw FBO binding misprediction!");
+            printf_stderr("Bound draw FBO was: %d, Expected: %d\n", ret, mInternalBoundDrawFBO);
+            abort = true;
         }
+
+        if (abort)
+            NS_ABORT();
 #endif
 
         // We only ever expose the user's bound FBOs
         return mUserBoundDrawFBO;
     }
 
-    GLuint GetBoundReadFBO() {
+    GLuint GetUserBoundReadFBO() {
 #ifdef DEBUG
         GLint ret = 0;
         // We use raw_ here because this is debug code and we need to see what
         // the driver thinks.
         if (SupportsOffscreenSplit())
             raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, &ret);
         else
             raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
 
+        bool abort = false;
+
+        if (mInInternalBindingMode_ReadFBO) {
+            NS_ERROR("Read FBO still bound internally!");
+            printf_stderr("Current internal read FBO: %d, user: %d)\n", ret, mUserBoundReadFBO);
+            abort = true;
+        }
+
         if (mInternalBoundReadFBO != (GLuint)ret) {
-          printf_stderr("!!! Read FBO mismatch: Was: %d, Expected: %d\n", ret, mInternalBoundReadFBO);
-          NS_ABORT();
+            NS_ERROR("Read FBO binding misprediction!");
+            printf_stderr("Bound read FBO was: %d, Expected: %d\n", ret, mInternalBoundReadFBO);
+            abort = true;
         }
+
+        if (abort)
+            NS_ABORT();
 #endif
 
         // We only ever expose the user's bound FBOs
         return mUserBoundReadFBO;
     }
 
-    void BindDrawFBO(GLuint name) {
+    void BindUserDrawFBO(GLuint name) {
         if (SupportsOffscreenSplit())
             fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
         else
             fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
+#ifdef DEBUG
+        mInInternalBindingMode_DrawFBO = false;
+#endif
     }
 
-    void BindReadFBO(GLuint name) {
+    void BindUserReadFBO(GLuint name) {
         if (SupportsOffscreenSplit())
             fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
         else
             fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
+#ifdef DEBUG
+        mInInternalBindingMode_ReadFBO = false;
+#endif
     }
 
-    GLuint SwapBoundDrawFBO(GLuint name) {
-        GLuint prev = GetBoundDrawFBO();
-        BindDrawFBO(name);
-        return prev;
+    // BindInternalDraw/ReadFBO() switch us over into 'internal binding mode'
+    //   for the corresponding Draw or Read binding.
+    // To exit internal binding mode, use BindUserDraw/ReadFBO().
+    // While in internal binding mode for Draw/Read, the corresponding
+    //   GetBoundUserDraw/ReadFBO() is undefined, and will trigger ABORT in DEBUG builds.
+    void BindInternalDrawFBO(GLuint name) {
+#ifdef DEBUG
+      mInInternalBindingMode_DrawFBO = true;
+#endif
+        if (SupportsOffscreenSplit())
+            raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name);
+        else
+            raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
+
+        mInternalBoundDrawFBO = name;
     }
 
-    GLuint SwapBoundReadFBO(GLuint name) {
-        GLuint prev = GetBoundReadFBO();
-        BindReadFBO(name);
+    void BindInternalReadFBO(GLuint name) {
+#ifdef DEBUG
+      mInInternalBindingMode_ReadFBO = true;
+#endif
+        if (SupportsOffscreenSplit())
+            raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name);
+        else
+            raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name);
+
+        mInternalBoundReadFBO = name;
+    }
+
+    void BindInternalFBO(GLuint name) {
+        BindInternalDrawFBO(name);
+        BindInternalReadFBO(name);
+    }
+
+    void InitFramebuffers() {
+        MakeCurrent();
+        BindUserDrawFBO(0);
+        BindUserReadFBO(0);
+    }
+
+    GLuint SwapUserDrawFBO(GLuint name) {
+        GLuint prev = GetUserBoundDrawFBO();
+        BindUserDrawFBO(name);
         return prev;
     }
 
-    void BindOffscreenDrawBuffer() {
-        BindDrawFBO(mOffscreenDrawFBO);
-    }
-
-    void BindOffscreenReadBuffer() {
-        BindReadFBO(mOffscreenReadFBO);
-    }
-
-    void BindOffscreenBuffers() {
-        BindOffscreenDrawBuffer();
-        BindOffscreenReadBuffer();
+    GLuint SwapUserReadFBO(GLuint name) {
+        GLuint prev = GetUserBoundReadFBO();
+        BindUserReadFBO(name);
+        return prev;
     }
 
 private:
     bool mOffscreenFBOsDirty;
 
     void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
         switch (precisiontype) {
             case LOCAL_GL_LOW_FLOAT:
@@ -1065,29 +1133,37 @@ private:
         // If we're not dirty, there's no need to blit
         if (!mOffscreenFBOsDirty)
             return;
 
         const bool scissor = fIsEnabled(LOCAL_GL_SCISSOR_TEST);
         if (scissor)
             fDisable(LOCAL_GL_SCISSOR_TEST);
 
-        // flip read/draw for blitting
-        GLuint prevDraw = SwapBoundDrawFBO(mOffscreenReadFBO);
-        GLuint prevRead = SwapBoundReadFBO(mOffscreenDrawFBO);
+        // Store current bindings for restoring later
+        GLuint prevDraw = GetUserBoundDrawFBO();
+        GLuint prevRead = GetUserBoundReadFBO();
+
+        NS_ABORT_IF_FALSE(SupportsOffscreenSplit(), "Doesn't support offscreen split?");
+
+        // Manually setting internal bindings, entering internal mode
+        // Flip read/draw for blitting
+        BindInternalDrawFBO(mOffscreenReadFBO);
+        BindInternalReadFBO(mOffscreenDrawFBO);
 
         GLint width = mOffscreenActualSize.width;
         GLint height = mOffscreenActualSize.height;
         raw_fBlitFramebuffer(0, 0, width, height,
                              0, 0, width, height,
                              LOCAL_GL_COLOR_BUFFER_BIT,
                              LOCAL_GL_NEAREST);
 
-        BindDrawFBO(prevDraw);
-        BindReadFBO(prevRead);
+        // Reset to emulated user binding, exiting internal mode
+        BindUserDrawFBO(prevDraw);
+        BindUserReadFBO(prevRead);
 
         if (scissor)
             fEnable(LOCAL_GL_SCISSOR_TEST);
 
         mOffscreenFBOsDirty = false;
     }
 
     // Do whatever tear-down is necessary after reading from our offscreen FBO,
@@ -1132,33 +1208,33 @@ public:
     void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
         BeforeGLReadCall();
         raw_fCopyTexSubImage2D(target, level, xoffset, yoffset,
                                x, y, width, height);
         AfterGLReadCall();
     }
 
     void ForceDirtyFBOs() {
-        GLuint draw = SwapBoundReadFBO(mOffscreenDrawFBO);
+        GLuint draw = SwapUserDrawFBO(0);
 
         BeforeGLDrawCall();
         // no-op; just pretend we did something
         AfterGLDrawCall();
 
-        BindDrawFBO(draw);
+        BindUserDrawFBO(draw);
     }
 
     void BlitDirtyFBOs() {
-        GLuint read = SwapBoundReadFBO(mOffscreenReadFBO);
+        GLuint read = SwapUserReadFBO(0);
 
         BeforeGLReadCall();
         // no-op; we just want to make sure the Read FBO is updated if it needs to be
         AfterGLReadCall();
 
-        BindReadFBO(read);
+        BindUserReadFBO(read);
     }
 
     void fFinish() {
         BeforeGLReadCall();
         raw_fFinish();
         AfterGLReadCall();
     }
 
@@ -1538,26 +1614,36 @@ protected:
     // 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)
+        if (!mCreationFormat.samples) {
+            NS_WARNING("ResizeOffscreenFBO failed to resize non-AA context!");
             return false;
+        } else {
+            NS_WARNING("ResizeOffscreenFBO failed to resize AA context! Falling back to no AA...");
+        }
 
         if (DebugMode()) {
             printf_stderr("Requested level of multisampling is unavailable, continuing without multisampling\n");
         }
 
-        return ResizeOffscreenFBO(aSize, aUseReadFBO, true);
+        if (ResizeOffscreenFBO(aSize, aUseReadFBO, true))
+            return true;
+
+        NS_WARNING("ResizeOffscreenFBO failed to resize AA context even without AA!");
+        return false;
     }
+
     void DeleteOffscreenFBO();
+
     GLuint mOffscreenDrawFBO;
     GLuint mOffscreenReadFBO;
     GLuint mOffscreenColorRB;
     GLuint mOffscreenDepthRB;
     GLuint mOffscreenStencilRB;
 
     ExtensionBitset<Extensions_Max> mAvailableExtensions;
 
@@ -2052,21 +2138,21 @@ private:
 public:
     void fGetIntegerv(GLenum pname, GLint *params) {
         switch (pname)
         {
             // LOCAL_GL_FRAMEBUFFER_BINDING is equal to
             // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, so we don't need two
             // cases.
             case LOCAL_GL_FRAMEBUFFER_BINDING:
-                *params = GetBoundDrawFBO();
+                *params = GetUserBoundDrawFBO();
                 break;
 
             case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
-                *params = GetBoundReadFBO();
+                *params = GetUserBoundReadFBO();
                 break;
 
             default:
                 raw_fGetIntegerv(pname, params);
                 break;
         }
     }
 
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -148,17 +148,21 @@ public:
 
     GLContextType GetContextType() {
         return ContextTypeCGL;
     }
 
     bool Init()
     {
         MakeCurrent();
-        return InitWithPrefix("gl", true);
+        if (!InitWithPrefix("gl", true))
+            return false;
+
+        InitFramebuffers();
+        return true;
     }
 
     void *GetNativeData(NativeDataType aType)
     { 
         switch (aType) {
         case NativeGLContext:
             return mContext;
 
@@ -451,17 +455,17 @@ GLContextProviderCGL::CreateForWindow(ns
     [context setView:childView];
 
     // make the context transparent
     nsRefPtr<GLContextCGL> glContext = new GLContextCGL(ContextFormat(ContextFormat::BasicRGB24),
                                                         shareContext,
                                                         context);
     if (!glContext->Init()) {
         return nsnull;
-    }    
+    }
 
     return glContext.forget();
 }
 
 static already_AddRefed<GLContextCGL>
 CreateOffscreenPBufferContext(const gfxIntSize& aSize,
                               const ContextFormat& aFormat,
                               bool aShare = false)
@@ -549,16 +553,17 @@ CreateOffscreenPBufferContext(const gfxI
         GLint l;
         [pbFormat getValues:&l forAttribute:NSOpenGLPFADepthSize forVirtualScreen:[context currentVirtualScreen]];
         printf_stderr("*** depth: %d (req: %d)\n", l, aFormat.depth);
     }
 
     [pbFormat release];
 
     nsRefPtr<GLContextCGL> glContext = new GLContextCGL(aFormat, shareContext, context, pb);
+
     return glContext.forget();
 }
 
 static already_AddRefed<GLContextCGL>
 CreateOffscreenFBOContext(const ContextFormat& aFormat,
                           bool aShare = true)
 {
     if (!sCGLLibrary.EnsureInitialized()) {
@@ -574,16 +579,17 @@ CreateOffscreenFBOContext(const ContextF
     NSOpenGLContext *context = [[NSOpenGLContext alloc]
                                 initWithFormat:sCGLLibrary.PixelFormat()
                                 shareContext:shareContext ? shareContext->mContext : NULL];
     if (!context) {
         return nsnull;
     }
 
     nsRefPtr<GLContextCGL> glContext = new GLContextCGL(aFormat, shareContext, context, true);
+
     return glContext.forget();
 }
 
 already_AddRefed<GLContext>
 GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
                                       const ContextFormat& aFormat)
 {
     ContextFormat actualFormat(aFormat);
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -1094,16 +1094,19 @@ public:
         if (ok) {
             EGLint v;
             sEGLLibrary.fQueryContext(EGL_DISPLAY(), mContext, LOCAL_EGL_RENDER_BUFFER, &v);
             if (v == LOCAL_EGL_BACK_BUFFER)
                 mIsDoubleBuffered = true;
         }
 #endif
 
+        if (ok)
+            InitFramebuffers();
+
         return ok;
     }
 
     bool IsDoubleBuffered() {
         return mIsDoubleBuffered;
     }
 
     void SetIsDoubleBuffered(bool aIsDB) {
@@ -1311,19 +1314,16 @@ public:
     void SetOffscreenSize(const gfxIntSize &aRequestedSize,
                           const gfxIntSize &aActualSize)
     {
         mOffscreenSize = aRequestedSize;
         mOffscreenActualSize = aActualSize;
     }
 
     void *GetD3DShareHandle() {
-        if (!mPBufferCanBindToTexture)
-            return nsnull;
-
         if (!sEGLLibrary.HasANGLESurfaceD3DTexture2DShareHandle()) {
             return nsnull;
         }
 
         void *h = nsnull;
 
 #ifndef EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE
 #define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
@@ -2387,17 +2387,17 @@ GLContextEGL::CreateEGLPBufferOffscreenC
     bool configCanBindToTexture = true;
 
     EGLConfig configs[64];
     int numConfigs = sizeof(configs)/sizeof(EGLConfig);
     int foundConfigs = 0;
 
     // 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())
+    if (sEGLLibrary.IsANGLE() || bufferUnused)
         configCanBindToTexture = false;
 
     nsTArray<EGLint> attribs(32);
     int attribAttempt = 0;
 
     int tryDepthSize = (aFormat.depth > 0) ? 24 : 0;
 
 TRY_ATTRIBS_AGAIN:
@@ -2427,16 +2427,17 @@ TRY_ATTRIBS_AGAIN:
         if (configCanBindToTexture) {
             NS_WARNING("No pbuffer EGL configs that can bind to texture, trying without");
             configCanBindToTexture = false;
             attribAttempt = 0;
             goto TRY_ATTRIBS_AGAIN;
         }
 
         // no configs? no pbuffers!
+        NS_WARNING("Failed to select acceptable config for PBuffer creation!");
         return nsnull;
     }
 
     // XXX do some smarter matching here, perhaps instead of the more complex
     // minimum overrides above
     config = configs[0];
 #ifdef DEBUG
     sEGLLibrary.DumpEGLConfig(config);
@@ -2445,46 +2446,50 @@ TRY_ATTRIBS_AGAIN:
     gfxIntSize pbsize(aSize);
     surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
                                                                  configCanBindToTexture
                                                                  ? (aFormat.minAlpha
                                                                     ? LOCAL_EGL_TEXTURE_RGBA
                                                                     : LOCAL_EGL_TEXTURE_RGB)
                                                                  : LOCAL_EGL_NONE,
                                                                  pbsize);
-    if (!surface)
+    if (!surface) {
+        NS_WARNING("Failed to create PBuffer for context!");
         return nsnull;
+    }
 
     sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API);
 
     GLContextEGL* shareContext = GetGlobalContextEGL();
     context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
                                          config,
                                          shareContext ? shareContext->mContext
                                                       : EGL_NO_CONTEXT,
                                          sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
                                                                      : gContextAttribs);
     if (!context) { 
-        NS_WARNING("Failed to create context");
+        NS_WARNING("Failed to create GLContext from PBuffer");
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
         return nsnull;
     }
 
     nsRefPtr<GLContextEGL> glContext = new GLContextEGL(aFormat, shareContext,
                                                         config, surface, context,
                                                         true);
 
     if (!glContext->Init()) {
+        NS_WARNING("Failed to initialize GLContext!");
         return nsnull;
     }
 
-    if (!bufferUnused) {
+    glContext->mPBufferCanBindToTexture = configCanBindToTexture;
+
+    if (!bufferUnused) {  // We *are* using the buffer
       glContext->SetOffscreenSize(aSize, pbsize);
       glContext->mIsPBuffer = true;
-      glContext->mPBufferCanBindToTexture = configCanBindToTexture;
     }
 
     return glContext.forget();
 }
 
 #ifdef MOZ_X11
 EGLSurface
 CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig, EGLenum aDepth)
@@ -2635,23 +2640,30 @@ already_AddRefed<GLContext>
 GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
                                       const ContextFormat& aFormat)
 {
     if (!sEGLLibrary.EnsureInitialized()) {
         return nsnull;
     }
 
 #if defined(ANDROID) || defined(XP_WIN)
+    bool usePBuffers = false; // Generally, prefer FBOs to PBuffers
+
+    if (sEGLLibrary.IsANGLE())
+      usePBuffers = true; // For d3d share handle, we need an EGL surface
+
+    gfxIntSize pbufferSize = usePBuffers ? aSize : gfxIntSize(16, 16);
     nsRefPtr<GLContextEGL> glContext =
-        GLContextEGL::CreateEGLPBufferOffscreenContext(gfxIntSize(16, 16), aFormat, true);
+        GLContextEGL::CreateEGLPBufferOffscreenContext(pbufferSize, aFormat, !usePBuffers);
 
     if (!glContext)
         return nsnull;
 
-    if (!glContext->ResizeOffscreenFBO(aSize, true))
+    gfxIntSize fboSize = usePBuffers ? glContext->OffscreenActualSize() : aSize;
+    if (!glContext->ResizeOffscreenFBO(fboSize, !usePBuffers))
         return nsnull;
 
     return glContext.forget();
 #elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
     nsRefPtr<GLContextEGL> glContext =
         GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, aFormat);
 
     if (!glContext)
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -771,17 +771,22 @@ TRY_AGAIN_NO_SHARING:
     bool Init()
     {
         MakeCurrent();
         SetupLookupFunction();
         if (!InitWithPrefix("gl", true)) {
             return false;
         }
 
-        return IsExtensionSupported("GL_EXT_framebuffer_object");
+        if (!IsExtensionSupported("GL_EXT_framebuffer_object"))
+            return false;
+
+        InitFramebuffers();
+
+        return true;
     }
 
     bool MakeCurrentImpl(bool aForce = false)
     {
         bool succeeded = true;
 
         // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change.
         // (This is not the case with other drivers such as NVIDIA).
@@ -1156,16 +1161,17 @@ GLContextProviderGLX::CreateForWindow(ns
 
     nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
                                                                      display,
                                                                      window,
                                                                      cfgs[matchIndex],
                                                                      vinfo,
                                                                      shareContext,
                                                                      false);
+
     return glContext.forget();
 }
 
 static already_AddRefed<GLContextGLX>
 CreateOffscreenPixmapContext(const gfxIntSize& aSize,
                              const ContextFormat& aFormat,
                              bool aShare)
 {
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -320,17 +320,21 @@ public:
 
     bool Init()
     {
         if (!mDC || !mContext)
             return false;
 
         MakeCurrent();
         SetupLookupFunction();
-        return InitWithPrefix("gl", true);
+        if (!InitWithPrefix("gl", true))
+            return false;
+
+        InitFramebuffers();
+        return true;
     }
 
     bool MakeCurrentImpl(bool aForce = false)
     {
         BOOL succeeded = true;
 
         // wglGetCurrentContext seems to just pull the HGLRC out
         // of its TLS slot, so no need to do our own tls slot.