Title: [268145] trunk/Source
Revision
268145
Author
wenson_hs...@apple.com
Date
2020-10-07 13:13:24 -0700 (Wed, 07 Oct 2020)

Log Message

[GPU Process] Support CanvasRenderingContext2D.drawImage() with HTMLVideoElement
https://bugs.webkit.org/show_bug.cgi?id=217339
<rdar://problem/69409029>

Reviewed by Darin Adler.

Source/WebCore:

Implements support for painting the current video frame into a canvas 2D graphics context. See below for more
details.

* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::paintCurrentFrameInContext):

Flip this around to call `GraphicsContext::paintFrameForMedia` with the `MediaPlayer`, instead of calling into
`MediaPlayer` with the graphics context. See changes below.

* platform/graphics/GraphicsContext.cpp:
(WebCore::GraphicsContext::paintFrameForMedia):
* platform/graphics/GraphicsContext.h:

Add a `paintFrameForMedia` method that takes a `MediaPlayer` representing a video, and paints the current frame
of the video into the context. If the graphics context is backed by an platform context (i.e. `m_impl` is
`nullptr`), then we simply call through to `MediaPlayer`'s private impl to paint into the context. Otherwise, we
forward the call to the `GraphicsContextImpl` (see the changes to `DisplayListRecorder.cpp` below).

* platform/graphics/GraphicsContextImpl.h:

Add a new virtual function to paint the current frame of the given `MediaPlayer` into the destination rect.

* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::playerPrivate const):
(WebCore::MediaPlayer::playerPrivate):
(WebCore::MediaPlayer::paintCurrentFrameInContext): Deleted.
* platform/graphics/MediaPlayer.h:

Remove the existing `paintCurrentFrameInContext` method on `MediaPlayer`, which currently takes a graphics
context. Instead, move `paintCurrentFrameInContext` to `GraphicsContext`, rename it to `paintFrameForMedia`, and
pass it a `MediaPlayer`. Additionally, expose a helper method to get a non-const `MediaPlayerPrivateInterface`,
and move both method definitions to the implementation file to avoid style checker errors due to `MediaPlayer`
itself being `WEBCORE_EXPORT`-ed.

* platform/graphics/cairo/GraphicsContextImplCairo.cpp:
(WebCore::GraphicsContextImplCairo::paintFrameForMedia):
* platform/graphics/cairo/GraphicsContextImplCairo.h:
* platform/graphics/displaylists/DisplayList.h:
* platform/graphics/displaylists/DisplayListItems.cpp:
(WebCore::DisplayList::Item::sizeInBytes):
(WebCore::DisplayList::PaintFrameForMedia::create):
(WebCore::DisplayList::PaintFrameForMedia::PaintFrameForMedia):
(WebCore::DisplayList::PaintFrameForMedia::apply const):
(WebCore::DisplayList::operator<<):
* platform/graphics/displaylists/DisplayListItems.h:
(WebCore::DisplayList::PaintFrameForMedia::destination const):
(WebCore::DisplayList::PaintFrameForMedia::identifier const):
(WebCore::DisplayList::PaintFrameForMedia::encode const):
(WebCore::DisplayList::PaintFrameForMedia::decode):
(WebCore::DisplayList::Item::encode const):
(WebCore::DisplayList::Item::decode):
* platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::paintFrameForMedia):
* platform/graphics/displaylists/DisplayListRecorder.h:

Add a new display list item, `PaintFrameForMedia`, that paints the current frame of a given `MediaPlayer`. This
works by serializing and then deserializing a `MediaPlayerHandle` and destination rect; similar to
`PutImageData`, the replayer delegate is responsible for applying this item by mapping the `MediaPlayerHandle`
to a concrete `MediaPlayer` instance.

* platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp:
(Nicosia::CairoOperationRecorder::paintFrameForMedia):
* platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h:
* platform/graphics/win/GraphicsContextImplDirect2D.cpp:
(WebCore::GraphicsContextImplDirect2D::paintFrameForMedia):
* platform/graphics/win/GraphicsContextImplDirect2D.h:
* rendering/RenderVideo.cpp:
(WebCore::RenderVideo::paintReplaced):

Source/WebKit:

Implements support for painting the current video frame into a canvas 2D graphics context. See below (and
Source/WebCore/ChangeLog) for more details.

* GPUProcess/graphics/RemoteImageBufferMessageHandlerProxy.h:
(WebKit::RemoteImageBufferMessageHandlerProxy::backend):
* GPUProcess/graphics/RemoteImageBufferProxy.h:
(WebKit::RemoteImageBufferProxy::apply):

Refactor `apply` so that it treats `PutImageData` and `PaintFrameForMedia` as special cases, and otherwise
returns `false` by default. Implement `apply` in the case where the display list item is `PaintFrameForMedia` by
using the `MediaPlayerIdentifier` to look up the platform `MediaPlayer` instance, and then calling
`GraphicsContext::paintFrameForMedia` with this `MediaPlayer`.

* GPUProcess/graphics/RemoteRenderingBackendProxy.cpp:
(WebKit::RemoteRenderingBackendProxy::gpuConnectionToWebProcess const):
* GPUProcess/graphics/RemoteRenderingBackendProxy.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (268144 => 268145)


--- trunk/Source/WebCore/ChangeLog	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/ChangeLog	2020-10-07 20:13:24 UTC (rev 268145)
@@ -1,3 +1,80 @@
+2020-10-07  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [GPU Process] Support CanvasRenderingContext2D.drawImage() with HTMLVideoElement
+        https://bugs.webkit.org/show_bug.cgi?id=217339
+        <rdar://problem/69409029>
+
+        Reviewed by Darin Adler.
+
+        Implements support for painting the current video frame into a canvas 2D graphics context. See below for more
+        details.
+
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::paintCurrentFrameInContext):
+
+        Flip this around to call `GraphicsContext::paintFrameForMedia` with the `MediaPlayer`, instead of calling into
+        `MediaPlayer` with the graphics context. See changes below.
+
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::paintFrameForMedia):
+        * platform/graphics/GraphicsContext.h:
+
+        Add a `paintFrameForMedia` method that takes a `MediaPlayer` representing a video, and paints the current frame
+        of the video into the context. If the graphics context is backed by an platform context (i.e. `m_impl` is
+        `nullptr`), then we simply call through to `MediaPlayer`'s private impl to paint into the context. Otherwise, we
+        forward the call to the `GraphicsContextImpl` (see the changes to `DisplayListRecorder.cpp` below).
+
+        * platform/graphics/GraphicsContextImpl.h:
+
+        Add a new virtual function to paint the current frame of the given `MediaPlayer` into the destination rect.
+
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::playerPrivate const):
+        (WebCore::MediaPlayer::playerPrivate):
+        (WebCore::MediaPlayer::paintCurrentFrameInContext): Deleted.
+        * platform/graphics/MediaPlayer.h:
+
+        Remove the existing `paintCurrentFrameInContext` method on `MediaPlayer`, which currently takes a graphics
+        context. Instead, move `paintCurrentFrameInContext` to `GraphicsContext`, rename it to `paintFrameForMedia`, and
+        pass it a `MediaPlayer`. Additionally, expose a helper method to get a non-const `MediaPlayerPrivateInterface`,
+        and move both method definitions to the implementation file to avoid style checker errors due to `MediaPlayer`
+        itself being `WEBCORE_EXPORT`-ed.
+
+        * platform/graphics/cairo/GraphicsContextImplCairo.cpp:
+        (WebCore::GraphicsContextImplCairo::paintFrameForMedia):
+        * platform/graphics/cairo/GraphicsContextImplCairo.h:
+        * platform/graphics/displaylists/DisplayList.h:
+        * platform/graphics/displaylists/DisplayListItems.cpp:
+        (WebCore::DisplayList::Item::sizeInBytes):
+        (WebCore::DisplayList::PaintFrameForMedia::create):
+        (WebCore::DisplayList::PaintFrameForMedia::PaintFrameForMedia):
+        (WebCore::DisplayList::PaintFrameForMedia::apply const):
+        (WebCore::DisplayList::operator<<):
+        * platform/graphics/displaylists/DisplayListItems.h:
+        (WebCore::DisplayList::PaintFrameForMedia::destination const):
+        (WebCore::DisplayList::PaintFrameForMedia::identifier const):
+        (WebCore::DisplayList::PaintFrameForMedia::encode const):
+        (WebCore::DisplayList::PaintFrameForMedia::decode):
+        (WebCore::DisplayList::Item::encode const):
+        (WebCore::DisplayList::Item::decode):
+        * platform/graphics/displaylists/DisplayListRecorder.cpp:
+        (WebCore::DisplayList::Recorder::paintFrameForMedia):
+        * platform/graphics/displaylists/DisplayListRecorder.h:
+
+        Add a new display list item, `PaintFrameForMedia`, that paints the current frame of a given `MediaPlayer`. This
+        works by serializing and then deserializing a `MediaPlayerHandle` and destination rect; similar to
+        `PutImageData`, the replayer delegate is responsible for applying this item by mapping the `MediaPlayerHandle`
+        to a concrete `MediaPlayer` instance.
+
+        * platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp:
+        (Nicosia::CairoOperationRecorder::paintFrameForMedia):
+        * platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h:
+        * platform/graphics/win/GraphicsContextImplDirect2D.cpp:
+        (WebCore::GraphicsContextImplDirect2D::paintFrameForMedia):
+        * platform/graphics/win/GraphicsContextImplDirect2D.h:
+        * rendering/RenderVideo.cpp:
+        (WebCore::RenderVideo::paintReplaced):
+
 2020-10-07  Aditya Keerthi  <akeer...@apple.com>
 
         [Contact Picker API] Add support for ContactsManager.getProperties()

Modified: trunk/Source/WebCore/html/HTMLVideoElement.cpp (268144 => 268145)


--- trunk/Source/WebCore/html/HTMLVideoElement.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/html/HTMLVideoElement.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -297,7 +297,7 @@
         return;
     
     player->setVisible(true); // Make player visible or it won't draw.
-    player->paintCurrentFrameInContext(context, destRect);
+    context.paintFrameForMedia(*player, destRect);
 }
 
 bool HTMLVideoElement::copyVideoTextureToPlatformTexture(GraphicsContextGLOpenGL* context, PlatformGLObject texture, GCGLenum target, GCGLint level, GCGLenum internalFormat, GCGLenum format, GCGLenum type, bool premultiplyAlpha, bool flipY)

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -33,6 +33,8 @@
 #include "GraphicsContextImpl.h"
 #include "ImageBuffer.h"
 #include "IntRect.h"
+#include "MediaPlayer.h"
+#include "MediaPlayerPrivate.h"
 #include "RoundedRect.h"
 #include "TextRun.h"
 #include <wtf/text/TextStream.h>
@@ -1239,6 +1241,7 @@
 }
 
 #if !USE(CG)
+
 bool GraphicsContext::supportsInternalLinks() const
 {
     return false;
@@ -1251,6 +1254,20 @@
 void GraphicsContext::addDestinationAtPoint(const String&, const FloatPoint&)
 {
 }
+
 #endif
 
+void GraphicsContext::paintFrameForMedia(MediaPlayer& player, const FloatRect& destination)
+{
+    if (paintingDisabled())
+        return;
+
+    if (m_impl && m_impl->canPaintFrameForMedia()) {
+        m_impl->paintFrameForMedia(player, destination);
+        return;
+    }
+
+    player.playerPrivate()->paintCurrentFrameInContext(*this, destination);
 }
+
+}

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.h (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -92,6 +92,7 @@
 class GraphicsContextPlatformPrivate;
 class ImageBuffer;
 class IntRect;
+class MediaPlayer;
 class RoundedRect;
 class GraphicsContextGLOpenGL;
 class Path;
@@ -516,6 +517,8 @@
     void setContentfulPaintDetected() { m_contenfulPaintDetected = true; }
     bool contenfulPaintDetected() const { return m_contenfulPaintDetected; }
 
+    WEBCORE_EXPORT void paintFrameForMedia(MediaPlayer&, const FloatRect& destination);
+
 #if OS(WINDOWS)
     HDC getWindowsContext(const IntRect&, bool supportAlphaBlend); // The passed in rect is used to create a bitmap for compositing inside transparency layers.
     void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend); // The passed in HDC should be the one handed back by getWindowsContext.

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContextImpl.h (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/GraphicsContextImpl.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContextImpl.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -107,6 +107,8 @@
     virtual IntRect clipBounds() = 0;
     virtual void clipToImageBuffer(ImageBuffer&, const FloatRect&) = 0;
     virtual void clipToDrawingCommands(const FloatRect& destination, ColorSpace, Function<void(GraphicsContext&)>&& drawingFunction) = 0;
+    virtual void paintFrameForMedia(MediaPlayer&, const FloatRect& destination) = 0;
+    virtual bool canPaintFrameForMedia() const = 0;
     
     virtual void applyDeviceScaleFactor(float) = 0;
 

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -31,6 +31,7 @@
 #include "ContentType.h"
 #include "DeprecatedGlobalSettings.h"
 #include "Document.h"
+#include "GraphicsContext.h"
 #include "IntRect.h"
 #include "Logging.h"
 #include "MIMETypeRegistry.h"
@@ -304,6 +305,16 @@
     return textPlain;
 }
 
+const MediaPlayerPrivateInterface* MediaPlayer::playerPrivate() const
+{
+    return m_private.get();
+}
+
+MediaPlayerPrivateInterface* MediaPlayer::playerPrivate()
+{
+    return m_private.get();
+}
+
 const MediaPlayerFactory* MediaPlayer::mediaEngine(MediaPlayerEnums::MediaEngineIdentifier identifier)
 {
     auto& engines = installedMediaEngines();
@@ -967,11 +978,6 @@
     m_private->paint(p, r);
 }
 
-void MediaPlayer::paintCurrentFrameInContext(GraphicsContext& p, const FloatRect& r)
-{
-    m_private->paintCurrentFrameInContext(p, r);
-}
-
 bool MediaPlayer::copyVideoTextureToPlatformTexture(GraphicsContextGLOpenGL* context, PlatformGLObject texture, GCGLenum target, GCGLint level, GCGLenum internalFormat, GCGLenum format, GCGLenum type, bool premultiplyAlpha, bool flipY)
 {
     return m_private->copyVideoTextureToPlatformTexture(context, texture, target, level, internalFormat, format, type, premultiplyAlpha, flipY);

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -422,7 +422,6 @@
     void setClosedCaptionsVisible(bool closedCaptionsVisible);
 
     void paint(GraphicsContext&, const FloatRect&);
-    void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&);
 
     // copyVideoTextureToPlatformTexture() is used to do the GPU-GPU textures copy without a readback to system memory.
     // The first five parameters denote the corresponding GraphicsContext, destination texture, requested level, requested type and the required internalFormat for destination texture.
@@ -630,7 +629,8 @@
     void requestInstallMissingPlugins(const String& details, const String& description, MediaPlayerRequestInstallMissingPluginsCallback& callback) { client().requestInstallMissingPlugins(details, description, callback); }
 #endif
 
-    const MediaPlayerPrivateInterface* playerPrivate() const { return m_private.get(); }
+    const MediaPlayerPrivateInterface* playerPrivate() const;
+    MediaPlayerPrivateInterface* playerPrivate();
 
     DynamicRangeMode preferredDynamicRangeMode() const { return m_preferredDynamicRangeMode; }
     void setPreferredDynamicRangeMode(DynamicRangeMode);

Modified: trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextImplCairo.cpp (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextImplCairo.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextImplCairo.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -432,6 +432,11 @@
     // FIXME: Not implemented.
 }
 
+void GraphicsContextImplCairo::paintFrameForMedia(MediaPlayer&, const FloatRect&)
+{
+    // FIXME: Not implemented.
+}
+
 } // namespace WebCore
 
 #endif // USE(CAIRO)

Modified: trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextImplCairo.h (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextImplCairo.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextImplCairo.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -107,6 +107,8 @@
     IntRect clipBounds() override;
     void clipToImageBuffer(ImageBuffer&, const FloatRect&) override;
     void clipToDrawingCommands(const FloatRect& destination, ColorSpace, Function<void(GraphicsContext&)>&&) override;
+    void paintFrameForMedia(MediaPlayer&, const FloatRect& destination) override;
+    bool canPaintFrameForMedia() const override { return false; }
     
     void applyDeviceScaleFactor(float) override;
 

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


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -83,6 +83,7 @@
     FillPath,
     FillEllipse,
     PutImageData,
+    PaintFrameForMedia,
     StrokeRect,
     StrokePath,
     StrokeEllipse,

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


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -29,6 +29,7 @@
 #include "DisplayListReplayer.h"
 #include "FontCascade.h"
 #include "ImageData.h"
+#include "MediaPlayer.h"
 #include "SharedBuffer.h"
 #include <wtf/text/TextStream.h>
 
@@ -145,6 +146,8 @@
         return sizeof(downcast<FillEllipse>(item));
     case ItemType::PutImageData:
         return sizeof(downcast<PutImageData>(item));
+    case ItemType::PaintFrameForMedia:
+        return sizeof(downcast<PaintFrameForMedia>(item));
     case ItemType::StrokeRect:
         return sizeof(downcast<StrokeRect>(item));
     case ItemType::StrokePath:
@@ -1218,6 +1221,45 @@
     return ts;
 }
 
+Ref<PaintFrameForMedia> PaintFrameForMedia::create(MediaPlayer& player, const FloatRect& destination)
+{
+    return adoptRef(*new PaintFrameForMedia(player, destination));
+}
+
+Ref<PaintFrameForMedia> PaintFrameForMedia::create(MediaPlayerIdentifier identifier, const FloatRect& destination)
+{
+    return adoptRef(*new PaintFrameForMedia(identifier, destination));
+}
+
+PaintFrameForMedia::PaintFrameForMedia(MediaPlayer& player, const FloatRect& destination)
+    : DrawingItem(ItemType::PaintFrameForMedia)
+    , m_identifier(player.identifier())
+    , m_destination(destination)
+{
+}
+
+PaintFrameForMedia::PaintFrameForMedia(MediaPlayerIdentifier identifier, const FloatRect& destination)
+    : DrawingItem(ItemType::PaintFrameForMedia)
+    , m_identifier(identifier)
+    , m_destination(destination)
+{
+}
+
+PaintFrameForMedia::~PaintFrameForMedia() = default;
+
+void PaintFrameForMedia::apply(GraphicsContext&) const
+{
+    // Should be handled by the delegate.
+    ASSERT_NOT_REACHED();
+}
+
+static TextStream& operator<<(TextStream& ts, const PaintFrameForMedia& item)
+{
+    ts << static_cast<const DrawingItem&>(item);
+    ts.dumpProperty("destination", item.destination());
+    return ts;
+}
+
 StrokeRect::StrokeRect(const FloatRect& rect, float lineWidth)
     : DrawingItem(ItemType::StrokeRect)
     , m_rect(rect)
@@ -1448,6 +1490,7 @@
     case ItemType::FillPath: ts << "fill-path"; break;
     case ItemType::FillEllipse: ts << "fill-ellipse"; break;
     case ItemType::PutImageData: ts << "put-image-data"; break;
+    case ItemType::PaintFrameForMedia: ts << "paint-frame-for-media"; break;
     case ItemType::StrokeRect: ts << "stroke-rect"; break;
     case ItemType::StrokePath: ts << "stroke-path"; break;
     case ItemType::StrokeEllipse: ts << "stroke-ellipse"; break;
@@ -1587,6 +1630,9 @@
     case ItemType::PutImageData:
         ts << downcast<PutImageData>(item);
         break;
+    case ItemType::PaintFrameForMedia:
+        ts << downcast<PaintFrameForMedia>(item);
+        break;
     case ItemType::StrokeRect:
         ts << downcast<StrokeRect>(item);
         break;

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


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -33,6 +33,7 @@
 #include "Gradient.h"
 #include "Image.h"
 #include "ImageData.h"
+#include "MediaPlayerIdentifier.h"
 #include "Pattern.h"
 #include "SharedBuffer.h"
 #include <wtf/TypeCasts.h>
@@ -44,6 +45,7 @@
 namespace WebCore {
 
 class ImageData;
+class MediaPlayer;
 struct ImagePaintingOptions;
 
 namespace DisplayList {
@@ -2582,6 +2584,53 @@
     return PutImageData::create(*inputFormat, WTFMove(*imageData), *srcRect, *destPoint, *destFormat);
 }
 
+class PaintFrameForMedia : public DrawingItem {
+public:
+    static Ref<PaintFrameForMedia> create(MediaPlayer&, const FloatRect& destination);
+
+    WEBCORE_EXPORT virtual ~PaintFrameForMedia();
+
+    const FloatRect& destination() const { return m_destination; }
+    MediaPlayerIdentifier identifier() const { return m_identifier; }
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<Ref<PaintFrameForMedia>> decode(Decoder&);
+
+private:
+    WEBCORE_EXPORT static Ref<PaintFrameForMedia> create(MediaPlayerIdentifier, const FloatRect& destination);
+
+    PaintFrameForMedia(MediaPlayer&, const FloatRect& destination);
+    PaintFrameForMedia(MediaPlayerIdentifier, const FloatRect& destination);
+
+    void apply(GraphicsContext&) const override;
+
+    MediaPlayerIdentifier m_identifier;
+    FloatRect m_destination;
+};
+
+template<class Encoder>
+void PaintFrameForMedia::encode(Encoder& encoder) const
+{
+    encoder << m_identifier;
+    encoder << m_destination;
+}
+
+template<class Decoder>
+Optional<Ref<PaintFrameForMedia>> PaintFrameForMedia::decode(Decoder& decoder)
+{
+    Optional<MediaPlayerIdentifier> identifier;
+    decoder >> identifier;
+    if (!identifier)
+        return WTF::nullopt;
+
+    Optional<FloatRect> destination;
+    decoder >> destination;
+    if (!destination)
+        return WTF::nullopt;
+
+    return PaintFrameForMedia::create(*identifier, *destination);
+}
+
 class StrokeRect : public DrawingItem {
 public:
     static Ref<StrokeRect> create(const FloatRect& rect, float lineWidth)
@@ -2983,6 +3032,9 @@
     case ItemType::PutImageData:
         encoder << downcast<PutImageData>(*this);
         break;
+    case ItemType::PaintFrameForMedia:
+        encoder << downcast<PaintFrameForMedia>(*this);
+        break;
     case ItemType::StrokeRect:
         encoder << downcast<StrokeRect>(*this);
         break;
@@ -3190,6 +3242,10 @@
         if (auto item = PutImageData::decode(decoder))
             return static_reference_cast<Item>(WTFMove(*item));
         break;
+    case ItemType::PaintFrameForMedia:
+        if (auto item = PaintFrameForMedia::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));
@@ -3291,6 +3347,7 @@
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillPath)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(FillEllipse)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(PutImageData)
+SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(PaintFrameForMedia)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokeRect)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokePath)
 SPECIALIZE_TYPE_TRAITS_DISPLAYLIST_ITEM(StrokeEllipse)
@@ -3352,6 +3409,7 @@
     WebCore::DisplayList::ItemType::FillPath,
     WebCore::DisplayList::ItemType::FillEllipse,
     WebCore::DisplayList::ItemType::PutImageData,
+    WebCore::DisplayList::ItemType::PaintFrameForMedia,
     WebCore::DisplayList::ItemType::StrokeRect,
     WebCore::DisplayList::ItemType::StrokePath,
     WebCore::DisplayList::ItemType::StrokeEllipse,

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


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -389,6 +389,11 @@
     appendItem(ClipToDrawingCommands::create(destination, colorSpace, recordingContext->takeDisplayList()));
 }
 
+void Recorder::paintFrameForMedia(MediaPlayer& player, const FloatRect& destination)
+{
+    appendItem(PaintFrameForMedia::create(player, destination));
+}
+
 void Recorder::applyDeviceScaleFactor(float deviceScaleFactor)
 {
     // FIXME: this changes the baseCTM, which will invalidate all of our cached extents.

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


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -137,6 +137,8 @@
     IntRect clipBounds() override;
     void clipToImageBuffer(WebCore::ImageBuffer&, const FloatRect&) override;
     void clipToDrawingCommands(const FloatRect& destination, ColorSpace, Function<void(GraphicsContext&)>&&) override;
+    void paintFrameForMedia(MediaPlayer&, const FloatRect& destination) override;
+    bool canPaintFrameForMedia() const override { return true; }
     
     void applyDeviceScaleFactor(float) override;
 

Modified: trunk/Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -1095,4 +1095,9 @@
     // FIXME: Not implemented.
 }
 
+void CairoOperationRecorder::paintFrameForMedia(MediaPlayer&, const FloatRect&)
+{
+    // FIXME: Not implemented.
+}
+
 } // namespace Nicosia

Modified: trunk/Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -100,6 +100,8 @@
     WebCore::IntRect clipBounds() override;
     void clipToImageBuffer(WebCore::ImageBuffer&, const WebCore::FloatRect&) override;
     void clipToDrawingCommands(const WebCore::FloatRect& destination, WebCore::ColorSpace, Function<void(WebCore::GraphicsContext&)>&&) override;
+    void paintFrameForMedia(WebCore::MediaPlayer&, const WebCore::FloatRect& destination) override;
+    bool canPaintFrameForMedia() const override { return false; }
 
     void applyDeviceScaleFactor(float) override;
 

Modified: trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.cpp (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -441,6 +441,11 @@
     // FIXME: Not implemented.
 }
 
+void GraphicsContextImplDirect2D::paintFrameForMedia(MediaPlayer&, const FloatRect&)
+{
+    // FIXME: Not implemented.
+}
+
 } // namespace WebCore
 
 #endif // USE(DIRECT2D)

Modified: trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.h (268144 => 268145)


--- trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/platform/graphics/win/GraphicsContextImplDirect2D.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -104,6 +104,8 @@
     IntRect clipBounds() override;
     void clipToImageBuffer(ImageBuffer&, const FloatRect&) override;
     void clipToDrawingCommands(const FloatRect& destination, ColorSpace, Function<void(GraphicsContext&)>&&) override;
+    void paintFrameForMedia(MediaPlayer&, const FloatRect& destination) override;
+    bool canPaintFrameForMedia() const override { return false; }
     
     void applyDeviceScaleFactor(float) override;
 

Modified: trunk/Source/WebCore/rendering/RenderVideo.cpp (268144 => 268145)


--- trunk/Source/WebCore/rendering/RenderVideo.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebCore/rendering/RenderVideo.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -226,7 +226,7 @@
         paintIntoRect(paintInfo, rect);
     else if (!videoElement().isFullscreen() || !mediaPlayer->supportsAcceleratedRendering()) {
         if (paintInfo.paintBehavior.contains(PaintBehavior::FlattenCompositingLayers))
-            mediaPlayer->paintCurrentFrameInContext(context, rect);
+            context.paintFrameForMedia(*mediaPlayer, rect);
         else
             mediaPlayer->paint(context, rect);
     }

Modified: trunk/Source/WebKit/ChangeLog (268144 => 268145)


--- trunk/Source/WebKit/ChangeLog	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebKit/ChangeLog	2020-10-07 20:13:24 UTC (rev 268145)
@@ -1,3 +1,28 @@
+2020-10-07  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [GPU Process] Support CanvasRenderingContext2D.drawImage() with HTMLVideoElement
+        https://bugs.webkit.org/show_bug.cgi?id=217339
+        <rdar://problem/69409029>
+
+        Reviewed by Darin Adler.
+
+        Implements support for painting the current video frame into a canvas 2D graphics context. See below (and
+        Source/WebCore/ChangeLog) for more details.
+
+        * GPUProcess/graphics/RemoteImageBufferMessageHandlerProxy.h:
+        (WebKit::RemoteImageBufferMessageHandlerProxy::backend):
+        * GPUProcess/graphics/RemoteImageBufferProxy.h:
+        (WebKit::RemoteImageBufferProxy::apply):
+
+        Refactor `apply` so that it treats `PutImageData` and `PaintFrameForMedia` as special cases, and otherwise
+        returns `false` by default. Implement `apply` in the case where the display list item is `PaintFrameForMedia` by
+        using the `MediaPlayerIdentifier` to look up the platform `MediaPlayer` instance, and then calling
+        `GraphicsContext::paintFrameForMedia` with this `MediaPlayer`.
+
+        * GPUProcess/graphics/RemoteRenderingBackendProxy.cpp:
+        (WebKit::RemoteRenderingBackendProxy::gpuConnectionToWebProcess const):
+        * GPUProcess/graphics/RemoteRenderingBackendProxy.h:
+
 2020-10-07  Youenn Fablet  <you...@apple.com>
 
         Add support for BlobEvent.timecode

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferMessageHandlerProxy.h (268144 => 268145)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferMessageHandlerProxy.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferMessageHandlerProxy.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -59,6 +59,8 @@
     void createBackend(const WebCore::FloatSize& logicalSize, const WebCore::IntSize& backendSize, float resolutionScale, WebCore::ColorSpace, ImageBufferBackendHandle);
     void commitFlushContext(ImageBufferFlushIdentifier);
 
+    RemoteRenderingBackendProxy& backend() { return m_remoteRenderingBackendProxy; }
+
 private:
     RemoteRenderingBackendProxy& m_remoteRenderingBackendProxy;
     ImageBufferIdentifier m_imageBufferIdentifier;

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferProxy.h (268144 => 268145)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferProxy.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBufferProxy.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -27,6 +27,7 @@
 
 #if ENABLE(GPU_PROCESS)
 
+#include "GPUConnectionToWebProcess.h"
 #include "RemoteImageBufferMessageHandlerProxy.h"
 #include <WebCore/ConcreteImageBuffer.h>
 #include <WebCore/DisplayListReplayer.h>
@@ -84,15 +85,38 @@
         return BaseConcreteImageBuffer::getImageData(outputFormat, srcRect);
     }
 
-    bool apply(WebCore::DisplayList::Item& item, WebCore::GraphicsContext&) override
+    bool apply(WebCore::DisplayList::Item& item, WebCore::GraphicsContext& context) override
     {
-        if (item.type() != WebCore::DisplayList::ItemType::PutImageData)
-            return false;
+        if (item.type() == WebCore::DisplayList::ItemType::PutImageData) {
+            auto& putImageDataItem = static_cast<WebCore::DisplayList::PutImageData&>(item);
+            putImageData(putImageDataItem.inputFormat(), putImageDataItem.imageData(), putImageDataItem.srcRect(), putImageDataItem.destPoint(), putImageDataItem.destFormat());
+            return true;
+        }
 
-        auto& putImageDataItem = static_cast<WebCore::DisplayList::PutImageData&>(item);
-        putImageData(putImageDataItem.inputFormat(), putImageDataItem.imageData(), putImageDataItem.srcRect(), putImageDataItem.destPoint(), putImageDataItem.destFormat());
-        return true;
+        if (item.type() == WebCore::DisplayList::ItemType::PaintFrameForMedia) {
+            apply(static_cast<WebCore::DisplayList::PaintFrameForMedia&>(item), context);
+            return true;
+        }
+
+        return false;
     }
+
+    void apply(WebCore::DisplayList::PaintFrameForMedia& item, WebCore::GraphicsContext& context)
+    {
+        auto process = backend().gpuConnectionToWebProcess();
+        if (!process)
+            return;
+
+        auto playerProxy = process->remoteMediaPlayerManagerProxy().getProxy(item.identifier());
+        if (!playerProxy)
+            return;
+
+        auto player = playerProxy->mediaPlayer();
+        if (!player)
+            return;
+
+        context.paintFrameForMedia(*player, item.destination());
+    }
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackendProxy.cpp (268144 => 268145)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackendProxy.cpp	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackendProxy.cpp	2020-10-07 20:13:24 UTC (rev 268145)
@@ -121,6 +121,11 @@
         imageBuffer->flushDrawingContextAndCommit(displayList, flushIdentifier);
 }
 
+GPUConnectionToWebProcess* RemoteRenderingBackendProxy::gpuConnectionToWebProcess() const
+{
+    return m_gpuConnectionToWebProcess.get();
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(GPU_PROCESS)

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackendProxy.h (268144 => 268145)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackendProxy.h	2020-10-07 20:10:38 UTC (rev 268144)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackendProxy.h	2020-10-07 20:13:24 UTC (rev 268145)
@@ -60,6 +60,7 @@
     virtual ~RemoteRenderingBackendProxy();
 
     RenderingBackendIdentifier renderingBackendIdentifier() const { return m_renderingBackendIdentifier; }
+    GPUConnectionToWebProcess* gpuConnectionToWebProcess() const;
 
 private:
     RemoteRenderingBackendProxy(GPUConnectionToWebProcess&, RenderingBackendIdentifier);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to