Bug 1399268 - Disable filtering during Draw3DTransformedSurface() when layer was split draft
authorMiko Mynttinen <mikokm@gmail.com>
Thu, 12 Oct 2017 17:40:12 +0200
changeset 680570 0745cbbe2b885489bd5d6d115da15bbdfc4d9650
parent 680024 196dadb2fe500e75c6fbddcac78106648676cf10
child 735890 1ddd5418ec70af2d4a0ca97f811c8131dbb09008
push id84540
push userbmo:mikokm@gmail.com
push dateSun, 15 Oct 2017 13:27:31 +0000
bugs1399268
milestone58.0a1
Bug 1399268 - Disable filtering during Draw3DTransformedSurface() when layer was split MozReview-Commit-ID: KEvmh2sbOY7
gfx/2d/2D.h
gfx/2d/DrawTargetCairo.cpp
gfx/2d/DrawTargetCairo.h
gfx/2d/DrawTargetSkia.cpp
gfx/2d/DrawTargetSkia.h
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/basic/BasicLayerManager.cpp
layout/generic/TextDrawTarget.h
layout/reftests/transform-3d/reftest.list
layout/reftests/transform-3d/split-seam-1-ref.html
layout/reftests/transform-3d/split-seam-1.html
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1171,17 +1171,18 @@ public:
 
   /**
    * Draw aSurface using the 3D transform aMatrix. The DrawTarget's transform
    * and clip are applied after the 3D transform.
    *
    * If the transform fails (i.e. because aMatrix is singular), false is returned and nothing is drawn.
    */
   virtual bool Draw3DTransformedSurface(SourceSurface* aSurface,
-                                        const Matrix4x4& aMatrix);
+                                        const Matrix4x4& aMatrix,
+                                        const bool aEnableFilter);
 
   /**
    * Push a clip to the DrawTarget.
    *
    * @param aPath The path to clip to
    */
   virtual void PushClip(const Path *aPath) = 0;
 
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -1992,17 +1992,19 @@ GfxMatrixToPixmanTransform(const Matrix4
     { aMatrix._12, aMatrix._22, aMatrix._42 },
     { aMatrix._14, aMatrix._24, aMatrix._44 }
   }};
   return pixman_transform_from_pixman_f_transform(aResult, &fTransform);
 }
 
 #ifndef USE_SKIA
 bool
-DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
+DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface,
+                                     const Matrix4x4& aMatrix,
+                                     const bool /* aEnableFilter */)
 {
   // Composite the 3D transform with the DT's transform.
   Matrix4x4 fullMat = aMatrix * Matrix4x4::From2D(mTransform);
   // Transform the surface bounds and clip to this DT.
   IntRect xformBounds =
     RoundedOut(
       fullMat.TransformAndClipBounds(Rect(Point(0, 0), Size(aSurface->GetSize())),
                                      Rect(Point(0, 0), Size(GetSize()))));
@@ -2115,24 +2117,26 @@ SupportsXRender(cairo_surface_t* surface
 
   cairo_device_release(device);
 
   return true;
 }
 #endif
 
 bool
-DrawTargetCairo::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
+DrawTargetCairo::Draw3DTransformedSurface(SourceSurface* aSurface,
+                                          const Matrix4x4& aMatrix,
+                                          const bool aEnableFilter)
 {
 #if CAIRO_HAS_XLIB_SURFACE
   cairo_surface_t* srcSurf =
     aSurface->GetType() == SurfaceType::CAIRO ?
       static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface() : nullptr;
   if (!SupportsXRender(srcSurf) || !gXRenderHasTransform) {
-    return DrawTarget::Draw3DTransformedSurface(aSurface, aMatrix);
+    return DrawTarget::Draw3DTransformedSurface(aSurface, aMatrix, aEnableFilter);
   }
 
   Matrix4x4 fullMat = aMatrix * Matrix4x4::From2D(mTransform);
   IntRect xformBounds =
     RoundedOut(
       fullMat.TransformAndClipBounds(Rect(Point(0, 0), Size(aSurface->GetSize())),
                                      Rect(Point(0, 0), Size(GetSize()))));
   if (xformBounds.IsEmpty()) {
@@ -2196,17 +2200,17 @@ DrawTargetCairo::Draw3DTransformedSurfac
   cairo_new_path(mContext);
   cairo_rectangle(mContext, xformBounds.x, xformBounds.y, xformBounds.width, xformBounds.height);
   cairo_fill(mContext);
 
   cairo_surface_destroy(xformSurf);
 
   return true;
 #else
-  return DrawTarget::Draw3DTransformedSurface(aSurface, aMatrix);
+  return DrawTarget::Draw3DTransformedSurface(aSurface, aMatrix, aEnableFilter);
 #endif
 }
 
 bool
 DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
 {
   cairo_surface_reference(aSurface);
   return InitAlreadyReferenced(aSurface, aSize, aFormat);
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -130,17 +130,18 @@ public:
                     const Pattern &aMask,
                     const DrawOptions &aOptions = DrawOptions()) override;
   virtual void MaskSurface(const Pattern &aSource,
                            SourceSurface *aMask,
                            Point aOffset,
                            const DrawOptions &aOptions = DrawOptions()) override;
 
   virtual bool Draw3DTransformedSurface(SourceSurface* aSurface,
-                                        const Matrix4x4& aMatrix) override;
+                                        const Matrix4x4& aMatrix,
+                                        const bool aEnableFilter) override;
 
   virtual void PushClip(const Path *aPath) override;
   virtual void PushClipRect(const Rect &aRect) override;
   virtual void PopClip() override;
   virtual void PushLayer(bool aOpaque, Float aOpacity,
                          SourceSurface* aMask,
                          const Matrix& aMaskTransform,
                          const IntRect& aBounds = IntRect(),
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -1522,17 +1522,19 @@ DrawTargetSkia::MaskSurface(const Patter
     gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
     return;
   }
 
   mCanvas->drawImage(alphaMask, aOffset.x, aOffset.y, &paint.mPaint);
 }
 
 bool
-DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
+DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface,
+                                     const Matrix4x4& aMatrix,
+                                     const bool aEnableFilter)
 {
   // Composite the 3D transform with the DT's transform.
   Matrix4x4 fullMat = aMatrix * Matrix4x4::From2D(mTransform);
   if (fullMat.IsSingular()) {
     return false;
   }
   // Transform the surface bounds and clip to this DT.
   IntRect xformBounds =
@@ -1569,17 +1571,18 @@ DrawTarget::Draw3DTransformedSurface(Sou
       dstSurf->GetData(), dstSurf->Stride()));
   if (!dstCanvas) {
     return false;
   }
 
   // Do the transform.
   SkPaint paint;
   paint.setAntiAlias(true);
-  paint.setFilterQuality(kLow_SkFilterQuality);
+  paint.setFilterQuality(aEnableFilter ? kLow_SkFilterQuality
+                                       : kNone_SkFilterQuality);
   paint.setBlendMode(SkBlendMode::kSrc);
 
   SkMatrix xform;
   GfxMatrixToSkiaMatrix(fullMat, xform);
   dstCanvas->setMatrix(xform);
 
   dstCanvas->drawImage(srcImage, 0, 0, &paint);
   dstCanvas->flush();
@@ -1592,34 +1595,37 @@ DrawTarget::Draw3DTransformedSurface(Sou
   DrawSurface(dstSurf, Rect(xformBounds), Rect(Point(0, 0), Size(xformBounds.Size())));
 
   SetTransform(origTransform);
 
   return true;
 }
 
 bool
-DrawTargetSkia::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& aMatrix)
+DrawTargetSkia::Draw3DTransformedSurface(SourceSurface* aSurface,
+                                         const Matrix4x4& aMatrix,
+                                         const bool aEnableFilter)
 {
   if (aMatrix.IsSingular()) {
     return false;
   }
 
   MarkChanged();
 
   sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
   if (!image) {
     return true;
   }
 
   mCanvas->save();
 
   SkPaint paint;
   paint.setAntiAlias(true);
-  paint.setFilterQuality(kLow_SkFilterQuality);
+  paint.setFilterQuality(aEnableFilter ? kLow_SkFilterQuality
+                                       : kNone_SkFilterQuality);
 
   SkMatrix xform;
   GfxMatrixToSkiaMatrix(aMatrix, xform);
   mCanvas->concat(xform);
 
   mCanvas->drawImage(image, 0, 0, &paint);
 
   mCanvas->restore();
--- a/gfx/2d/DrawTargetSkia.h
+++ b/gfx/2d/DrawTargetSkia.h
@@ -95,17 +95,18 @@ public:
   virtual void Mask(const Pattern &aSource,
                     const Pattern &aMask,
                     const DrawOptions &aOptions = DrawOptions()) override;
   virtual void MaskSurface(const Pattern &aSource,
                            SourceSurface *aMask,
                            Point aOffset,
                            const DrawOptions &aOptions = DrawOptions()) override;
   virtual bool Draw3DTransformedSurface(SourceSurface* aSurface,
-                                        const Matrix4x4& aMatrix) override;
+                                        const Matrix4x4& aMatrix,
+                                        const bool aEnableFilter) override;
   virtual void PushClip(const Path *aPath) override;
   virtual void PushClipRect(const Rect& aRect) override;
   virtual void PushDeviceSpaceClipRects(const IntRect* aRects, uint32_t aCount) override;
   virtual void PopClip() override;
   virtual void PushLayer(bool aOpaque, Float aOpacity,
                          SourceSurface* aMask,
                          const Matrix& aMaskTransform,
                          const IntRect& aBounds = IntRect(),
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -834,24 +834,25 @@ BasicCompositor::DrawGeometry(const Geom
   }
 
   if (!aTransform.Is2D()) {
     dest->Flush();
 
     RefPtr<SourceSurface> destSnapshot = dest->Snapshot();
 
     SetupMask(aEffectChain, buffer, offset, sourceMask, maskTransform);
+    const bool aEnableFilter = aEnableAA;
 
     if (sourceMask) {
       RefPtr<DrawTarget> transformDT =
         dest->CreateSimilarDrawTarget(IntSize::Truncate(transformBounds.Width(), transformBounds.Height()),
                                       SurfaceFormat::B8G8R8A8);
       new3DTransform.PostTranslate(-transformBounds.x, -transformBounds.y, 0);
       if (transformDT &&
-          transformDT->Draw3DTransformedSurface(destSnapshot, new3DTransform)) {
+          transformDT->Draw3DTransformedSurface(destSnapshot, new3DTransform, aEnableFilter)) {
         RefPtr<SourceSurface> transformSnapshot = transformDT->Snapshot();
 
         // Transform the source by it's normal transform, and then the inverse
         // of the mask transform so that it's in the mask's untransformed
         // coordinate space.
         Matrix sourceTransform = newTransform;
         sourceTransform.PostTranslate(transformBounds.TopLeft());
 
@@ -868,17 +869,17 @@ BasicCompositor::DrawGeometry(const Geom
         // by the mask transform to put the result back into destination
         // coords.
         buffer->SetTransform(maskTransform);
         buffer->MaskSurface(source, sourceMask, Point(0, 0));
 
         buffer->PopClip();
       }
     } else {
-      buffer->Draw3DTransformedSurface(destSnapshot, new3DTransform);
+      buffer->Draw3DTransformedSurface(destSnapshot, new3DTransform, aEnableFilter);
     }
   }
 
   buffer->PopClip();
 }
 
 void
 BasicCompositor::ClearRect(const gfx::Rect& aRect)
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -930,17 +930,17 @@ BasicLayerManager::PaintLayer(gfxContext
     effectiveTransform.PreTranslate(bounds.x, bounds.y, 0);
 
     RefPtr<SourceSurface> untransformedSurf = untransformedDT->Snapshot();
     RefPtr<DrawTarget> xformDT =
       untransformedDT->CreateSimilarDrawTarget(IntSize::Truncate(xformBounds.Width(), xformBounds.Height()),
                                                SurfaceFormat::B8G8R8A8);
     RefPtr<SourceSurface> xformSurf;
     if(xformDT && untransformedSurf &&
-       xformDT->Draw3DTransformedSurface(untransformedSurf, effectiveTransform)) {
+       xformDT->Draw3DTransformedSurface(untransformedSurf, effectiveTransform, true)) {
       xformSurf = xformDT->Snapshot();
     }
 
     if (xformSurf) {
       aTarget->SetPattern(
         new gfxPattern(xformSurf,
                        Matrix::Translation(xformBounds.TopLeft())));
 
--- a/layout/generic/TextDrawTarget.h
+++ b/layout/generic/TextDrawTarget.h
@@ -358,17 +358,18 @@ public:
   void MaskSurface(const Pattern &aSource,
                    SourceSurface *aMask,
                    Point aOffset,
                    const DrawOptions &aOptions) override {
     MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
   }
 
   bool Draw3DTransformedSurface(SourceSurface* aSurface,
-                                const Matrix4x4& aMatrix) override {
+                                const Matrix4x4& aMatrix,
+                                const bool aEnableFilter) override {
     MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
   }
 
   void PushClip(const Path *aPath) override {
     // Fine to pretend we do this
   }
 
   void PushClipRect(const Rect &aRect) override {
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -64,17 +64,17 @@ fuzzy-if(winWidget&&!layersGPUAccelerate
 fails-if(!layersGPUAccelerated) fails-if(webrender) == 1035611-1.html 1035611-1-ref.html # Bug 1072898 for !layersGPUAccelerated failures
 fails-if(webrender) != 1157984-1.html about:blank # Bug 1157984
 fuzzy(3,99) == animate-cube-radians.html animate-cube-radians-ref.html # subpixel AA
 fuzzy(3,99) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated,16,6) == animate-cube-radians-zoom.html animate-cube-radians-zoom-ref.html
 != animate-cube-radians-ref.html animate-cube-radians-zoom-ref.html
 fuzzy(3,99) == animate-cube-degrees.html animate-cube-degrees-ref.html # subpixel AA
 == animate-cube-degrees-zoom.html animate-cube-degrees-zoom-ref.html
 != animate-cube-degrees-ref.html animate-cube-degrees-zoom-ref.html
-fuzzy-if(gtkWidget,128,100) fuzzy-if(Android||OSX==1010||(gtkWidget&&layersGPUAccelerated),143,100) fuzzy-if(winWidget||OSX<1010,141,100) == preserves3d-nested.html preserves3d-nested-ref.html
+fuzzy(255,100) == preserves3d-nested.html preserves3d-nested-ref.html
 fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
 fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
 == animate-backface-hidden.html about:blank
 == 1245450-1.html green-rect.html
 fuzzy(1,2000) == opacity-preserve3d-1.html opacity-preserve3d-1-ref.html
 fuzzy(1,15000) == opacity-preserve3d-2.html opacity-preserve3d-2-ref.html
 fuzzy(1,10000) == opacity-preserve3d-3.html opacity-preserve3d-3-ref.html
 fuzzy(1,10000) == opacity-preserve3d-4.html opacity-preserve3d-4-ref.html
@@ -85,8 +85,9 @@ fails-if(webrender) == snap-perspective-
 fails-if(webrender) == mask-layer-3.html mask-layer-ref.html
 fails-if(webrender) == split-intersect1.html split-intersect1-ref.html
 fuzzy(255,150) fails-if(webrender) == split-intersect2.html split-intersect2-ref.html
 fuzzy(255,100) fails-if(webrender) == split-non-ortho1.html split-non-ortho1-ref.html
 fuzzy-if(winWidget,150,120) == component-alpha-1.html component-alpha-1-ref.html
 == nested-transform-1.html nested-transform-1-ref.html
 == transform-geometry-1.html transform-geometry-1-ref.html
 == intermediate-1.html intermediate-1-ref.html
+fuzzy-if(winWidget||gtkWidget,1,1) == split-seam-1.html split-seam-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/split-seam-1-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<meta charset="UTF-8">
+<style>
+
+.scene {
+  position: absolute;
+  perspective-origin: 50% 50%;
+  perspective: 1000px;
+  transform-style: preserve-3d;
+}
+
+.element {
+  position: absolute;
+  left: 100px;
+  width: 200px;
+  height: 100px;
+  background: dimgrey;
+}
+
+.top {
+  top: 100px;
+}
+
+.bottom {
+  top: 300px;
+  transform: rotateY(-1deg);
+}
+
+</style>
+</head>
+<body>
+
+<div class="scene">
+  <div class="element top"></div>
+</div>
+<div class="scene">
+  <div class="element bottom"></div>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/transform-3d/split-seam-1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<meta charset="UTF-8">
+<style>
+
+.scene {
+  position: absolute;
+  perspective-origin: 50% 50%;
+  perspective: 1000px;
+  transform-style: preserve-3d;
+}
+
+.element {
+  position: absolute;
+  left: 100px;
+  width: 200px;
+  height: 100px;
+  background: dimgrey;
+}
+
+.top {
+  top: 100px;
+}
+
+.bottom {
+  top: 300px;
+  transform: rotateY(-1deg);
+}
+
+</style>
+</head>
+<body>
+
+<div class="scene">
+  <div class="element top"></div>
+  <div class="element bottom"></div>
+</div>
+
+</body>
+</html>