Title: [265543] trunk
Revision
265543
Author
[email protected]
Date
2020-08-12 02:05:54 -0700 (Wed, 12 Aug 2020)

Log Message

Implement Canvas.transferControlToOffscreen and OffscreenCanvasRenderingContext2D.commit
https://bugs.webkit.org/show_bug.cgi?id=202797

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

* web-platform-tests/html/canvas/offscreen/filter/offscreencanvas.filter.w-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.w-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-expected.txt:
* web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w-expected.txt:

Source/WebCore:

Implement HTMLCanvasElement.transferControlToOffscreen and
OffscreenCanvasRenderingContext2D.commit. This allows for
(synchronous) display of asynchronously rendered OffscreenCanvas
content.

No new tests. Covered by existing tests.

* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::setHeight):
(WebCore::HTMLCanvasElement::setWidth):
(WebCore::HTMLCanvasElement::reset):
(WebCore::HTMLCanvasElement::transferControlToOffscreen):
(WebCore::HTMLCanvasElement::setImageBufferAndMarkDirty):
(WebCore::HTMLCanvasElement::isControlledByOffscreen const):
* html/HTMLCanvasElement.h:
* html/HTMLCanvasElement.idl:
* html/OffscreenCanvas.cpp:
(WebCore::DetachedOffscreenCanvas::takePlaceholderCanvas):
(WebCore::OffscreenCanvas::create):
(WebCore::OffscreenCanvas::getContext):
(WebCore::OffscreenCanvas::didDraw):
(WebCore::OffscreenCanvas::detach):
(WebCore::OffscreenCanvas::setPlaceholderCanvas):
(WebCore::OffscreenCanvas::pushBufferToPlaceholder):
(WebCore::OffscreenCanvas::commitToPlaceholderCanvas):
(WebCore::OffscreenCanvas::scheduleCommitToPlaceholderCanvas):
(WebCore::OffscreenCanvas::reset):
* html/OffscreenCanvas.h:
* html/canvas/OffscreenCanvasRenderingContext2D.cpp:
(WebCore::OffscreenCanvasRenderingContext2D::commit):
* html/canvas/OffscreenCanvasRenderingContext2D.h:
* html/canvas/OffscreenCanvasRenderingContext2D.idl:
* html/canvas/PlaceholderRenderingContext.cpp:
(WebCore::PlaceholderRenderingContext::canvas const):
* html/canvas/PlaceholderRenderingContext.h:

LayoutTests:

* platform/glib/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w-expected.txt: Removed.

Modified Paths

Removed Paths

  • trunk/LayoutTests/platform/glib/imported/w3c/web-platform-tests/html/canvas/offscreen/

Diff

Modified: trunk/LayoutTests/ChangeLog (265542 => 265543)


--- trunk/LayoutTests/ChangeLog	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/ChangeLog	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,3 +1,12 @@
+2020-08-12  Chris Lord  <[email protected]>
+
+        Implement Canvas.transferControlToOffscreen and OffscreenCanvasRenderingContext2D.commit
+        https://bugs.webkit.org/show_bug.cgi?id=202797
+
+        Reviewed by Dean Jackson.
+
+        * platform/glib/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w-expected.txt: Removed.
+
 2020-08-11  Lauro Moura  <[email protected]>
 
         [GTK] Garden accessibility failures after r265514

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,3 +1,19 @@
+2020-08-12  Chris Lord  <[email protected]>
+
+        Implement Canvas.transferControlToOffscreen and OffscreenCanvasRenderingContext2D.commit
+        https://bugs.webkit.org/show_bug.cgi?id=202797
+
+        Reviewed by Dean Jackson.
+
+        * web-platform-tests/html/canvas/offscreen/filter/offscreencanvas.filter.w-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.w-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-expected.txt:
+        * web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w-expected.txt:
+
 2020-08-11  Chris Dumez  <[email protected]>
 
         Fix WaveShapperNode's waveshaping curve implementation

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filter/offscreencanvas.filter.w-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filter/offscreencanvas.filter.w-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/filter/offscreencanvas.filter.w-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,3 +1,2 @@
+FAIL: Timed out waiting for notifyDone to be called
 
-PASS offscreencanvas 
-

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,4 +1,4 @@
 
-FAIL Test that calling OffscreenCanvas's commit pushes its contents to its placeholder. placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Test that calling commit on an OffscreenCanvas that is not transferred from a HTMLCanvasElement is a noop. ctx.commit is not a function. (In 'ctx.commit()', 'ctx.commit' is undefined)
+PASS Test that calling OffscreenCanvas's commit pushes its contents to its placeholder. 
+PASS Test that calling commit on an OffscreenCanvas that is not transferred from a HTMLCanvasElement is a noop. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.w-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.w-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.w-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,4 +1,4 @@
 
-FAIL Test that calling OffscreenCanvas's commit pushes its contents to its placeholder. placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
+PASS Test that calling OffscreenCanvas's commit pushes its contents to its placeholder. 
 PASS Test that calling commit on an OffscreenCanvas that is not transferred from a HTMLCanvasElement throws an exception in a worker. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,7 +1,7 @@
 
 PASS Test that getContext with un-supported string throws a TypeError. 
 FAIL Test that getContext with supported string returns correct results Argument 1 ('contextType') to OffscreenCanvas.getContext must be one of: "2d", "webgl"
-FAIL Test that getContext twice with different context type returns null the second time The object is in an invalid state.
+PASS Test that getContext twice with different context type returns null the second time 
 PASS Test that 2dcontext.canvas should return the original OffscreenCanvas 
 PASS Test that webglcontext.canvas should return the original OffscreenCanvas 
 FAIL Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque assert_approx_equals: Green channel of the pixel at (5, 5) expected 127 +/- 2 but got 255

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,7 +1,7 @@
 
 PASS Test that getContext with un-supported string throws a TypeError. 
-FAIL Test that getContext with supported string returns correct results Can't find variable: OffscreenCanvasRenderingContext2D
-FAIL Test that getContext twice with different context type returns null the second time The object is in an invalid state.
+FAIL Test that getContext with supported string returns correct results Can't find variable: WebGLRenderingContext
+PASS Test that getContext twice with different context type returns null the second time 
 PASS Test that 2dcontext.canvas should return the original OffscreenCanvas 
 PASS Test that webglcontext.canvas should return the original OffscreenCanvas 
 FAIL Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque assert_approx_equals: Green channel of the pixel at (5, 5) expected 127 +/- 2 but got 255

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -2,11 +2,11 @@
 PASS Verify that writing to the width and height attributes of an OffscreenCanvas works when there is no context attached. 
 PASS Verify that writing to the width and height attributes of an OffscreenCanvas works when there is a 2d context attached. 
 PASS Verify that writing to the width and height attributes of an OffscreenCanvas works when there is a webgl context attached. 
-FAIL Verify that writing to the width or height attribute of a placeholder canvas throws an exception placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Verify that writing to the width or height attribute of a placeholder canvas throws an exception even when not changing the value of the attribute. placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
+PASS Verify that writing to the width or height attribute of a placeholder canvas throws an exception 
+PASS Verify that writing to the width or height attribute of a placeholder canvas throws an exception even when not changing the value of the attribute. 
 PASS Verify that resizing a 2d context resets its state. 
 PASS Verify that setting the size of a 2d context to the same size it already had resets its state. 
-FAIL Verify that resizing an OffscreenCanvas with a 2d context propagates the new size to its placeholder canvas asynchronously. placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously. placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Verify that drawImage uses the size of the frame as the intinsic size of a placeholder canvas. placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
+PASS Verify that resizing an OffscreenCanvas with a 2d context propagates the new size to its placeholder canvas asynchronously. 
+PASS Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously. 
+PASS Verify that drawImage uses the size of the frame as the intinsic size of a placeholder canvas. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,5 +1,5 @@
 
-FAIL Test that an OffscreenCanvas generated by transferControlToOffscreen gets correct width and height placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Test that calling getContext on a placeholder canvas that has already transferred its control throws an exception placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Test that calling transferControlToOffscreen twice throws an exception placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
+PASS Test that an OffscreenCanvas generated by transferControlToOffscreen gets correct width and height 
+PASS Test that calling getContext on a placeholder canvas that has already transferred its control throws an exception 
+PASS Test that calling transferControlToOffscreen twice throws an exception 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w-expected.txt (265542 => 265543)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w-expected.txt	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfercontrol.to.offscreen.w-expected.txt	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,5 +1,5 @@
 
-FAIL Test that an OffscreenCanvas generated by transferControlToOffscreen gets correct width and height when it is transferred to a worker placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Test that calling getContext on a placeholder canvas that is transferred its control to an OffscreenCanvas throws an exception, when the OffscreenCanvas is transferred to a worker placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
-FAIL Test that calling transferControlToOffscreen twice throws an exception, when its associated OffscreenCanvas is transferred to a worker placeholder.transferControlToOffscreen is not a function. (In 'placeholder.transferControlToOffscreen()', 'placeholder.transferControlToOffscreen' is undefined)
+PASS Test that an OffscreenCanvas generated by transferControlToOffscreen gets correct width and height when it is transferred to a worker 
+PASS Test that calling getContext on a placeholder canvas that is transferred its control to an OffscreenCanvas throws an exception, when the OffscreenCanvas is transferred to a worker 
+PASS Test that calling transferControlToOffscreen twice throws an exception, when its associated OffscreenCanvas is transferred to a worker 
 

Modified: trunk/Source/WebCore/ChangeLog (265542 => 265543)


--- trunk/Source/WebCore/ChangeLog	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/ChangeLog	2020-08-12 09:05:54 UTC (rev 265543)
@@ -1,3 +1,46 @@
+2020-08-12  Chris Lord  <[email protected]>
+
+        Implement Canvas.transferControlToOffscreen and OffscreenCanvasRenderingContext2D.commit
+        https://bugs.webkit.org/show_bug.cgi?id=202797
+
+        Reviewed by Dean Jackson.
+
+        Implement HTMLCanvasElement.transferControlToOffscreen and
+        OffscreenCanvasRenderingContext2D.commit. This allows for
+        (synchronous) display of asynchronously rendered OffscreenCanvas
+        content.
+
+        No new tests. Covered by existing tests.
+
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::setHeight):
+        (WebCore::HTMLCanvasElement::setWidth):
+        (WebCore::HTMLCanvasElement::reset):
+        (WebCore::HTMLCanvasElement::transferControlToOffscreen):
+        (WebCore::HTMLCanvasElement::setImageBufferAndMarkDirty):
+        (WebCore::HTMLCanvasElement::isControlledByOffscreen const):
+        * html/HTMLCanvasElement.h:
+        * html/HTMLCanvasElement.idl:
+        * html/OffscreenCanvas.cpp:
+        (WebCore::DetachedOffscreenCanvas::takePlaceholderCanvas):
+        (WebCore::OffscreenCanvas::create):
+        (WebCore::OffscreenCanvas::getContext):
+        (WebCore::OffscreenCanvas::didDraw):
+        (WebCore::OffscreenCanvas::detach):
+        (WebCore::OffscreenCanvas::setPlaceholderCanvas):
+        (WebCore::OffscreenCanvas::pushBufferToPlaceholder):
+        (WebCore::OffscreenCanvas::commitToPlaceholderCanvas):
+        (WebCore::OffscreenCanvas::scheduleCommitToPlaceholderCanvas):
+        (WebCore::OffscreenCanvas::reset):
+        * html/OffscreenCanvas.h:
+        * html/canvas/OffscreenCanvasRenderingContext2D.cpp:
+        (WebCore::OffscreenCanvasRenderingContext2D::commit):
+        * html/canvas/OffscreenCanvasRenderingContext2D.h:
+        * html/canvas/OffscreenCanvasRenderingContext2D.idl:
+        * html/canvas/PlaceholderRenderingContext.cpp:
+        (WebCore::PlaceholderRenderingContext::canvas const):
+        * html/canvas/PlaceholderRenderingContext.h:
+
 2020-08-12  Carlos Garcia Campos  <[email protected]>
 
         REGRESSION(r261570): [GTK] Fails to send drop event to _javascript_

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (265542 => 265543)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2020-08-12 09:05:54 UTC (rev 265543)
@@ -49,6 +49,7 @@
 #include "InspectorInstrumentation.h"
 #include "JSDOMConvertDictionary.h"
 #include "MIMETypeRegistry.h"
+#include "PlaceholderRenderingContext.h"
 #include "RenderElement.h"
 #include "RenderHTMLCanvas.h"
 #include "ResourceLoadObserver.h"
@@ -184,7 +185,7 @@
 
 ExceptionOr<void> HTMLCanvasElement::setHeight(unsigned value)
 {
-    if (m_context && m_context->isPlaceholder())
+    if (isControlledByOffscreen())
         return Exception { InvalidStateError };
     setAttributeWithoutSynchronization(heightAttr, AtomString::number(limitToOnlyHTMLNonNegative(value, defaultHeight)));
     return { };
@@ -192,7 +193,7 @@
 
 ExceptionOr<void> HTMLCanvasElement::setWidth(unsigned value)
 {
-    if (m_context && m_context->isPlaceholder())
+    if (isControlledByOffscreen())
         return Exception { InvalidStateError };
     setAttributeWithoutSynchronization(widthAttr, AtomString::number(limitToOnlyHTMLNonNegative(value, defaultWidth)));
     return { };
@@ -566,7 +567,7 @@
 
 void HTMLCanvasElement::reset()
 {
-    if (m_ignoreReset)
+    if (m_ignoreReset || isControlledByOffscreen())
         return;
 
     bool hadImageBuffer = hasCreatedImageBuffer();
@@ -768,6 +769,17 @@
     return { };
 }
 
+#if ENABLE(OFFSCREEN_CANVAS)
+ExceptionOr<Ref<OffscreenCanvas>> HTMLCanvasElement::transferControlToOffscreen(ScriptExecutionContext& context)
+{
+    if (m_context)
+        return Exception { InvalidStateError };
+
+    m_context = makeUnique<PlaceholderRenderingContext>(*this);
+    return OffscreenCanvas::create(context, *this);
+}
+#endif
+
 RefPtr<ImageData> HTMLCanvasElement::getImageData()
 {
 #if ENABLE(WEBGL)
@@ -945,8 +957,24 @@
 
 void HTMLCanvasElement::setImageBufferAndMarkDirty(std::unique_ptr<ImageBuffer>&& buffer)
 {
+    IntSize oldSize = size();
     m_hasCreatedImageBuffer = true;
     setImageBuffer(WTFMove(buffer));
+
+    if (isControlledByOffscreen() && oldSize != size()) {
+        setAttributeWithoutSynchronization(widthAttr, AtomString::number(width()));
+        setAttributeWithoutSynchronization(heightAttr, AtomString::number(height()));
+
+        auto renderer = this->renderer();
+        if (is<RenderHTMLCanvas>(renderer)) {
+            auto& canvasRenderer = downcast<RenderHTMLCanvas>(*renderer);
+            canvasRenderer.canvasSizeChanged();
+            canvasRenderer.contentChanged(CanvasChanged);
+        }
+
+        notifyObserversCanvasResized();
+    }
+
     didDraw(FloatRect(FloatPoint(), size()));
 }
 
@@ -1052,4 +1080,9 @@
 #endif
 }
 
+bool HTMLCanvasElement::isControlledByOffscreen() const
+{
+    return m_context && m_context->isPlaceholder();
 }
+
+}

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (265542 => 265543)


--- trunk/Source/WebCore/html/HTMLCanvasElement.h	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h	2020-08-12 09:05:54 UTC (rev 265543)
@@ -50,6 +50,7 @@
 class ImageData;
 class MediaSample;
 class MediaStream;
+class OffscreenCanvas;
 class WebGLRenderingContextBase;
 class GPUCanvasContext;
 struct UncachedString;
@@ -97,6 +98,9 @@
     WEBCORE_EXPORT ExceptionOr<UncachedString> toDataURL(const String& mimeType, JSC::JSValue quality);
     WEBCORE_EXPORT ExceptionOr<UncachedString> toDataURL(const String& mimeType);
     ExceptionOr<void> toBlob(ScriptExecutionContext&, Ref<BlobCallback>&&, const String& mimeType, JSC::JSValue quality);
+#if ENABLE(OFFSCREEN_CANVAS)
+    ExceptionOr<Ref<OffscreenCanvas>> transferControlToOffscreen(ScriptExecutionContext&);
+#endif
 
     // Used for rendering
     void didDraw(const FloatRect&) final;
@@ -135,6 +139,8 @@
     void setIsSnapshotting(bool isSnapshotting) { m_isSnapshotting = isSnapshotting; }
     bool isSnapshotting() const { return m_isSnapshotting; }
 
+    bool isControlledByOffscreen() const;
+
 private:
     HTMLCanvasElement(const QualifiedName&, Document&);
 

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.idl (265542 => 265543)


--- trunk/Source/WebCore/html/HTMLCanvasElement.idl	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.idl	2020-08-12 09:05:54 UTC (rev 265543)
@@ -50,6 +50,7 @@
 
     [MayThrowException] DOMString toDataURL(optional DOMString type, optional any quality);
     [CallWith=ScriptExecutionContext, MayThrowException] void toBlob(BlobCallback callback, optional DOMString type, optional any quality);
+    [Conditional=OFFSCREEN_CANVAS, CallWith=ScriptExecutionContext, MayThrowException] OffscreenCanvas transferControlToOffscreen();
 
     [Conditional=MEDIA_STREAM, CallWith=Document, MayThrowException, NewObject] MediaStream captureStream(optional double frameRequestRate);
 };

Modified: trunk/Source/WebCore/html/OffscreenCanvas.cpp (265542 => 265543)


--- trunk/Source/WebCore/html/OffscreenCanvas.cpp	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/OffscreenCanvas.cpp	2020-08-12 09:05:54 UTC (rev 265543)
@@ -31,11 +31,14 @@
 #include "CSSValuePool.h"
 #include "CanvasRenderingContext.h"
 #include "Document.h"
+#include "HTMLCanvasElement.h"
 #include "ImageBitmap.h"
+#include "ImageData.h"
 #include "JSBlob.h"
 #include "JSDOMPromiseDeferred.h"
 #include "MIMETypeRegistry.h"
 #include "OffscreenCanvasRenderingContext2D.h"
+#include "PlaceholderRenderingContext.h"
 #include "WebGLRenderingContext.h"
 #include "WorkerGlobalScope.h"
 #include <wtf/IsoMallocInlines.h>
@@ -56,6 +59,12 @@
     return WTFMove(m_buffer);
 }
 
+WeakPtr<HTMLCanvasElement> DetachedOffscreenCanvas::takePlaceholderCanvas()
+{
+    ASSERT(isMainThread());
+    return std::exchange(m_placeholderCanvas, nullptr);
+}
+
 Ref<OffscreenCanvas> OffscreenCanvas::create(ScriptExecutionContext& context, unsigned width, unsigned height)
 {
     return adoptRef(*new OffscreenCanvas(context, width, height));
@@ -68,9 +77,22 @@
     if (!detachedCanvas->originClean())
         clone->setOriginTainted();
 
+    callOnMainThread([detachedCanvas = WTFMove(detachedCanvas), offscreenCanvas = makeRef(clone.get())] () mutable {
+        offscreenCanvas->m_placeholderCanvas = detachedCanvas->takePlaceholderCanvas();
+        offscreenCanvas->scriptExecutionContext()->postTask({ ScriptExecutionContext::Task::CleanupTask,
+            [releaseOffscreenCanvas = WTFMove(offscreenCanvas)] (ScriptExecutionContext&) { } });
+    });
+
     return clone;
 }
 
+Ref<OffscreenCanvas> OffscreenCanvas::create(ScriptExecutionContext& context, HTMLCanvasElement& canvas)
+{
+    auto offscreen = adoptRef(*new OffscreenCanvas(context, canvas.width(), canvas.height()));
+    offscreen->setPlaceholderCanvas(canvas);
+    return offscreen;
+}
+
 OffscreenCanvas::OffscreenCanvas(ScriptExecutionContext& context, unsigned width, unsigned height)
     : CanvasBase(IntSize(width, height))
     , ContextDestructionObserver(&context)
@@ -119,7 +141,7 @@
     reset();
 }
 
-ExceptionOr<OffscreenRenderingContext> OffscreenCanvas::getContext(JSC::JSGlobalObject& state, RenderingContextType contextType, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
+ExceptionOr<Optional<OffscreenRenderingContext>> OffscreenCanvas::getContext(JSC::JSGlobalObject& state, RenderingContextType contextType, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
 {
     if (m_detached)
         return Exception { InvalidStateError };
@@ -127,22 +149,22 @@
     if (contextType == RenderingContextType::_2d) {
         if (m_context) {
             if (!is<OffscreenCanvasRenderingContext2D>(*m_context))
-                return Exception { InvalidStateError };
-            return { RefPtr<OffscreenCanvasRenderingContext2D> { &downcast<OffscreenCanvasRenderingContext2D>(*m_context) } };
+                return { { WTF::nullopt } };
+            return { { RefPtr<OffscreenCanvasRenderingContext2D> { &downcast<OffscreenCanvasRenderingContext2D>(*m_context) } } };
         }
 
         m_context = makeUnique<OffscreenCanvasRenderingContext2D>(*this);
         if (!m_context)
-            return { RefPtr<OffscreenCanvasRenderingContext2D> { nullptr } };
+            return { { WTF::nullopt } };
 
-        return { RefPtr<OffscreenCanvasRenderingContext2D> { &downcast<OffscreenCanvasRenderingContext2D>(*m_context) } };
+        return { { RefPtr<OffscreenCanvasRenderingContext2D> { &downcast<OffscreenCanvasRenderingContext2D>(*m_context) } } };
     }
 #if ENABLE(WEBGL)
     if (contextType == RenderingContextType::Webgl) {
         if (m_context) {
-            if (!is<WebGLRenderingContext>(*m_context))
-                return Exception { InvalidStateError };
-            return { RefPtr<WebGLRenderingContext> { &downcast<WebGLRenderingContext>(*m_context) } };
+            if (is<WebGLRenderingContext>(*m_context))
+                return { { RefPtr<WebGLRenderingContext> { &downcast<WebGLRenderingContext>(*m_context) } } };
+            return { { WTF::nullopt } };
         }
 
         auto scope = DECLARE_THROW_SCOPE(state.vm());
@@ -151,13 +173,13 @@
 
         m_context = WebGLRenderingContextBase::create(*this, attributes, "webgl");
         if (!m_context)
-            return { RefPtr<WebGLRenderingContext> { nullptr } };
+            return { { WTF::nullopt } };
 
-        return { RefPtr<WebGLRenderingContext> { &downcast<WebGLRenderingContext>(*m_context) } };
+        return { { RefPtr<WebGLRenderingContext> { &downcast<WebGLRenderingContext>(*m_context) } } };
     }
 #endif
 
-    return Exception { NotSupportedError };
+    return Exception { TypeError };
 }
 
 ExceptionOr<RefPtr<ImageBitmap>> OffscreenCanvas::transferToImageBitmap()
@@ -259,6 +281,7 @@
 void OffscreenCanvas::didDraw(const FloatRect& rect)
 {
     clearCopiedImage();
+    scheduleCommitToPlaceholderCanvas();
     notifyObserversCanvasChanged(rect);
 }
 
@@ -301,9 +324,75 @@
 
     m_detached = true;
 
-    return makeUnique<DetachedOffscreenCanvas>(takeImageBuffer(), size(), originClean());
+    auto detached = makeUnique<DetachedOffscreenCanvas>(takeImageBuffer(), size(), originClean());
+    detached->m_placeholderCanvas = std::exchange(m_placeholderCanvas, nullptr);
+
+    return detached;
 }
 
+void OffscreenCanvas::setPlaceholderCanvas(HTMLCanvasElement& canvas)
+{
+    ASSERT(!m_context);
+    ASSERT(isMainThread());
+    m_placeholderCanvas = makeWeakPtr(canvas);
+}
+
+void OffscreenCanvas::pushBufferToPlaceholder()
+{
+    callOnMainThread([protectedThis = makeRef(*this), this] () mutable {
+        auto locker = holdLock(m_commitLock);
+
+        if (m_placeholderCanvas && m_hasPendingCommitData) {
+            std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(FloatSize(m_pendingCommitData->size()), RenderingMode::Unaccelerated);
+            buffer->putImageData(AlphaPremultiplication::Premultiplied, *m_pendingCommitData, IntRect(IntPoint(), m_pendingCommitData->size()));
+            m_placeholderCanvas->setImageBufferAndMarkDirty(WTFMove(buffer));
+            m_hasPendingCommitData = false;
+        }
+
+        scriptExecutionContext()->postTask([releaseThis = WTFMove(protectedThis)] (ScriptExecutionContext&) { });
+    });
+}
+
+void OffscreenCanvas::commitToPlaceholderCanvas()
+{
+    auto* imageBuffer = buffer();
+    if (!imageBuffer)
+        return;
+
+    // FIXME: Transfer texture over if we're using accelerated compositing
+    if (m_context && (m_context->isWebGL() || m_context->isAccelerated()))
+        m_context->paintRenderingResultsToCanvas();
+
+    if (isMainThread()) {
+        if (m_placeholderCanvas) {
+            if (auto bufferCopy = imageBuffer->copyRectToBuffer(FloatRect(FloatPoint(), imageBuffer->logicalSize()), ColorSpace::SRGB, imageBuffer->context()))
+                m_placeholderCanvas->setImageBufferAndMarkDirty(WTFMove(bufferCopy));
+        }
+        return;
+    }
+
+    auto locker = holdLock(m_commitLock);
+
+    bool shouldPushBuffer = !m_hasPendingCommitData;
+    m_pendingCommitData = imageBuffer->getImageData(AlphaPremultiplication::Premultiplied, IntRect(IntPoint(), imageBuffer->logicalSize()));
+    m_hasPendingCommitData = true;
+
+    if (shouldPushBuffer)
+        pushBufferToPlaceholder();
+}
+
+void OffscreenCanvas::scheduleCommitToPlaceholderCanvas()
+{
+    if (!m_hasScheduledCommit) {
+        auto& scriptContext = *scriptExecutionContext();
+        m_hasScheduledCommit = true;
+        scriptContext.postTask([protectedThis = makeRef(*this), this] (ScriptExecutionContext&) {
+            m_hasScheduledCommit = false;
+            commitToPlaceholderCanvas();
+        });
+    }
+}
+
 CSSValuePool& OffscreenCanvas::cssValuePool()
 {
     auto* context = canvasBaseScriptExecutionContext();
@@ -351,6 +440,7 @@
     clearCopiedImage();
 
     notifyObserversCanvasResized();
+    scheduleCommitToPlaceholderCanvas();
 }
 
 }

Modified: trunk/Source/WebCore/html/OffscreenCanvas.h (265542 => 265543)


--- trunk/Source/WebCore/html/OffscreenCanvas.h	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/OffscreenCanvas.h	2020-08-12 09:05:54 UTC (rev 265543)
@@ -38,6 +38,7 @@
 #include "ScriptWrappable.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
+#include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -45,7 +46,9 @@
 class CanvasRenderingContext;
 class CSSValuePool;
 class DeferredPromise;
+class HTMLCanvasElement;
 class ImageBitmap;
+class ImageData;
 class OffscreenCanvasRenderingContext2D;
 class WebGLRenderingContext;
 
@@ -58,6 +61,8 @@
 class DetachedOffscreenCanvas {
     WTF_MAKE_NONCOPYABLE(DetachedOffscreenCanvas);
     WTF_MAKE_FAST_ALLOCATED;
+    friend class OffscreenCanvas;
+
 public:
     DetachedOffscreenCanvas(std::unique_ptr<ImageBuffer>&&, const IntSize&, bool originClean);
 
@@ -71,11 +76,13 @@
             return buffer->memoryCost();
         return 0;
     }
+    WeakPtr<HTMLCanvasElement> takePlaceholderCanvas();
 
 private:
     std::unique_ptr<ImageBuffer> m_buffer;
     IntSize m_size;
     bool m_originClean;
+    WeakPtr<HTMLCanvasElement> m_placeholderCanvas;
 };
 
 class OffscreenCanvas final : public RefCounted<OffscreenCanvas>, public CanvasBase, public EventTargetWithInlineData, private ContextDestructionObserver {
@@ -94,6 +101,7 @@
 
     static Ref<OffscreenCanvas> create(ScriptExecutionContext&, unsigned width, unsigned height);
     static Ref<OffscreenCanvas> create(ScriptExecutionContext&, std::unique_ptr<DetachedOffscreenCanvas>&&);
+    static Ref<OffscreenCanvas> create(ScriptExecutionContext&, HTMLCanvasElement&);
     virtual ~OffscreenCanvas();
 
     unsigned width() const final;
@@ -103,7 +111,7 @@
 
     CanvasRenderingContext* renderingContext() const final { return m_context.get(); }
 
-    ExceptionOr<OffscreenRenderingContext> getContext(JSC::JSGlobalObject&, RenderingContextType, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
+    ExceptionOr<Optional<OffscreenRenderingContext>> getContext(JSC::JSGlobalObject&, RenderingContextType, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
     ExceptionOr<RefPtr<ImageBitmap>> transferToImageBitmap();
     void convertToBlob(ImageEncodeOptions&&, Ref<DeferredPromise>&&);
 
@@ -117,6 +125,8 @@
     bool canDetach() const;
     std::unique_ptr<DetachedOffscreenCanvas> detach();
 
+    void commitToPlaceholderCanvas();
+
     CSSValuePool& cssValuePool();
 
     using RefCounted::ref;
@@ -146,6 +156,10 @@
 
     void clearCopiedImage() const;
 
+    void setPlaceholderCanvas(HTMLCanvasElement&);
+    void pushBufferToPlaceholder();
+    void scheduleCommitToPlaceholderCanvas();
+
     std::unique_ptr<CanvasRenderingContext> m_context;
 
     // m_hasCreatedImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
@@ -154,6 +168,13 @@
     bool m_detached { false };
 
     mutable RefPtr<Image> m_copiedImage;
+
+    bool m_hasScheduledCommit { false };
+    WeakPtr<HTMLCanvasElement> m_placeholderCanvas;
+
+    mutable Lock m_commitLock;
+    bool m_hasPendingCommitData { false };
+    RefPtr<ImageData> m_pendingCommitData;
 };
 
 }

Modified: trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.cpp (265542 => 265543)


--- trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.cpp	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.cpp	2020-08-12 09:05:54 UTC (rev 265543)
@@ -48,6 +48,11 @@
 
 OffscreenCanvasRenderingContext2D::~OffscreenCanvasRenderingContext2D() = default;
 
+void OffscreenCanvasRenderingContext2D::commit()
+{
+    downcast<OffscreenCanvas>(canvasBase()).commitToPlaceholderCanvas();
+}
+
 } // namespace WebCore
 
 #endif

Modified: trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.h (265542 => 265543)


--- trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.h	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.h	2020-08-12 09:05:54 UTC (rev 265543)
@@ -42,6 +42,8 @@
     bool isOffscreen2d() const override { return true; }
 
     OffscreenCanvas& canvas() const { return downcast<OffscreenCanvas>(canvasBase()); }
+
+    void commit();
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.idl (265542 => 265543)


--- trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.idl	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/canvas/OffscreenCanvasRenderingContext2D.idl	2020-08-12 09:05:54 UTC (rev 265543)
@@ -27,14 +27,13 @@
     CustomIsReachable,
     EnabledAtRuntime=OffscreenCanvas,
     Conditional=OFFSCREEN_CANVAS,
-    Exposed=(Window), // FIXME: OffscreenCanvas - should be Window,Worker
+    Exposed=(Window,Worker),
     JSGenerateToJSObject,
     JSCustomMarkFunction,
     // CallTracingCallback=recordCanvasAction, // FIXME: OffscreenCanvas.
 ] interface OffscreenCanvasRenderingContext2D {
     readonly attribute OffscreenCanvas canvas;
-    // FIXME: OffscreenCanvas.
-    // void commit();
+    void commit();
 
     // Inspector-only.
     // FIXME: OffscreenCanvas.

Modified: trunk/Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp (265542 => 265543)


--- trunk/Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp	2020-08-12 09:05:54 UTC (rev 265543)
@@ -26,6 +26,10 @@
 #include "config.h"
 #include "PlaceholderRenderingContext.h"
 
+#if ENABLE(OFFSCREEN_CANVAS)
+
+#include "HTMLCanvasElement.h"
+#include "OffscreenCanvas.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
@@ -37,4 +41,14 @@
 {
 }
 
+HTMLCanvasElement* PlaceholderRenderingContext::canvas() const
+{
+    auto& base = canvasBase();
+    if (!is<HTMLCanvasElement>(base))
+        return nullptr;
+    return &downcast<HTMLCanvasElement>(base);
 }
+
+}
+
+#endif

Modified: trunk/Source/WebCore/html/canvas/PlaceholderRenderingContext.h (265542 => 265543)


--- trunk/Source/WebCore/html/canvas/PlaceholderRenderingContext.h	2020-08-12 07:35:52 UTC (rev 265542)
+++ trunk/Source/WebCore/html/canvas/PlaceholderRenderingContext.h	2020-08-12 09:05:54 UTC (rev 265543)
@@ -25,15 +25,21 @@
 
 #pragma once
 
+#if ENABLE(OFFSCREEN_CANVAS)
+
 #include "CanvasRenderingContext.h"
 
 namespace WebCore {
 
+class OffscreenCanvas;
+
 class PlaceholderRenderingContext final : public CanvasRenderingContext {
     WTF_MAKE_ISO_ALLOCATED(PlaceholderRenderingContext);
 public:
     PlaceholderRenderingContext(CanvasBase&);
 
+    HTMLCanvasElement* canvas() const;
+
 private:
     bool isPlaceholder() const final { return true; }
 };
@@ -41,3 +47,5 @@
 }
 
 SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::PlaceholderRenderingContext, isPlaceholder())
+
+#endif
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to