Bug 1347147 - fix DrawTargetD2D1::GetImageForSurface to support uploads in device-space. r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Tue, 14 Mar 2017 22:17:47 -0400
changeset 347658 fa6e1037d65d
parent 347657 9883a566c747
child 347659 9279db79576b
push id88063
push userlsalzman@mozilla.com
push dateWed, 15 Mar 2017 02:18:16 +0000
treeherdermozilla-inbound@fa6e1037d65d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1347147
milestone55.0a1
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 1347147 - fix DrawTargetD2D1::GetImageForSurface to support uploads in device-space. r=mchang 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