Bug 604101 - Part 6 - Add TextureImage::DirectUpload for faster texture uploads. r=jrmuizel a=blocking2.0
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 16 Dec 2010 23:50:26 -0800
changeset 59443 d1da1005b6d61e9aec2ea40dbef18d9120dad7f7
parent 59442 c5aeb066cbb5ac67f2a71772ea0de96b56038030
child 59444 83cb5ea3fe30858b602994486d3ba48d4fda06a5
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersjrmuizel, blocking2
bugs604101
milestone2.0b9pre
Bug 604101 - Part 6 - Add TextureImage::DirectUpload for faster texture uploads. r=jrmuizel a=blocking2.0
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/thebes/GLContext.cpp
gfx/thebes/GLContext.h
gfx/thebes/GLContextProviderEGL.cpp
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -280,23 +280,17 @@ ShadowCanvasLayerOGL::Initialize(const D
 already_AddRefed<gfxSharedImageSurface>
 ShadowCanvasLayerOGL::Swap(gfxSharedImageSurface* aNewFront)
 {
   if (!mDestroyed && mTexImage) {
     // XXX this is always just ridiculously slow
 
     gfxSize sz = aNewFront->GetSize();
     nsIntRegion updateRegion(nsIntRect(0, 0, sz.width, sz.height));
-    // NB: this gfxContext must not escape EndUpdate() below
-    nsRefPtr<gfxContext> dest = mTexImage->BeginUpdate(updateRegion);
-
-    dest->SetOperator(gfxContext::OPERATOR_SOURCE);
-    dest->DrawSurface(aNewFront, aNewFront->GetSize());
-
-    mTexImage->EndUpdate();
+    mTexImage->DirectUpdate(aNewFront, updateRegion);
   }
 
   return aNewFront;
 }
 
 void
 ShadowCanvasLayerOGL::DestroyFrontBuffer()
 {
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -730,23 +730,17 @@ ShadowImageLayerOGL::Init(gfxSharedImage
 already_AddRefed<gfxSharedImageSurface>
 ShadowImageLayerOGL::Swap(gfxSharedImageSurface* aNewFront)
 {
   if (!mDestroyed && mTexImage) {
     // XXX this is always just ridiculously slow
 
     gfxSize sz = aNewFront->GetSize();
     nsIntRegion updateRegion(nsIntRect(0, 0, sz.width, sz.height));
-    // NB: this gfxContext must not escape EndUpdate() below
-    nsRefPtr<gfxContext> dest = mTexImage->BeginUpdate(updateRegion);
-
-    dest->SetOperator(gfxContext::OPERATOR_SOURCE);
-    dest->DrawSurface(aNewFront, aNewFront->GetSize());
-
-    mTexImage->EndUpdate();
+    mTexImage->DirectUpdate(aNewFront, updateRegion);
   }
 
   return aNewFront;
 }
 
 void
 ShadowImageLayerOGL::DestroyFrontBuffer()
 {
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -636,22 +636,17 @@ ShadowBufferOGL::Upload(gfxASurface* aUp
   nsIntRect destBounds = destRegion.GetBounds();
   gfxRect destRect(destBounds.x, destBounds.y, destBounds.width, destBounds.height);
   destRect.Scale(mLayer->GetXResolution(), mLayer->GetYResolution());
   destRect.RoundOut();
 
   // NB: this gfxContext must not escape EndUpdate() below
   nsIntRegion scaledDestRegion(nsIntRect(destRect.pos.x, destRect.pos.y,
                                          destRect.size.width, destRect.size.height));
-  nsRefPtr<gfxContext> dest = mTexImage->BeginUpdate(scaledDestRegion);
-
-  dest->SetOperator(gfxContext::OPERATOR_SOURCE);
-  dest->DrawSurface(aUpdate, aUpdate->GetSize());
-
-  mTexImage->EndUpdate();
+  mTexImage->DirectUpdate(aUpdate, scaledDestRegion);
 
   mBufferRect = aRect;
   mBufferRotation = aRotation;
 }
 
 ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
   : ShadowThebesLayer(aManager, nsnull)
   , LayerOGL(aManager)
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -640,16 +640,35 @@ BasicTextureImage::FinishedSurfaceUpdate
   return false;
 }
 
 void
 BasicTextureImage::FinishedSurfaceUpload()
 {
 }
 
+bool 
+BasicTextureImage::DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion)
+{
+  nsIntRect bounds = aRegion.GetBounds();
+  if (!mTextureInited) {
+    bounds = nsIntRect(0, 0, mSize.width, mSize.height);
+  }
+
+  mShaderType =
+    mGLContext->UploadSurfaceToTexture(aSurf,
+                                       bounds,
+                                       mTexture,
+                                       !mTextureInited,
+                                       bounds.TopLeft(),
+                                       PR_FALSE);
+  mTextureInited = PR_TRUE;
+  return true;
+}
+
 void
 BasicTextureImage::Resize(const nsIntSize& aSize)
 {
     NS_ASSERTION(!mUpdateContext, "Resize() while in update?");
 
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
 
     mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -197,16 +197,18 @@ public:
      */
     virtual void Resize(const nsIntSize& aSize) {
         mSize = aSize;
         nsIntRegion r(nsIntRect(0, 0, aSize.width, aSize.height));
         BeginUpdate(r);
         EndUpdate();
     }
 
+    virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion) =0;
+
     /**
      * Return this TextureImage's texture ID for use with GL APIs.
      * Callers are responsible for properly binding the texture etc.
      *
      * The texture is only texture complete after either Resize
      * or a matching pair of BeginUpdate/EndUpdate have been called.
      * Otherwise, a texture ID may be returned, but the texture
      * may not be texture complete.
@@ -290,16 +292,17 @@ public:
         : TextureImage(aTexture, aSize, aWrapMode, aContentType)
         , mTextureInited(PR_FALSE)
         , mGLContext(aContext)
         , mUpdateOffset(0, 0)
     {}
 
     virtual gfxContext* BeginUpdate(nsIntRegion& aRegion);
     virtual PRBool EndUpdate();
+    virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion);
 
     // Returns a surface to draw into
     virtual already_AddRefed<gfxASurface>
       GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt);
 
     // Call when drawing into the update surface is complete.
     // Returns true if textures should be upload with a relative 
     // offset - See UploadSurfaceToTexture.
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1127,16 +1127,40 @@ public:
                                        GLTypeForImage(uploadImage->Format()),
                                        uploadImage->Data());
         }
 
         mUpdateContext = nsnull;
         return PR_TRUE;         // mTexture is bound
     }
 
+    virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion)
+    {
+        nsIntRect bounds = aRegion.GetBounds();
+        nsIntPoint dest = bounds.TopLeft();
+
+        // Bounds is the destination rect, it will be at 0,0 on the source
+        bounds.x = 0;
+        bounds.y = 0;
+  
+        if (!mCreated) {
+            bounds = nsIntRect(0, 0, mSize.width, mSize.height);
+        }
+
+        mShaderType =
+          mGLContext->UploadSurfaceToTexture(aSurf,
+                                             bounds,
+                                             mTexture,
+                                             !mCreated,
+                                             dest,
+                                             PR_FALSE);
+        mCreated = PR_TRUE;
+        return true;
+    }
+
     virtual PRBool InUpdate() const { return !!mUpdateContext; }
 
     virtual void Resize(const nsIntSize& aSize)
     {
         NS_ASSERTION(!mUpdateContext, "Resize() while in update?");
 
         if (mSize == aSize && mCreated)
             return;