Tiling CSS gradients is slow
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Oct 2018 19:00:03 +0000 (19:00 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 Oct 2018 19:00:03 +0000 (19:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190615

Reviewed by Tim Horton.

Painting blocks the main thread on CG rendering queue to make a copy of the backing store.

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::drawPattern):

Also use sinkIntoImage for bitmap image pattern drawing.

* platform/graphics/GradientImage.cpp:
(WebCore::GradientImage::drawPattern):

Sink the gradient into an Image after generating it. Unlike ImageBuffer, painting it doesn't involve inefficient copies.
Previous isCompatibleWithContext test is replaced with an equivalent scale factor test.

* platform/graphics/GradientImage.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237230 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/BitmapImage.cpp
Source/WebCore/platform/graphics/GradientImage.cpp
Source/WebCore/platform/graphics/GradientImage.h

index 939c02e..abc6f5e 100644 (file)
@@ -1,3 +1,25 @@
+2018-10-17  Antti Koivisto  <antti@apple.com>
+
+        Tiling CSS gradients is slow
+        https://bugs.webkit.org/show_bug.cgi?id=190615
+
+        Reviewed by Tim Horton.
+
+        Painting blocks the main thread on CG rendering queue to make a copy of the backing store.
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::drawPattern):
+
+        Also use sinkIntoImage for bitmap image pattern drawing.
+
+        * platform/graphics/GradientImage.cpp:
+        (WebCore::GradientImage::drawPattern):
+
+        Sink the gradient into an Image after generating it. Unlike ImageBuffer, painting it doesn't involve inefficient copies.
+        Previous isCompatibleWithContext test is replaced with an equivalent scale factor test.
+
+        * platform/graphics/GradientImage.h:
+
 2018-10-17  Chris Dumez  <cdumez@apple.com>
 
         Update more DOMWindow getters to return references instead of raw pointers
index 015c0d5..52bf00e 100644 (file)
@@ -314,7 +314,7 @@ void BitmapImage::drawPattern(GraphicsContext& ctxt, const FloatRect& destRect,
         setImageObserver(observer);
         buffer->convertToLuminanceMask();
 
-        m_cachedImage = buffer->copyImage(DontCopyBackingStore, PreserveResolution::Yes);
+        m_cachedImage = ImageBuffer::sinkIntoImage(WTFMove(buffer), PreserveResolution::Yes);
         if (!m_cachedImage)
             return;
     }
index f31e5a4..8d388c6 100644 (file)
@@ -70,25 +70,29 @@ void GradientImage::drawPattern(GraphicsContext& destContext, const FloatRect& d
 
     unsigned generatorHash = m_gradient->hash();
 
-    if (!m_cachedImageBuffer || m_cachedGeneratorHash != generatorHash || m_cachedAdjustedSize != adjustedSize || !m_cachedImageBuffer->isCompatibleWithContext(destContext)) {
-        m_cachedImageBuffer = ImageBuffer::createCompatibleBuffer(adjustedSize, ColorSpaceSRGB, destContext);
-        if (!m_cachedImageBuffer)
+    if (!m_cachedImage || m_cachedGeneratorHash != generatorHash || m_cachedAdjustedSize != adjustedSize || !areEssentiallyEqual(destContext.scaleFactor(), m_cachedScaleFactor)) {
+        auto imageBuffer = ImageBuffer::createCompatibleBuffer(adjustedSize, ColorSpaceSRGB, destContext);
+        if (!imageBuffer)
             return;
 
         // Fill with the generated image.
-        m_cachedImageBuffer->context().fillRect(FloatRect(FloatPoint(), adjustedSize), m_gradient.get());
+        imageBuffer->context().fillRect(FloatRect(FloatPoint(), adjustedSize), m_gradient.get());
 
         m_cachedGeneratorHash = generatorHash;
         m_cachedAdjustedSize = adjustedSize;
+        m_cachedScaleFactor = destContext.scaleFactor();
 
         if (destContext.drawLuminanceMask())
-            m_cachedImageBuffer->convertToLuminanceMask();
+            imageBuffer->convertToLuminanceMask();
+
+        m_cachedImage = ImageBuffer::sinkIntoImage(WTFMove(imageBuffer), PreserveResolution::Yes);
     }
 
     destContext.setDrawLuminanceMask(false);
 
     // Tile the image buffer into the context.
-    m_cachedImageBuffer->drawPattern(destContext, destRect, adjustedSrcRect, adjustedPatternCTM, phase, spacing, compositeOp, blendMode);
+    m_cachedImage->drawPattern(destContext, destRect, adjustedSrcRect, adjustedPatternCTM, phase, spacing, compositeOp, blendMode);
+
 }
 
 void GradientImage::dump(WTF::TextStream& ts) const
index d3e6575..d74d578 100644 (file)
@@ -30,7 +30,7 @@
 namespace WebCore {
 
 class Gradient;
-class ImageBuffer;
+class Image;
 
 class GradientImage final : public GeneratedImage {
 public:
@@ -52,9 +52,10 @@ private:
     void dump(WTF::TextStream&) const final;
     
     Ref<Gradient> m_gradient;
-    std::unique_ptr<ImageBuffer> m_cachedImageBuffer;
+    RefPtr<Image> m_cachedImage;
     FloatSize m_cachedAdjustedSize;
     unsigned m_cachedGeneratorHash;
+    FloatSize m_cachedScaleFactor;
 };
 
 }