Bug 1347147 - fix DrawTargetD2D1::GetImageForSurface to support uploads in device-space. r=mchang a=gchang
authorLee Salzman <lsalzman@mozilla.com>
Tue, 14 Mar 2017 22:17:47 -0400
changeset 375293 b6b6a603722a
parent 375292 930aa449c30f
child 375294 daf87d4151aa
push id10915
push usercbook@mozilla.com
push dateMon, 20 Mar 2017 12:05:19 +0000
treeherdermozilla-aurora@ac9d58dd3c7c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang, gchang
bugs1347147
milestone54.0a2
Bug 1347147 - fix DrawTargetD2D1::GetImageForSurface to support uploads in device-space. r=mchang a=gchang MozReview-Commit-ID: 2galhKidxca
gfx/2d/DrawTargetD2D1.cpp
gfx/2d/DrawTargetD2D1.h
layout/reftests/canvas/1347147-1-ref.html
layout/reftests/canvas/1347147-1.html
layout/reftests/canvas/reftest.list
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -224,17 +224,17 @@ DrawTargetD2D1::DrawSurfaceWithShadow(So
                                       Float aSigma,
                                       CompositionOp aOperator)
 {
   MarkChanged();
   mDC->SetTransform(D2D1::IdentityMatrix());
   mTransformDirty = true;
 
   Matrix mat;
-  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);
+  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP, nullptr, false);
 
   if (!image) {
     gfxWarning() << "Couldn't get image for surface.";
     return;
   }
 
   if (!mat.IsIdentity()) {
     gfxDebug() << *this << ": At this point complex partial uploads are not supported for Shadow surfaces.";
@@ -373,17 +373,17 @@ DrawTargetD2D1::CopySurface(SourceSurfac
   MarkChanged();
 
   PopAllClips();
 
   mDC->SetTransform(D2D1::IdentityMatrix());
   mTransformDirty = true;
 
   Matrix mat = Matrix::Translation(aDestination.x - aSourceRect.x, aDestination.y - aSourceRect.y);
-  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);
+  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP, nullptr, false);
 
   if (!image) {
     gfxWarning() << "Couldn't get image for surface.";
     return;
   }
 
   if (mat.HasNonIntegerTranslation()) {
     gfxDebug() << *this << ": At this point scaled partial uploads are not supported for CopySurface.";
@@ -1852,17 +1852,18 @@ DrawTargetD2D1::CreateBrushForPattern(co
   }
 
   gfxWarning() << "Invalid pattern type detected.";
   return CreateTransparentBlackBrush();
 }
 
 already_AddRefed<ID2D1Image>
 DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
-                                   ExtendMode aExtendMode, const IntRect* aSourceRect)
+                                   ExtendMode aExtendMode, const IntRect* aSourceRect,
+                                   bool aUserSpace)
 {
   RefPtr<ID2D1Image> image;
 
   switch (aSurface->GetType()) {
   case SurfaceType::D2D1_1_IMAGE:
     {
       SourceSurfaceD2D1 *surf = static_cast<SourceSurfaceD2D1*>(aSurface);
       image = surf->GetImage();
@@ -1871,17 +1872,18 @@ DrawTargetD2D1::GetImageForSurface(Sourc
     break;
   default:
     {
       RefPtr<DataSourceSurface> dataSurf = aSurface->GetDataSurface();
       if (!dataSurf) {
         gfxWarning() << "Invalid surface type.";
         return nullptr;
       }
-      return CreatePartialBitmapForSurface(dataSurf, mTransform, mSize, aExtendMode,
+      Matrix transform = aUserSpace ? mTransform : Matrix();
+      return CreatePartialBitmapForSurface(dataSurf, transform, mSize, aExtendMode,
                                            aSourceTransform, mDC, aSourceRect);
     }
     break;
   }
 
   return image.forget();
 }
 
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -135,19 +135,21 @@ public:
                                             uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics) override;
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
   bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat);
   uint32_t GetByteSize() const;
 
   // This function will get an image for a surface, it may adjust the source
   // transform for any transformation of the resulting image relative to the
-  // oritingal SourceSurface.
+  // oritingal SourceSurface. By default, the surface and its transform are
+  // interpreted in user-space, but may be specified in device-space instead.
   already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
-                                              ExtendMode aExtendMode, const IntRect* aSourceRect = nullptr);
+                                              ExtendMode aExtendMode, const IntRect* aSourceRect = nullptr,
+                                              bool aUserSpace = true);
 
   already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, ExtendMode aExtendMode) {
     Matrix mat;
     return GetImageForSurface(aSurface, mat, aExtendMode, nullptr);
   }
 
   static ID2D1Factory1 *factory();
   static void CleanupD2D();
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/1347147-1-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <script>
+      function draw() {
+        var c = document.getElementById('c').getContext('2d');
+
+        c.fillStyle = 'lime';
+        c.fillRect(0, 0, 100, 50);
+
+        c.fillStyle = 'red';
+        c.fillRect(40, 0, 30, 50);
+
+        c.fillStyle = 'blue';
+        c.fillRect(70, 0, 30, 50);
+      }
+    </script>
+  </head>
+  <body onload="draw();">
+    <canvas id='c' width='100' height='50'></canvas>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/1347147-1.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <script>
+      function draw() {
+        var c = document.getElementById('c').getContext('2d');
+
+        c.fillStyle = 'lime';
+        c.fillRect(0, 0, 100, 50);
+
+        var imgdata = c.createImageData(60, 50);
+        for (var i = 0; i < imgdata.data.length; i += 4 * 60) {
+            for (var x = i; x < i + 4 * 30; x += 4) {
+                imgdata.data[x] = 255;
+                imgdata.data[x+3] = 255;
+            }
+            for (var x = i + 4 * 30; x < i + 4 * 60; x += 4) {
+                imgdata.data[x+2] = 255;
+                imgdata.data[x+3] = 255;
+            }
+        }
+
+        // Verify that putImageData is not affected by the current transform.
+        c.translate(20, 0);
+        c.putImageData(imgdata, 40, 0);
+      }
+    </script>
+  </head>
+  <body onload="draw();">
+    <canvas id='c' width='100' height='50'></canvas>
+  </body>
+</html>
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -103,8 +103,10 @@ fuzzy-if(d2d,12,21) fuzzy-if(skiaContent
 == 1201272-1.html 1201272-1-ref.html
 == 1224976-1.html 1224976-1-ref.html
 == 1238795-1.html 1238795-1-ref.html
 == 1303534-1.html 1303534-1-ref.html
 
 == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1-ref.html
 fuzzy-if(winWidget,1,14) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2-ref.html
 fuzzy-if(winWidget,94,1575) fuzzy-if(cocoaWidget,1,24) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1-ref.html
+
+== 1347147-1.html 1347147-1-ref.html