Bug 1238755 - Avoid a copy when uploading the BasicCompositor result to a texture. r?mattwoodrow draft
authorMarkus Stange <mstange@themasta.com>
Mon, 11 Jan 2016 20:11:10 +0100
changeset 320604 b8352d4025f4c526fd286a1ed122a804fbf56b39
parent 320603 b3bb8d735119d681b161c749c2a39340a6879e26
child 320605 a3771e0291f23e7844975c6536149315c1dc8e7f
push id9248
push usermstange@themasta.com
push dateMon, 11 Jan 2016 22:41:48 +0000
reviewersmattwoodrow
bugs1238755
milestone46.0a1
Bug 1238755 - Avoid a copy when uploading the BasicCompositor result to a texture. r?mattwoodrow
widget/cocoa/nsChildView.mm
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -313,16 +313,17 @@ public:
             const Matrix4x4& aTransform = Matrix4x4());
 
   static LayoutDeviceIntSize TextureSizeForSize(
     const LayoutDeviceIntSize& aSize);
 
 protected:
 
   RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
+  UniquePtr<unsigned char[]> mUpdateDrawTargetData;
   GLContext* mGLContext;
   LayoutDeviceIntRegion mUpdateRegion;
   LayoutDeviceIntSize mUsedSize;
   LayoutDeviceIntSize mBufferSize;
   LayoutDeviceIntSize mTextureSize;
   GLuint mTexture;
   bool mInUpdate;
 };
@@ -2931,19 +2932,24 @@ RectTextureImage::BeginUpdate(const Layo
 
   if (mUpdateRegion.IsEmpty()) {
     return nullptr;
   }
 
   LayoutDeviceIntSize neededBufferSize = TextureSizeForSize(mUsedSize);
   if (!mUpdateDrawTarget || mBufferSize != neededBufferSize) {
     gfx::IntSize size(neededBufferSize.width, neededBufferSize.height);
+    mUpdateDrawTarget = nullptr;
+    mUpdateDrawTargetData = nullptr;
+    int32_t stride = size.width * 4;
+    mUpdateDrawTargetData = MakeUnique<unsigned char[]>(stride * size.height);
     mUpdateDrawTarget =
-      gfx::Factory::CreateDrawTarget(gfx::BackendType::COREGRAPHICS, size,
-                                     gfx::SurfaceFormat::B8G8R8A8);
+      gfx::Factory::CreateDrawTargetForData(gfx::BackendType::COREGRAPHICS,
+                                            mUpdateDrawTargetData.get(), size,
+                                            stride, gfx::SurfaceFormat::B8G8R8A8);
     mBufferSize = neededBufferSize;
   }
 
   mInUpdate = true;
 
   RefPtr<gfx::DrawTarget> drawTarget = mUpdateDrawTarget;
   return drawTarget.forget();
 }
@@ -2968,31 +2974,31 @@ RectTextureImage::EndUpdate(bool aKeepSu
     mTextureSize = mBufferSize;
   }
 
   if (overwriteTexture || !CanUploadSubtextures()) {
     updateRegion =
       LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0), mTextureSize);
   }
 
-  RefPtr<gfx::SourceSurface> snapshot = mUpdateDrawTarget->Snapshot();
-  RefPtr<gfx::DataSourceSurface> dataSnapshot = snapshot->GetDataSurface();
-
-  UploadSurfaceToTexture(mGLContext,
-                         dataSnapshot,
-                         updateRegion.ToUnknownRegion(),
-                         mTexture,
-                         overwriteTexture,
-                         updateRegion.GetBounds().TopLeft().ToUnknownPoint(),
-                         false,
-                         LOCAL_GL_TEXTURE0,
-                         LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+  gfx::IntPoint srcPoint = updateRegion.GetBounds().TopLeft().ToUnknownPoint();
+  unsigned char* data = mUpdateDrawTargetData.get();
+  int32_t stride = mBufferSize.width * 4;
+  gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
+  data += srcPoint.y * stride + srcPoint.x * 4;
+
+  UploadImageDataToTexture(mGLContext, data, stride, format,
+                           updateRegion.ToUnknownRegion(), mTexture,
+                           overwriteTexture, false,
+                           LOCAL_GL_TEXTURE0,
+                           LOCAL_GL_TEXTURE_RECTANGLE_ARB);
 
   if (!aKeepSurface) {
     mUpdateDrawTarget = nullptr;
+    mUpdateDrawTargetData = nullptr;
   }
 
   mInUpdate = false;
 }
 
 void
 RectTextureImage::UpdateFromCGContext(const LayoutDeviceIntSize& aNewSize,
                                       const LayoutDeviceIntRegion& aDirtyRegion,