Title: [258051] trunk
Revision
258051
Author
[email protected]
Date
2020-03-06 19:34:24 -0800 (Fri, 06 Mar 2020)

Log Message

[GPU Process] Implement CanvasRenderingContext2D.putImageData()
https://bugs.webkit.org/show_bug.cgi?id=208621
<rdar://problem/60068047>

Reviewed by Simon Fraser.

Source/WebCore:

putImageData() is implemented just as a DisplayListItem. Conceptually, it's the
same as a draw command. Unfortunately, it can't be implemented on top of
GraphicsContext, and instead has to be implemented on top of ImageBuffer, so
this patch also adds a delegate to DisplayList::Replayer which can implement the
commands that require an ImageBuffer. This moves in the direction of making the
display list raw data, and moving the applier functions somewhere else at a
higher level.

Implementing this as a DisplayListItem rather than its own IPC message is superior
because it gives us more control about when to flush the in-flight display list.

There is still a few unnecessary copies - we're copying into / out of a SharedData
during encoding. Being able to either have the ImageBuffer retain the SharedBuffer,
or have putImageData() have an overload which accepts a SharedBuffer, would be a
good opportunity for improvement.

Test: fast/canvas/putImageData-multiple.html

* html/ImageData.cpp:
(WebCore::ImageData::deepClone const):
* html/ImageData.h:
* platform/graphics/AlphaPremultiplication.h:
* platform/graphics/GraphicsContext.h:
(WebCore::GraphicsContext::impl):
* platform/graphics/displaylists/DisplayList.h:
* platform/graphics/displaylists/DisplayListDrawingContext.cpp:
(WebCore::DisplayList::DrawingContext::recorder):
* platform/graphics/displaylists/DisplayListDrawingContext.h:
* platform/graphics/displaylists/DisplayListItems.cpp:
(WebCore::DisplayList::Item::sizeInBytes):
(WebCore::DisplayList::PutImageData::PutImageData):
(WebCore::DisplayList::PutImageData::apply const):
(WebCore::DisplayList::operator<<):
* platform/graphics/displaylists/DisplayListItems.h:
(WebCore::DisplayList::DrawingItem::globalBounds const):
(WebCore::DisplayList::PutImageData::create):
(WebCore::DisplayList::PutImageData::inputFormat const):
(WebCore::DisplayList::PutImageData::imageData const):
(WebCore::DisplayList::PutImageData::srcRect const):
(WebCore::DisplayList::PutImageData::destPoint const):
(WebCore::DisplayList::PutImageData::encode const):
(WebCore::DisplayList::PutImageData::decode):
(WebCore::DisplayList::Item::encode const):
(WebCore::DisplayList::Item::decode):
* platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::putImageData):
(WebCore::DisplayList::Recorder::updateItemExtent const):
* platform/graphics/displaylists/DisplayListRecorder.h:
* platform/graphics/displaylists/DisplayListReplayer.cpp:
(WebCore::DisplayList::Replayer::Replayer):
(WebCore::DisplayList::Replayer::replay):
* platform/graphics/displaylists/DisplayListReplayer.h:
(WebCore::DisplayList::Replayer::Delegate::~Delegate):
(WebCore::DisplayList::Replayer::Delegate::apply):

Source/WebKit:

* GPUProcess/graphics/RemoteImageBufferProxy.h:
* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<Ref<WebCore::SharedBuffer>>::encode):
(IPC::ArgumentCoder<Ref<WebCore::SharedBuffer>>::decode):
(IPC::ArgumentCoder<Ref<WebCore::ImageData>>::encode):
(IPC::ArgumentCoder<Ref<WebCore::ImageData>>::decode):
* Shared/WebCoreArgumentCoders.h:
* WebProcess/GPU/graphics/RemoteImageBuffer.h:
(WebKit::RemoteImageBuffer::putImageData):

LayoutTests:

* fast/canvas/putImageData-multiple-expected.html: Added.
* fast/canvas/putImageData-multiple.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (258050 => 258051)


--- trunk/LayoutTests/ChangeLog	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/LayoutTests/ChangeLog	2020-03-07 03:34:24 UTC (rev 258051)
@@ -1,3 +1,14 @@
+2020-03-06  Myles C. Maxfield  <[email protected]>
+
+        [GPU Process] Implement CanvasRenderingContext2D.putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=208621
+        <rdar://problem/60068047>
+
+        Reviewed by Simon Fraser.
+
+        * fast/canvas/putImageData-multiple-expected.html: Added.
+        * fast/canvas/putImageData-multiple.html: Added.
+
 2020-03-06  Daniel Bates  <[email protected]>
 
         Add support for inserting and removing a text placeholder

Added: trunk/LayoutTests/fast/canvas/putImageData-multiple-expected.html (0 => 258051)


--- trunk/LayoutTests/fast/canvas/putImageData-multiple-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/putImageData-multiple-expected.html	2020-03-07 03:34:24 UTC (rev 258051)
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+This test makes sure that putImageData() isn't affected by subsequent changes to the ImageData. The test passes if you see a green square below.
+<div style="width: 100px; height: 100px; background: rgb(0, 255, 0)"></div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/canvas/putImageData-multiple.html (0 => 258051)


--- trunk/LayoutTests/fast/canvas/putImageData-multiple.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/putImageData-multiple.html	2020-03-07 03:34:24 UTC (rev 258051)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+This test makes sure that putImageData() isn't affected by subsequent changes to the ImageData. The test passes if you see a green square below.
+<div><canvas id="canvas" width="100" height="100"></canvas></div>
+<script>
+let canvas = document.getElementById("canvas");
+let context = canvas.getContext("2d");
+let width = 100;
+let height = 100;
+let imageData = context.createImageData(width, height);
+let data = ""
+for (let i = 0; i < width * height; ++i) {
+    data[4 * i + 0] = 0;
+    data[4 * i + 1] = 255;
+    data[4 * i + 2] = 0;
+    data[4 * i + 3] = 255;
+}
+context.putImageData(imageData, 0, 0);
+for (let i = 0; i < width * height; ++i) {
+    data[4 * i + 0] = 255;
+    data[4 * i + 1] = 0;
+    data[4 * i + 2] = 0;
+    data[4 * i + 3] = 255;
+}
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (258050 => 258051)


--- trunk/Source/WebCore/ChangeLog	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/ChangeLog	2020-03-07 03:34:24 UTC (rev 258051)
@@ -1,3 +1,66 @@
+2020-03-06  Myles C. Maxfield  <[email protected]>
+
+        [GPU Process] Implement CanvasRenderingContext2D.putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=208621
+        <rdar://problem/60068047>
+
+        Reviewed by Simon Fraser.
+
+        putImageData() is implemented just as a DisplayListItem. Conceptually, it's the
+        same as a draw command. Unfortunately, it can't be implemented on top of
+        GraphicsContext, and instead has to be implemented on top of ImageBuffer, so
+        this patch also adds a delegate to DisplayList::Replayer which can implement the
+        commands that require an ImageBuffer. This moves in the direction of making the
+        display list raw data, and moving the applier functions somewhere else at a
+        higher level.
+
+        Implementing this as a DisplayListItem rather than its own IPC message is superior
+        because it gives us more control about when to flush the in-flight display list.
+
+        There is still a few unnecessary copies - we're copying into / out of a SharedData
+        during encoding. Being able to either have the ImageBuffer retain the SharedBuffer,
+        or have putImageData() have an overload which accepts a SharedBuffer, would be a
+        good opportunity for improvement.
+
+        Test: fast/canvas/putImageData-multiple.html
+
+        * html/ImageData.cpp:
+        (WebCore::ImageData::deepClone const):
+        * html/ImageData.h:
+        * platform/graphics/AlphaPremultiplication.h:
+        * platform/graphics/GraphicsContext.h:
+        (WebCore::GraphicsContext::impl):
+        * platform/graphics/displaylists/DisplayList.h:
+        * platform/graphics/displaylists/DisplayListDrawingContext.cpp:
+        (WebCore::DisplayList::DrawingContext::recorder):
+        * platform/graphics/displaylists/DisplayListDrawingContext.h:
+        * platform/graphics/displaylists/DisplayListItems.cpp:
+        (WebCore::DisplayList::Item::sizeInBytes):
+        (WebCore::DisplayList::PutImageData::PutImageData):
+        (WebCore::DisplayList::PutImageData::apply const):
+        (WebCore::DisplayList::operator<<):
+        * platform/graphics/displaylists/DisplayListItems.h:
+        (WebCore::DisplayList::DrawingItem::globalBounds const):
+        (WebCore::DisplayList::PutImageData::create):
+        (WebCore::DisplayList::PutImageData::inputFormat const):
+        (WebCore::DisplayList::PutImageData::imageData const):
+        (WebCore::DisplayList::PutImageData::srcRect const):
+        (WebCore::DisplayList::PutImageData::destPoint const):
+        (WebCore::DisplayList::PutImageData::encode const):
+        (WebCore::DisplayList::PutImageData::decode):
+        (WebCore::DisplayList::Item::encode const):
+        (WebCore::DisplayList::Item::decode):
+        * platform/graphics/displaylists/DisplayListRecorder.cpp:
+        (WebCore::DisplayList::Recorder::putImageData):
+        (WebCore::DisplayList::Recorder::updateItemExtent const):
+        * platform/graphics/displaylists/DisplayListRecorder.h:
+        * platform/graphics/displaylists/DisplayListReplayer.cpp:
+        (WebCore::DisplayList::Replayer::Replayer):
+        (WebCore::DisplayList::Replayer::replay):
+        * platform/graphics/displaylists/DisplayListReplayer.h:
+        (WebCore::DisplayList::Replayer::Delegate::~Delegate):
+        (WebCore::DisplayList::Replayer::Delegate::apply):
+
 2020-03-06  Daniel Bates  <[email protected]>
 
         Add support for inserting and removing a text placeholder

Modified: trunk/Source/WebCore/html/ImageData.cpp (258050 => 258051)


--- trunk/Source/WebCore/html/ImageData.cpp	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/html/ImageData.cpp	2020-03-07 03:34:24 UTC (rev 258051)
@@ -108,5 +108,10 @@
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION((size.area() * 4).unsafeGet() <= m_data->length());
 }
 
+Ref<ImageData> ImageData::deepClone() const
+{
+    return adoptRef(*new ImageData(m_size, Uint8ClampedArray::create(m_data->data(), m_data->length())));
 }
 
+}
+

Modified: trunk/Source/WebCore/html/ImageData.h (258050 => 258051)


--- trunk/Source/WebCore/html/ImageData.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/html/ImageData.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -47,6 +47,8 @@
 
     Uint8ClampedArray* data() const { return m_data.ptr(); }
 
+    Ref<ImageData> deepClone() const;
+
 private:
     explicit ImageData(const IntSize&);
     ImageData(const IntSize&, Ref<Uint8ClampedArray>&&);

Modified: trunk/Source/WebCore/platform/graphics/AlphaPremultiplication.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/AlphaPremultiplication.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/AlphaPremultiplication.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -34,6 +34,17 @@
     Unpremultiplied
 };
 
+
 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, AlphaPremultiplication);
 
-} // namespace WebCore
+}
+
+namespace WTF {
+template<> struct EnumTraits<WebCore::AlphaPremultiplication> {
+    using values = EnumValues<
+        WebCore::AlphaPremultiplication,
+        WebCore::AlphaPremultiplication::Premultiplied,
+        WebCore::AlphaPremultiplication::Unpremultiplied
+    >;
+};
+}

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -598,6 +598,8 @@
 
     bool supportsInternalLinks() const;
 
+    GraphicsContextImpl* impl() { return m_impl.get(); }
+
 private:
     void platformInit(PlatformGraphicsContext*);
     void platformDestroy();

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -81,6 +81,7 @@
     FillRectWithRoundedHole,
     FillPath,
     FillEllipse,
+    PutImageData,
     StrokeRect,
     StrokePath,
     StrokeEllipse,

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawingContext.cpp (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawingContext.cpp	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawingContext.cpp	2020-03-07 03:34:24 UTC (rev 258051)
@@ -46,6 +46,13 @@
     m_replayedDisplayList.reset();
 }
 
+Recorder& DrawingContext::recorder()
+{
+    auto* graphicsContextImpl = context().impl();
+    ASSERT(graphicsContextImpl);
+    return static_cast<Recorder&>(*graphicsContextImpl);
+}
+
 void DrawingContext::replayDisplayList(GraphicsContext& destContext)
 {
     if (!m_displayList.itemCount())

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawingContext.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawingContext.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawingContext.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -36,6 +36,7 @@
     WEBCORE_EXPORT DrawingContext(const FloatSize& logicalSize);
 
     GraphicsContext& context() const { return const_cast<DrawingContext&>(*this).m_context; }
+    WEBCORE_EXPORT Recorder& recorder();
     DisplayList& displayList() { return m_displayList; }
     const DisplayList& displayList() const { return m_displayList; }
     const DisplayList* replayedDisplayList() const { return m_replayedDisplayList.get(); }

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp	2020-03-07 03:34:24 UTC (rev 258051)
@@ -27,6 +27,8 @@
 #include "DisplayListItems.h"
 
 #include "FontCascade.h"
+#include "ImageData.h"
+#include "SharedBuffer.h"
 #include <wtf/text/TextStream.h>
 
 #if USE(CG)
@@ -138,6 +140,8 @@
         return sizeof(downcast<FillPath>(item));
     case ItemType::FillEllipse:
         return sizeof(downcast<FillEllipse>(item));
+    case ItemType::PutImageData:
+        return sizeof(downcast<PutImageData>(item));
     case ItemType::StrokeRect:
         return sizeof(downcast<StrokeRect>(item));
     case ItemType::StrokePath:
@@ -1147,6 +1151,42 @@
     return ts;
 }
 
+PutImageData::PutImageData(AlphaPremultiplication inputFormat, const ImageData& imageData, const IntRect& srcRect, const IntPoint& destPoint)
+    : DrawingItem(ItemType::PutImageData)
+    , m_srcRect(srcRect)
+    , m_destPoint(destPoint)
+    , m_imageData(imageData.deepClone()) // This copy is actually required to preserve the semantics of putImageData().
+    , m_inputFormat(inputFormat)
+{
+}
+
+PutImageData::PutImageData(AlphaPremultiplication inputFormat, Ref<ImageData>&& imageData, const IntRect& srcRect, const IntPoint& destPoint)
+    : DrawingItem(ItemType::PutImageData)
+    , m_srcRect(srcRect)
+    , m_destPoint(destPoint)
+    , m_imageData(WTFMove(imageData))
+    , m_inputFormat(inputFormat)
+{
+}
+
+PutImageData::~PutImageData() = default;
+
+void PutImageData::apply(GraphicsContext&) const
+{
+    // Should be handled by the delegate.
+    ASSERT_NOT_REACHED();
+}
+
+static TextStream& operator<<(TextStream& ts, const PutImageData& item)
+{
+    ts << static_cast<const DrawingItem&>(item);
+    ts.dumpProperty("inputFormat", item.inputFormat());
+    ts.dumpProperty("imageDataSize", item.imageData().size());
+    ts.dumpProperty("srcRect", item.srcRect());
+    ts.dumpProperty("destPoint", item.destPoint());
+    return ts;
+}
+
 StrokeRect::StrokeRect(const FloatRect& rect, float lineWidth)
     : DrawingItem(ItemType::StrokeRect)
     , m_rect(rect)
@@ -1375,6 +1415,7 @@
     case ItemType::FillRectWithRoundedHole: ts << "fill-rect-with-rounded-hole"; break;
     case ItemType::FillPath: ts << "fill-path"; break;
     case ItemType::FillEllipse: ts << "fill-ellipse"; break;
+    case ItemType::PutImageData: ts << "put-image-data"; break;
     case ItemType::StrokeRect: ts << "stroke-rect"; break;
     case ItemType::StrokePath: ts << "stroke-path"; break;
     case ItemType::StrokeEllipse: ts << "stroke-ellipse"; break;
@@ -1508,6 +1549,9 @@
     case ItemType::FillEllipse:
         ts << downcast<FillEllipse>(item);
         break;
+    case ItemType::PutImageData:
+        ts << downcast<PutImageData>(item);
+        break;
     case ItemType::StrokeRect:
         ts << downcast<StrokeRect>(item);
         break;

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "AlphaPremultiplication.h"
 #include "DisplayList.h"
 #include "FloatPoint.h"
 #include "FloatRoundedRect.h"
@@ -31,7 +32,9 @@
 #include "Font.h"
 #include "GlyphBuffer.h"
 #include "Image.h"
+#include "ImageData.h"
 #include "Pattern.h"
+#include "SharedBuffer.h"
 #include <wtf/RefCounted.h>
 #include <wtf/TypeCasts.h>
 
@@ -41,6 +44,7 @@
 
 namespace WebCore {
 
+class ImageData;
 struct ImagePaintingOptions;
 
 namespace DisplayList {
@@ -60,6 +64,10 @@
     // Does not include effets of transform, shadow etc in the state.
     virtual Optional<FloatRect> localBounds(const GraphicsContext&) const { return WTF::nullopt; }
 
+    // Some operations (e.g. putImageData) operate in global bounds. For these operations, override this method.
+    // If applicable, the return value needs to include the effects of shadows, clipping, etc.
+    virtual Optional<FloatRect> globalBounds() const { return WTF::nullopt; }
+
 private:
     bool isDrawingItem() const override { return true; }
 
@@ -2442,6 +2450,77 @@
     return FillEllipse::create(*rect);
 }
 
+class PutImageData : public DrawingItem {
+public:
+    static Ref<PutImageData> create(AlphaPremultiplication inputFormat, const ImageData& imageData, const IntRect& srcRect, const IntPoint& destPoint)
+    {
+        return adoptRef(*new PutImageData(inputFormat, imageData, srcRect, destPoint));
+    }
+    static Ref<PutImageData> create(AlphaPremultiplication inputFormat, Ref<ImageData>&& imageData, const IntRect& srcRect, const IntPoint& destPoint)
+    {
+        return adoptRef(*new PutImageData(inputFormat, WTFMove(imageData), srcRect, destPoint));
+    }
+
+    WEBCORE_EXPORT virtual ~PutImageData();
+
+    AlphaPremultiplication inputFormat() const { return m_inputFormat; }
+    ImageData& imageData() const { return m_imageData; }
+    IntRect srcRect() const { return m_srcRect; }
+    IntPoint destPoint() const { return m_destPoint; }
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<Ref<PutImageData>> decode(Decoder&);
+
+private:
+    WEBCORE_EXPORT PutImageData(AlphaPremultiplication inputFormat, const ImageData&, const IntRect& srcRect, const IntPoint& destPoint);
+    WEBCORE_EXPORT PutImageData(AlphaPremultiplication inputFormat, Ref<ImageData>&&, const IntRect& srcRect, const IntPoint& destPoint);
+
+    void apply(GraphicsContext&) const override;
+
+    Optional<FloatRect> globalBounds() const override { return FloatRect(m_destPoint, m_srcRect.size()); }
+
+    IntRect m_srcRect;
+    IntPoint m_destPoint;
+    Ref<ImageData> m_imageData;
+    AlphaPremultiplication m_inputFormat;
+};
+
+template<class Encoder>
+void PutImageData::encode(Encoder& encoder) const
+{
+    encoder << m_inputFormat;
+    encoder << m_imageData;
+    encoder << m_srcRect;
+    encoder << m_destPoint;
+}
+
+template<class Decoder>
+Optional<Ref<PutImageData>> PutImageData::decode(Decoder& decoder)
+{
+    Optional<AlphaPremultiplication> inputFormat;
+    Optional<Ref<ImageData>> imageData;
+    Optional<IntRect> srcRect;
+    Optional<IntPoint> destPoint;
+
+    decoder >> inputFormat;
+    if (!inputFormat)
+        return WTF::nullopt;
+
+    decoder >> imageData;
+    if (!imageData)
+        return WTF::nullopt;
+
+    decoder >> srcRect;
+    if (!srcRect)
+        return WTF::nullopt;
+
+    decoder >> destPoint;
+    if (!destPoint)
+        return WTF::nullopt;
+
+    return PutImageData::create(*inputFormat, WTFMove(*imageData), *srcRect, *destPoint);
+}
+
 class StrokeRect : public DrawingItem {
 public:
     static Ref<StrokeRect> create(const FloatRect& rect, float lineWidth)
@@ -2837,6 +2916,9 @@
     case ItemType::FillEllipse:
         encoder << downcast<FillEllipse>(*this);
         break;
+    case ItemType::PutImageData:
+        encoder << downcast<PutImageData>(*this);
+        break;
     case ItemType::StrokeRect:
         encoder << downcast<StrokeRect>(*this);
         break;
@@ -3036,6 +3118,10 @@
         if (auto item = FillEllipse::decode(decoder))
             return static_reference_cast<Item>(WTFMove(*item));
         break;
+    case ItemType::PutImageData:
+        if (auto item = PutImageData::decode(decoder))
+            return static_reference_cast<Item>(WTFMove(*item));
+        break;
     case ItemType::StrokeRect:
         if (auto item = StrokeRect::decode(decoder))
             return static_reference_cast<Item>(WTFMove(*item));
@@ -3135,6 +3221,7 @@
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillRectWithRoundedHole)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillPath)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillEllipse)
+SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(PutImageData)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokeRect)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokePath)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokeEllipse)
@@ -3194,6 +3281,7 @@
     WebCore::DisplayList::ItemType::FillRectWithRoundedHole,
     WebCore::DisplayList::ItemType::FillPath,
     WebCore::DisplayList::ItemType::FillEllipse,
+    WebCore::DisplayList::ItemType::PutImageData,
     WebCore::DisplayList::ItemType::StrokeRect,
     WebCore::DisplayList::ItemType::StrokePath,
     WebCore::DisplayList::ItemType::StrokeEllipse,

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp	2020-03-07 03:34:24 UTC (rev 258051)
@@ -50,6 +50,11 @@
     LOG(DisplayLists, "Recorded display list:\n%s", m_displayList.description().data());
 }
 
+void Recorder::putImageData(WebCore::AlphaPremultiplication inputFormat, const WebCore::ImageData& imageData, const WebCore::IntRect& srcRect, const WebCore::IntPoint& destPoint)
+{
+    appendItem(WebCore::DisplayList::PutImageData::create(inputFormat, imageData, srcRect, destPoint));
+}
+
 void Recorder::willAppendItem(const Item& item)
 {
     if (item.isDrawingItem()
@@ -395,6 +400,8 @@
 {
     if (Optional<FloatRect> rect = item.localBounds(graphicsContext()))
         item.setExtent(extentFromLocalBounds(rect.value()));
+    else if (Optional<FloatRect> rect = item.globalBounds())
+        item.setExtent(rect.value());
 }
 
 // FIXME: share with ShadowData

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -33,6 +33,7 @@
 
 namespace WebCore {
 
+enum class AlphaPremultiplication : uint8_t;
 class FloatPoint;
 class FloatRect;
 class GlyphBuffer;
@@ -39,6 +40,7 @@
 class FloatPoint;
 class Font;
 class Image;
+class ImageData;
 
 struct GraphicsContextState;
 struct ImagePaintingOptions;
@@ -54,6 +56,8 @@
     WEBCORE_EXPORT Recorder(GraphicsContext&, DisplayList&, const GraphicsContextState&, const FloatRect& initialClip, const AffineTransform&);
     WEBCORE_EXPORT virtual ~Recorder();
 
+    WEBCORE_EXPORT void putImageData(AlphaPremultiplication inputFormat, const ImageData&, const IntRect& srcRect, const IntPoint& destPoint);
+
     size_t itemCount() const { return m_displayList.itemCount(); }
 
 private:
@@ -124,7 +128,7 @@
     void clipOut(const Path&) override;
     void clipPath(const Path&, WindRule) override;
     IntRect clipBounds() override;
-    void clipToImageBuffer(ImageBuffer&, const FloatRect&) override;
+    void clipToImageBuffer(WebCore::ImageBuffer&, const FloatRect&) override;
     
     void applyDeviceScaleFactor(float) override;
 

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp	2020-03-07 03:34:24 UTC (rev 258051)
@@ -35,9 +35,10 @@
 namespace WebCore {
 namespace DisplayList {
 
-Replayer::Replayer(GraphicsContext& context, const DisplayList& displayList)
+Replayer::Replayer(GraphicsContext& context, const DisplayList& displayList, Delegate* delegate)
     : m_displayList(displayList)
     , m_context(context)
+    , m_delegate(delegate)
 {
 }
 
@@ -66,7 +67,8 @@
         }
 
         LOG_WITH_STREAM(DisplayLists, stream << "applying " << i << " " << item);
-        item.apply(m_context);
+        if (!m_delegate || !m_delegate->apply(item, m_context))
+            item.apply(m_context);
 
         if (UNLIKELY(trackReplayList))
             replayList->appendItem(const_cast<Item&>(item));

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h (258050 => 258051)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -31,8 +31,10 @@
 
 namespace WebCore {
 
+enum class AlphaPremultiplication : uint8_t;
 class FloatRect;
 class GraphicsContext;
+class ImageData;
 
 namespace DisplayList {
 
@@ -39,14 +41,22 @@
 class Replayer {
     WTF_MAKE_NONCOPYABLE(Replayer);
 public:
-    WEBCORE_EXPORT Replayer(GraphicsContext&, const DisplayList&);
+    class Delegate;
+    WEBCORE_EXPORT Replayer(GraphicsContext&, const DisplayList&, Delegate* = nullptr);
     WEBCORE_EXPORT ~Replayer();
 
     WEBCORE_EXPORT std::unique_ptr<DisplayList> replay(const FloatRect& initialClip = { }, bool trackReplayList = false);
+
+    class Delegate {
+    public:
+        virtual ~Delegate() { }
+        virtual bool apply(Item&, GraphicsContext&) { return false; }
+    };
     
 private:
     const DisplayList& m_displayList;
     GraphicsContext& m_context;
+    Delegate* m_delegate;
 };
 
 }

Modified: trunk/Source/WebKit/ChangeLog (258050 => 258051)


--- trunk/Source/WebKit/ChangeLog	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebKit/ChangeLog	2020-03-07 03:34:24 UTC (rev 258051)
@@ -1,3 +1,21 @@
+2020-03-06  Myles C. Maxfield  <[email protected]>
+
+        [GPU Process] Implement CanvasRenderingContext2D.putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=208621
+        <rdar://problem/60068047>
+
+        Reviewed by Simon Fraser.
+
+        * GPUProcess/graphics/RemoteImageBufferProxy.h:
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<Ref<WebCore::SharedBuffer>>::encode):
+        (IPC::ArgumentCoder<Ref<WebCore::SharedBuffer>>::decode):
+        (IPC::ArgumentCoder<Ref<WebCore::ImageData>>::encode):
+        (IPC::ArgumentCoder<Ref<WebCore::ImageData>>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+        * WebProcess/GPU/graphics/RemoteImageBuffer.h:
+        (WebKit::RemoteImageBuffer::putImageData):
+
 2020-03-06  Daniel Bates  <[email protected]>
 
         Add support for inserting and removing a text placeholder

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferProxy.h (258050 => 258051)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferProxy.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferProxy.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -34,7 +34,7 @@
 namespace WebKit {
 
 template<typename BackendType>
-class RemoteImageBufferProxy : public WebCore::ConcreteImageBuffer<BackendType>, public RemoteImageBufferMessageHandlerProxy {
+class RemoteImageBufferProxy : public WebCore::ConcreteImageBuffer<BackendType>, public RemoteImageBufferMessageHandlerProxy, public DisplayList::Replayer::Delegate {
     using BaseConcreteImageBuffer = WebCore::ConcreteImageBuffer<BackendType>;
     using BaseConcreteImageBuffer::m_backend;
 
@@ -53,16 +53,27 @@
 
 private:
     using BaseConcreteImageBuffer::flushDrawingContext;
+    using BaseConcreteImageBuffer::putImageData;
 
     void flushDrawingContext(const WebCore::DisplayList::DisplayList& displayList, ImageBufferFlushIdentifier flushIdentifier) override
     {
         if (displayList.itemCount()) {
-            WebCore::DisplayList::Replayer replayer(BaseConcreteImageBuffer::context(), displayList);
+            WebCore::DisplayList::Replayer replayer(BaseConcreteImageBuffer::context(), displayList, this);
             replayer.replay();
         }
         m_backend->flushContext();
         commitFlushContext(flushIdentifier);
     }
+
+    bool apply(DisplayList::Item& item, GraphicsContext&) override
+    {
+        if (item.type() != DisplayList::ItemType::PutImageData)
+            return false;
+
+        auto& putImageDataItem = static_cast<DisplayList::PutImageData&>(item);
+        putImageData(putImageDataItem.inputFormat(), putImageDataItem.imageData(), putImageDataItem.srcRect(), putImageDataItem.destPoint());
+        return true;
+    }
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (258050 => 258051)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2020-03-07 03:34:24 UTC (rev 258051)
@@ -29,6 +29,8 @@
 #include "DataReference.h"
 #include "ShareableBitmap.h"
 #include "SharedBufferDataReference.h"
+#include <_javascript_Core/GenericTypedArrayViewInlines.h>
+#include <_javascript_Core/JSGenericTypedArrayViewInlines.h>
 #include <WebCore/AuthenticationChallenge.h>
 #include <WebCore/BlobPart.h>
 #include <WebCore/CacheQueryOptions.h>
@@ -3241,6 +3243,20 @@
     return buffer;
 }
 
+void ArgumentCoder<Ref<WebCore::SharedBuffer>>::encode(Encoder& encoder, const Ref<WebCore::SharedBuffer>& buffer)
+{
+    encodeSharedBuffer(encoder, buffer.ptr());
+}
+
+Optional<Ref<SharedBuffer>> ArgumentCoder<Ref<WebCore::SharedBuffer>>::decode(Decoder& decoder)
+{
+    RefPtr<SharedBuffer> buffer;
+    if (!decodeSharedBuffer(decoder, buffer) || !buffer)
+        return WTF::nullopt;
+
+    return buffer.releaseNonNull();
+}
+
 #if ENABLE(ENCRYPTED_MEDIA)
 void ArgumentCoder<WebCore::CDMInstanceSession::Message>::encode(Encoder& encoder, const WebCore::CDMInstanceSession::Message& message)
 {
@@ -3296,4 +3312,34 @@
 }
 #endif // ENABLE(ENCRYPTED_MEDIA)
 
+void ArgumentCoder<Ref<WebCore::ImageData>>::encode(Encoder& encoder, const Ref<WebCore::ImageData>& imageData)
+{
+    // FIXME: Copying from the ImageData to the SharedBuffer is slow. Invent some way for the SharedBuffer to be populated directly.
+    auto sharedBuffer = WebCore::SharedBuffer::create(imageData->data()->data(), imageData->data()->byteLength());
+    encoder << imageData->size();
+    encoder << sharedBuffer;
+}
+
+Optional<Ref<WebCore::ImageData>> ArgumentCoder<Ref<WebCore::ImageData>>::decode(Decoder& decoder)
+{
+    Optional<IntSize> imageDataSize;
+    Optional<Ref<SharedBuffer>> data;
+
+    decoder >> imageDataSize;
+    if (!imageDataSize)
+        return WTF::nullopt;
+
+    decoder >> data;
+    if (!data)
+        return WTF::nullopt;
+
+    // FIXME: Copying from the SharedBuffer into the ImageData is slow. Invent some way for the ImageData to simply just retain the SharedBuffer, and use it internally.
+    // Alternatively, we could create an overload for putImageData() which operates on the SharedBuffer directly.
+    auto imageData = ImageData::create(*imageDataSize, Uint8ClampedArray::create(reinterpret_cast<const uint8_t*>((*data)->data()), (*data)->size()));
+    if (!imageData)
+        return WTF::nullopt;
+
+    return { imageData.releaseNonNull() };
+}
+
 } // namespace IPC

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h (258050 => 258051)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -30,6 +30,7 @@
 #include <WebCore/ColorSpace.h>
 #include <WebCore/DiagnosticLoggingClient.h>
 #include <WebCore/FrameLoaderTypes.h>
+#include <WebCore/ImageData.h>
 #include <WebCore/IndexedDB.h>
 #include <WebCore/InputMode.h>
 #include <WebCore/MediaSelectionOption.h>
@@ -841,6 +842,11 @@
     static Optional<RefPtr<WebCore::SharedBuffer>> decode(Decoder&);
 };
 
+template<> struct ArgumentCoder<Ref<WebCore::SharedBuffer>> {
+    static void encode(Encoder&, const Ref<WebCore::SharedBuffer>&);
+    static Optional<Ref<WebCore::SharedBuffer>> decode(Decoder&);
+};
+
 #if ENABLE(ENCRYPTED_MEDIA)
 template<> struct ArgumentCoder<WebCore::CDMInstanceSession::Message> {
     static void encode(Encoder&, const WebCore::CDMInstanceSession::Message&);
@@ -853,6 +859,11 @@
 };
 #endif
 
+template<> struct ArgumentCoder<Ref<WebCore::ImageData>> {
+    static void encode(Encoder&, const Ref<WebCore::ImageData>&);
+    static Optional<Ref<WebCore::ImageData>> decode(Decoder&);
+};
+
 } // namespace IPC
 
 namespace WTF {

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBuffer.h (258050 => 258051)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBuffer.h	2020-03-07 03:04:32 UTC (rev 258050)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBuffer.h	2020-03-07 03:34:24 UTC (rev 258051)
@@ -30,6 +30,7 @@
 #include "RemoteImageBufferMessageHandler.h"
 #include <WebCore/DisplayListImageBuffer.h>
 #include <WebCore/DisplayListItems.h>
+#include <WebCore/DisplayListRecorder.h>
 
 namespace WebKit {
 
@@ -72,6 +73,14 @@
         return m_backend.get();
     }
 
+    void putImageData(WebCore::AlphaPremultiplication inputFormat, const WebCore::ImageData& imageData, const WebCore::IntRect& srcRect, const WebCore::IntPoint& destPoint = { }) override
+    {
+        // The math inside ImageData::create() doesn't agree with the math inside ImageBufferBackend::putImageData() about how m_resolutionScale interacts with the data in the ImageBuffer.
+        // This means that putImageData() is only called when m_resolutionScale == 1.
+        ASSERT(m_backend->resolutionScale() == 1);
+        m_drawingContext.recorder().putImageData(inputFormat, imageData, srcRect, destPoint);
+    }
+
     void flushContext() override
     {
         flushDrawingContext();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to