Bug 575521 - Use gfxASurface::GetAsImageSurface in TextureImageCGL to make it faster. r=jrmuizel
authorJoe Drew <joe@drew.ca>
Thu, 11 Nov 2010 15:31:23 -0500
changeset 57348 6b34818510c17db38e0898ba1809103a5051e2d7
parent 57347 7cfc5393907d81f28a95f4a6c0eecb04d8a380ef
child 57349 3be1fabf50b818bfc32a29185b6b409df270d927
push id16887
push userjdrew@mozilla.com
push dateThu, 11 Nov 2010 20:37:00 +0000
treeherdermozilla-central@182eb3c4fc44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs575521
milestone2.0b8pre
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 575521 - Use gfxASurface::GetAsImageSurface in TextureImageCGL to make it faster. r=jrmuizel
gfx/thebes/GLContext.cpp
gfx/thebes/GLContextProviderCGL.mm
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -559,16 +559,23 @@ BasicTextureImage::EndUpdate()
     // but important if we ever do anything directly with the surface.
     originalSurface->SetDeviceOffset(gfxPoint(0, 0));
 
     nsRefPtr<gfxImageSurface> uploadImage = GetImageForUpload(originalSurface);
     if (!uploadImage)
         return PR_FALSE;
 
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+
+    // The images that come out of the cairo quartz surface are 16-byte aligned
+    // for performance. We know this is an RGBA surface, so we divide the
+    // stride by 4 to represent the number of elements long the row is.
+    mGLContext->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH,
+                             uploadImage->Stride() / 4);
+
     if (!mTextureInited)
     {
         mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
                                 0,
                                 LOCAL_GL_RGBA,
                                 mUpdateRect.width,
                                 mUpdateRect.height,
                                 0,
@@ -583,16 +590,20 @@ BasicTextureImage::EndUpdate()
                                    mUpdateRect.y,
                                    mUpdateRect.width,
                                    mUpdateRect.height,
                                    LOCAL_GL_RGBA,
                                    LOCAL_GL_UNSIGNED_BYTE,
                                    uploadImage->Data());
     }
     mUpdateContext = NULL;
+
+    // Reset row length to use the default.
+    mGLContext->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+
     return PR_TRUE;         // mTexture is bound
 }
 
 void
 BasicTextureImage::Resize(const nsIntSize& aSize)
 {
     NS_ASSERTION(!mUpdateContext, "Resize() while in update?");
 
--- a/gfx/thebes/GLContextProviderCGL.mm
+++ b/gfx/thebes/GLContextProviderCGL.mm
@@ -37,16 +37,17 @@
 #include "GLContextProvider.h"
 #include "nsDebug.h"
 #include "nsIWidget.h"
 #include "OpenGL/OpenGL.h"
 #include <OpenGL/gl.h>
 #include <AppKit/NSOpenGL.h>
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
+#include "gfxQuartzSurface.h"
 #include "gfxPlatform.h"
 
 namespace mozilla {
 namespace gl {
 
 class CGLLibrary
 {
 public:
@@ -276,26 +277,34 @@ protected:
     {
         mUpdateFormat = aFmt;
         return gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt));
     }
 
     virtual already_AddRefed<gfxImageSurface>
     GetImageForUpload(gfxASurface* aUpdateSurface)
     {
-        // FIXME/bug 575521: make me fast!
-        nsRefPtr<gfxImageSurface> image =
-            new gfxImageSurface(gfxIntSize(mUpdateRect.width,
-                                           mUpdateRect.height),
-                                mUpdateFormat);
-        nsRefPtr<gfxContext> tmpContext = new gfxContext(image);
+        nsRefPtr<gfxImageSurface> image = aUpdateSurface->GetAsImageSurface();
+
+        if (image && image->Format() != mUpdateFormat) {
+          image = nsnull;
+        }
 
-        tmpContext->SetSource(aUpdateSurface);
-        tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE);
-        tmpContext->Paint();
+        // If we don't get an image directly from the quartz surface, we have
+        // to take the slow boat.
+        if (!image) {
+          image = new gfxImageSurface(gfxIntSize(mUpdateRect.width,
+                                                 mUpdateRect.height),
+                                      mUpdateFormat);
+          nsRefPtr<gfxContext> tmpContext = new gfxContext(image);
+
+          tmpContext->SetSource(aUpdateSurface);
+          tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE);
+          tmpContext->Paint();
+        }
 
         return image.forget();
     }
 
 private:
     TextureImageCGL(GLuint aTexture,
                     const nsIntSize& aSize,
                     ContentType aContentType,