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();