b=594892; [gl] force a real call to MakeCurrent after a widget is resized; r*=joe/jeff
authorVladimir Vukicevic <vladimir@pobox.com>
Thu, 09 Sep 2010 16:40:29 -0400
changeset 53689 46c0a7c9e4f5ba256e620309f41f03dbb22bdeb1
parent 53688 45518cd69dd16275f8378764823aea847e911d96
child 53690 508d0a50827c32b4b7ec0940595aebcef7353108
push idunknown
push userunknown
push dateunknown
bugs594892
milestone2.0b6pre
b=594892; [gl] force a real call to MakeCurrent after a widget is resized; r*=joe/jeff * * * b=594892; merge fail
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.h
gfx/thebes/GLContext.h
gfx/thebes/GLContextProviderCGL.mm
gfx/thebes/GLContextProviderEGL.cpp
gfx/thebes/GLContextProviderGLX.cpp
gfx/thebes/GLContextProviderOSMesa.cpp
gfx/thebes/GLContextProviderWGL.cpp
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -475,27 +475,16 @@ LayerManagerOGL::ForgetImageContainer(Im
 void
 LayerManagerOGL::RememberImageContainer(ImageContainer *aContainer)
 {
   NS_ASSERTION(aContainer->Manager() == this,
                "RememberImageContainer called on non-owned container!");
   mImageContainers.AppendElement(aContainer);
 }
 
-void
-LayerManagerOGL::MakeCurrent()
-{
-  if (mDestroyed) {
-    NS_WARNING("Call on destroyed layer manager");
-    return;
-  }
-
-  mGLContext->MakeCurrent();
-}
-
 LayerOGL*
 LayerManagerOGL::RootLayer() const
 {
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return nsnull;
   }
 
@@ -508,25 +497,35 @@ LayerManagerOGL::Render()
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
-  // We can't draw anything to something with no area
-  // so just return
-  if (rect.width == 0 || rect.height == 0)
-    return;
-
   GLint width = rect.width;
   GLint height = rect.height;
 
-  MakeCurrent();
+  // We can't draw anything to something with no area
+  // so just return
+  if (width == 0 || height == 0)
+    return;
+
+  // If the widget size changed, we have to force a MakeCurrent
+  // to make sure that GL sees the updated widget size.
+  if (mWidgetSize.width != width ||
+      mWidgetSize.height != height)
+  {
+    MakeCurrent(PR_TRUE);
+    mWidgetSize.width = width;
+    mWidgetSize.height = height;
+  } else {
+    MakeCurrent();
+  }
 
   DEBUG_GL_ERROR_CHECK(mGLContext);
 
   SetupBackBuffer(width, height);
   SetupPipeline(width, height);
 
   // Default blend function implements "OVER"
   mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -146,17 +146,23 @@ public:
    * on its current layer manager before switching to a new one.
    */
   void ForgetImageContainer(ImageContainer* aContainer);
   void RememberImageContainer(ImageContainer* aContainer);
 
   /**
    * Helper methods.
    */
-  void MakeCurrent();
+  void MakeCurrent(PRBool aForce = PR_FALSE) {
+    if (mDestroyed) {
+      NS_WARNING("Call on destroyed layer manager");
+      return;
+    }
+    mGLContext->MakeCurrent(aForce);
+  }
 
   ColorTextureLayerProgram *GetRGBALayerProgram() {
     return static_cast<ColorTextureLayerProgram*>(mPrograms[RGBALayerProgramType]);
   }
   ColorTextureLayerProgram *GetBGRALayerProgram() {
     return static_cast<ColorTextureLayerProgram*>(mPrograms[BGRALayerProgramType]);
   }
   ColorTextureLayerProgram *GetRGBXLayerProgram() {
@@ -309,16 +315,18 @@ public:
 
 #ifdef MOZ_LAYERS_HAVE_LOG
    virtual const char* Name() const { return "OGL"; }
 #endif // MOZ_LAYERS_HAVE_LOG
 
 private:
   /** Widget associated with this layer manager */
   nsIWidget *mWidget;
+  nsIntSize mWidgetSize;
+
   /** 
    * Context target, NULL when drawing directly to our swap chain.
    */
   nsRefPtr<gfxContext> mTarget;
 
   nsRefPtr<GLContext> mGLContext;
 
   // The image containers that this layer manager has created.
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -369,17 +369,17 @@ public:
         ContextTypeWGL,
         ContextTypeCGL,
         ContextTypeGLX,
         ContextTypeEGL,
         ContextTypeOSMesa
     };
 
     virtual GLContextType GetContextType() { return ContextTypeUnknown; }
-    virtual PRBool MakeCurrent() = 0;
+    virtual PRBool MakeCurrent(PRBool aForce = PR_FALSE) = 0;
     virtual PRBool SetupLookupFunction() = 0;
 
     virtual void WindowDestroyed() {}
 
     void *GetUserData(void *aKey) {
         void *result = nsnull;
         mUserData.Get(aKey, &result);
         return result;
--- a/gfx/thebes/GLContextProviderCGL.mm
+++ b/gfx/thebes/GLContextProviderCGL.mm
@@ -149,17 +149,17 @@ public:
         case NativeGLContext:
             return mContext;
 
         default:
             return nsnull;
         }
     }
 
-    PRBool MakeCurrent()
+    PRBool MakeCurrent(PRBool aForce = PR_FALSE)
     {
         if (mContext) {
             [mContext makeCurrentContext];
         }
         return PR_TRUE;
     }
 
     PRBool SetupLookupFunction()
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -603,17 +603,17 @@ public:
                                                LOCAL_EGL_BACK_BUFFER);
         if (success == LOCAL_EGL_FALSE)
             return PR_FALSE;
 
         mBound = PR_FALSE;
         return PR_TRUE;
     }
 
-    PRBool MakeCurrent(PRBool aForce) {
+    PRBool MakeCurrent(PRBool aForce = PR_FALSE) {
         PRBool succeeded = PR_TRUE;
 
         // Assume that EGL has the same problem as WGL does,
         // where MakeCurrent with an already-current context is
         // still expensive.
         if (aForce || sEGLLibrary.fGetCurrentContext() != mContext) {
             if (mGLWidget) {
 #ifdef MOZ_WIDGET_QT
@@ -627,21 +627,16 @@ public:
                                                      mContext);
             }
             NS_ASSERTION(succeeded, "Failed to make GL context current!");
         }
 
         return succeeded;
     }
 
-    PRBool MakeCurrent()
-    {
-        return MakeCurrent(PR_FALSE);
-    }
-
     PRBool SetupLookupFunction()
     {
         mLookupFunc = (PlatformLookupFunction)sEGLLibrary.fGetProcAddress;
         return PR_TRUE;
     }
 
     void *GetNativeData(NativeDataType aType)
     {
--- a/gfx/thebes/GLContextProviderGLX.cpp
+++ b/gfx/thebes/GLContextProviderGLX.cpp
@@ -247,17 +247,17 @@ TRY_AGAIN_NO_SHARING:
         SetupLookupFunction();
         if (!InitWithPrefix("gl", PR_TRUE)) {
             return PR_FALSE;
         }
 
         return IsExtensionSupported("GL_EXT_framebuffer_object");
     }
 
-    PRBool MakeCurrent()
+    PRBool MakeCurrent(PRBool aForce = PR_FALSE)
     {
         Bool succeeded = sGLXLibrary.xMakeCurrent(mDisplay, mDrawable, mContext);
         NS_ASSERTION(succeeded, "Failed to make GL context current!");
         return succeeded;
     }
 
     PRBool SetupLookupFunction()
     {
--- a/gfx/thebes/GLContextProviderOSMesa.cpp
+++ b/gfx/thebes/GLContextProviderOSMesa.cpp
@@ -217,17 +217,17 @@ public:
         if (!SetupLookupFunction()) return PR_FALSE;
 
         // OSMesa's different from the other GL providers, it renders to an image surface, not to a pbuffer
         sOSMesaLibrary.fPixelStore(OSMESA_Y_UP, 0);
 
         return InitWithPrefix("gl", PR_TRUE);
     }
 
-    PRBool MakeCurrent()
+    PRBool MakeCurrent(PRBool aForce = PR_FALSE)
     {
         PRBool succeeded
           = sOSMesaLibrary.fMakeCurrent(mContext, mThebesSurface->Data(),
                                         LOCAL_GL_UNSIGNED_BYTE,
                                         mThebesSurface->Width(),
                                         mThebesSurface->Height());
         NS_ASSERTION(succeeded, "Failed to make OSMesa context current!");
 
--- a/gfx/thebes/GLContextProviderWGL.cpp
+++ b/gfx/thebes/GLContextProviderWGL.cpp
@@ -214,32 +214,34 @@ public:
                  HGLRC aContext,
                  HWND aWindow = nsnull,
                  PRBool aIsOffscreen = PR_FALSE)
         : GLContext(aFormat, aIsOffscreen, aSharedContext),
           mDC(aDC),
           mContext(aContext),
           mWnd(aWindow),
           mPBuffer(NULL),
-          mPixelFormat(0)
+          mPixelFormat(0),
+          mIsDoubleBuffered(PR_FALSE)
     {
     }
 
     GLContextWGL(const ContextFormat& aFormat,
                  GLContext *aSharedContext,
                  HANDLE aPbuffer,
                  HDC aDC,
                  HGLRC aContext,
                  int aPixelFormat)
         : GLContext(aFormat, PR_TRUE, aSharedContext),
           mDC(aDC),
           mContext(aContext),
           mWnd(NULL),
           mPBuffer(aPbuffer),
-          mPixelFormat(aPixelFormat)
+          mPixelFormat(aPixelFormat),
+          mIsDoubleBuffered(PR_FALSE)
     {
     }
 
     ~GLContextWGL()
     {
         if (mOffscreenFBO) {
             MakeCurrent();
             DeleteOffscreenFBO();
@@ -262,32 +264,46 @@ public:
         if (!mDC || !mContext)
             return PR_FALSE;
 
         MakeCurrent();
         SetupLookupFunction();
         return InitWithPrefix("gl", PR_TRUE);
     }
 
-    PRBool MakeCurrent()
+    PRBool MakeCurrent(PRBool aForce = PR_FALSE)
     {
         BOOL succeeded = PR_TRUE;
 
         // wglGetCurrentContext seems to just pull the HGLRC out
         // of its TLS slot, so no need to do our own tls slot.
         // You would think that wglMakeCurrent would avoid doing
         // work if mContext was already current, but not so much..
-        if (sWGLLibrary.fGetCurrentContext() != mContext) {
+        if (aForce || sWGLLibrary.fGetCurrentContext() != mContext) {
             succeeded = sWGLLibrary.fMakeCurrent(mDC, mContext);
             NS_ASSERTION(succeeded, "Failed to make GL context current!");
         }
 
         return succeeded;
     }
 
+    void SetIsDoubleBuffered(PRBool aIsDB) {
+        mIsDoubleBuffered = aIsDB;
+    }
+
+    virtual PRBool IsDoubleBuffered() {
+        return mIsDoubleBuffered;
+    }
+
+    virtual PRBool SwapBuffers() {
+        if (!mIsDoubleBuffered)
+            return PR_FALSE;
+        return ::SwapBuffers(mDC);
+    }
+
     PRBool SetupLookupFunction()
     {
         mLookupFunc = (PlatformLookupFunction)sWGLLibrary.fGetProcAddress;
         return PR_TRUE;
     }
 
     void *GetNativeData(NativeDataType aType)
     {
@@ -315,16 +331,18 @@ public:
 protected:
     friend class GLContextProviderWGL;
 
     HDC mDC;
     HGLRC mContext;
     HWND mWnd;
     HANDLE mPBuffer;
     int mPixelFormat;
+
+    PRPackedBool mIsDoubleBuffered;
 };
 
 PRBool
 GLContextWGL::BindTex2DOffscreen(GLContext *aOffscreen)
 {
     if (aOffscreen->GetContextType() != ContextTypeWGL) {
         NS_WARNING("non-WGL context");
         return PR_FALSE;