diff --git a/dom/base/nsDeprecatedOperationList.h b/dom/base/nsDeprecatedOperationList.h index 4242aadd948b..44d41f1f4de0 100644 --- a/dom/base/nsDeprecatedOperationList.h +++ b/dom/base/nsDeprecatedOperationList.h @@ -61,3 +61,4 @@ DEPRECATED_OPERATION(FormSubmissionUntrustedEvent) DEPRECATED_OPERATION(ElementSetCapture) DEPRECATED_OPERATION(ElementReleaseCapture) DEPRECATED_OPERATION(DocumentReleaseCapture) +DEPRECATED_OPERATION(OffscreenCanvasToBlob) diff --git a/dom/canvas/OffscreenCanvas.cpp b/dom/canvas/OffscreenCanvas.cpp index bc138b49df87..02b0885653bb 100644 --- a/dom/canvas/OffscreenCanvas.cpp +++ b/dom/canvas/OffscreenCanvas.cpp @@ -15,11 +15,14 @@ #include "mozilla/layers/CanvasClient.h" #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/Telemetry.h" +#include "mozilla/webgpu/CanvasContext.h" #include "CanvasRenderingContext2D.h" #include "CanvasUtils.h" +#include "ClientWebGLContext.h" #include "GLContext.h" #include "GLScreenBuffer.h" #include "ImageBitmap.h" +#include "ImageBitmapRenderingContext.h" #include "nsContentUtils.h" namespace mozilla::dom { @@ -88,50 +91,80 @@ void OffscreenCanvas::ClearResources() { } } -already_AddRefed OffscreenCanvas::GetContext( - JSContext* aCx, const nsAString& aContextId, - JS::Handle aContextOptions, ErrorResult& aRv) { +void OffscreenCanvas::GetContext( + JSContext* aCx, const OffscreenRenderingContextId& aContextId, + JS::Handle aContextOptions, + Nullable& aResult, ErrorResult& aRv) { if (mNeutered) { + aResult.SetNull(); aRv.Throw(NS_ERROR_FAILURE); - return nullptr; + return; } - // We only support WebGL in workers for now CanvasContextType contextType; - if (!CanvasUtils::GetCanvasContextType(aContextId, &contextType)) { - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); - return nullptr; - } - - if (!(contextType == CanvasContextType::WebGL1 || - contextType == CanvasContextType::WebGL2 || - contextType == CanvasContextType::WebGPU || - contextType == CanvasContextType::ImageBitmap)) { - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); - return nullptr; + switch (aContextId) { + case OffscreenRenderingContextId::Bitmaprenderer: + contextType = CanvasContextType::ImageBitmap; + break; + case OffscreenRenderingContextId::Webgl: + contextType = CanvasContextType::WebGL1; + break; + case OffscreenRenderingContextId::Webgl2: + contextType = CanvasContextType::WebGL2; + break; + case OffscreenRenderingContextId::Webgpu: + contextType = CanvasContextType::WebGPU; + break; + default: + MOZ_ASSERT_UNREACHABLE("Unhandled canvas type!"); + aResult.SetNull(); + aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); + return; } RefPtr result = CanvasRenderingContextHelper::GetOrCreateContext( aCx, contextType, aContextOptions, aRv); - - if (!mCurrentContext) { - return nullptr; + if (!result) { + aResult.SetNull(); + return; } + MOZ_ASSERT(mCurrentContext); + if (mCanvasRenderer) { // mCanvasRenderer->SetContextType(contextType); if (contextType == CanvasContextType::WebGL1 || contextType == CanvasContextType::WebGL2) { MOZ_ASSERT_UNREACHABLE("WebGL OffscreenCanvas not yet supported."); - return nullptr; + aResult.SetNull(); + return; } if (contextType == CanvasContextType::WebGPU) { MOZ_ASSERT_UNREACHABLE("WebGPU OffscreenCanvas not yet supported."); - return nullptr; + aResult.SetNull(); + return; } } - return result.forget(); + switch (mCurrentContextType) { + case CanvasContextType::ImageBitmap: + aResult.SetValue().SetAsImageBitmapRenderingContext() = + *static_cast(mCurrentContext.get()); + break; + case CanvasContextType::WebGL1: + case CanvasContextType::WebGL2: + aResult.SetValue().SetAsWebGLRenderingContext() = + *static_cast(mCurrentContext.get()); + break; + case CanvasContextType::WebGPU: + aResult.SetValue().SetAsGPUCanvasContext() = + *static_cast(mCurrentContext.get()); + break; + default: + MOZ_ASSERT_UNREACHABLE("Unhandled canvas type!"); + aResult.SetNull(); + break; + } } layers::ImageContainer* OffscreenCanvas::GetImageContainer() { @@ -207,6 +240,12 @@ already_AddRefed OffscreenCanvas::TransferToImageBitmap( return result.forget(); } +already_AddRefed OffscreenCanvas::ConvertToBlob( + const ImageEncodeOptions& aOptions, ErrorResult& aRv) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return nullptr; +} + already_AddRefed OffscreenCanvas::ToBlob(JSContext* aCx, const nsAString& aType, JS::Handle aParams, diff --git a/dom/canvas/OffscreenCanvas.h b/dom/canvas/OffscreenCanvas.h index 40c12d287c4f..8d0ae9a26adc 100644 --- a/dom/canvas/OffscreenCanvas.h +++ b/dom/canvas/OffscreenCanvas.h @@ -32,8 +32,13 @@ class ImageContainer; } // namespace layers namespace dom { +enum class OffscreenRenderingContextId : uint8_t; class Blob; class ImageBitmap; +struct ImageEncodeOptions; + +using OwningOffscreenRenderingContext = class + OwningImageBitmapRenderingContextOrWebGLRenderingContextOrWebGL2RenderingContextOrGPUCanvasContext; // This is helper class for transferring OffscreenCanvas to worker thread. // Because OffscreenCanvas is not thread-safe. So we cannot pass Offscreen- @@ -61,11 +66,14 @@ class OffscreenCanvas final : public DOMEventTargetHelper, NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OffscreenCanvas, DOMEventTargetHelper) + IMPL_EVENT_HANDLER(contextlost); + IMPL_EVENT_HANDLER(contextrestored); + OffscreenCanvas(nsIGlobalObject* aGlobal, uint32_t aWidth, uint32_t aHeight, layers::LayersBackend aCompositorBackend, layers::CanvasRenderer* aRenderer); - nsCOMPtr GetParentObject() const { return GetOwnerGlobal(); } + nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; @@ -103,12 +111,16 @@ class OffscreenCanvas final : public DOMEventTargetHelper, } } - already_AddRefed GetContext( - JSContext* aCx, const nsAString& aContextId, - JS::Handle aContextOptions, ErrorResult& aRv); + void GetContext(JSContext* aCx, const OffscreenRenderingContextId& aContextId, + JS::Handle aContextOptions, + Nullable& aResult, + ErrorResult& aRv); already_AddRefed TransferToImageBitmap(ErrorResult& aRv); + already_AddRefed ConvertToBlob(const ImageEncodeOptions& aOptions, + ErrorResult& aRv); + already_AddRefed ToBlob(JSContext* aCx, const nsAString& aType, JS::Handle aParams, ErrorResult& aRv); diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index e7df4a40699e..fca9ce6cdfcc 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -426,3 +426,6 @@ DocumentReleaseCaptureWarning=Document.releaseCapture() is deprecated. Use Eleme # LOCALIZATION NOTE: Don't translate browser.runtime.lastError, %S is the error message from the unchecked value set on browser.runtime.lastError. WebExtensionUncheckedLastError=browser.runtime.lastError value was not checked: %S + +# LOCALIZATION NOTE: Do not translate "OffscreenCanvas.toBlob()" and "OffscreenCanvas.convertToBlob()". +OffscreenCanvasToBlobWarning=OffscreenCanvas.toBlob() is deprecated. Use OffscreenCanvas.convertToBlob() instead. diff --git a/dom/webidl/OffscreenCanvas.webidl b/dom/webidl/OffscreenCanvas.webidl index d9e946a24677..08ad5079037e 100644 --- a/dom/webidl/OffscreenCanvas.webidl +++ b/dom/webidl/OffscreenCanvas.webidl @@ -4,26 +4,42 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * For more information on this interface, please see - * https://wiki.whatwg.org/wiki/OffscreenCanvas + * https://html.spec.whatwg.org/#the-offscreencanvas-interface */ +typedef (ImageBitmapRenderingContext or WebGLRenderingContext or WebGL2RenderingContext or GPUCanvasContext) OffscreenRenderingContext; + +dictionary ImageEncodeOptions { + DOMString type = "image/png"; + unrestricted double quality; +}; + +enum OffscreenRenderingContextId { /* "2d", */ "bitmaprenderer", "webgl", "webgl2", "webgpu" }; + [Exposed=(Window,Worker), Pref="gfx.offscreencanvas.enabled"] interface OffscreenCanvas : EventTarget { - constructor(unsigned long width, unsigned long height); + constructor([EnforceRange] unsigned long width, [EnforceRange] unsigned long height); [Pure, SetterThrows] - attribute unsigned long width; + attribute [EnforceRange] unsigned long width; [Pure, SetterThrows] - attribute unsigned long height; + attribute [EnforceRange] unsigned long height; [Throws] - nsISupports? getContext(DOMString contextId, - optional any contextOptions = null); + OffscreenRenderingContext? getContext(OffscreenRenderingContextId contextId, + optional any contextOptions = null); [Throws] ImageBitmap transferToImageBitmap(); [Throws] + Promise convertToBlob(optional ImageEncodeOptions options = {}); + + attribute EventHandler oncontextlost; + attribute EventHandler oncontextrestored; + + // Deprecated by convertToBlob + [Deprecated="OffscreenCanvasToBlob", Throws] Promise toBlob(optional DOMString type = "", optional any encoderOptions); }; diff --git a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.html.ini b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.html.ini deleted file mode 100644 index 1267b7673891..000000000000 --- a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[offscreencanvas.constructor.html] - [Test that OffscreenCanvas constructor handles invalid arguments correctly] - expected: FAIL - diff --git a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.worker.js.ini b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.worker.js.ini deleted file mode 100644 index a74aa5ff5d2a..000000000000 --- a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.constructor.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[offscreencanvas.constructor.worker.html] - [Test that OffscreenCanvas constructor handles invalid arguments correctly in a worker] - expected: FAIL - diff --git a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini index 2739382a5e85..2d8031e11865 100644 --- a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini +++ b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini @@ -5,9 +5,6 @@ [Test that OffscreenCanvasRenderingContext2D with alpha enabled preserves the alpha] expected: FAIL - [Test that getContext with un-supported string throws a TypeError.] - expected: FAIL - [Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque] expected: FAIL diff --git a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini index 4f7d2aea14e6..8b28b2a486cd 100644 --- a/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini +++ b/testing/web-platform/meta/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini @@ -5,9 +5,6 @@ [Test that OffscreenCanvasRenderingContext2D with alpha enabled preserves the alpha] expected: FAIL - [Test that getContext with un-supported string throws a TypeError.] - expected: FAIL - [Test that OffscreenCanvasRenderingContext2D with alpha disabled makes the OffscreenCanvas opaque] expected: FAIL diff --git a/testing/web-platform/meta/html/dom/idlharness.https.html.ini b/testing/web-platform/meta/html/dom/idlharness.https.html.ini index 7268e55fc7db..76e8c760f02b 100644 --- a/testing/web-platform/meta/html/dom/idlharness.https.html.ini +++ b/testing/web-platform/meta/html/dom/idlharness.https.html.ini @@ -571,9 +571,6 @@ prefs: [dom.security.featurePolicy.experimental.enabled:true, dom.security.featu [OffscreenCanvasRenderingContext2D interface: operation setLineDash(sequence)] expected: FAIL - [OffscreenCanvas interface: operation convertToBlob(optional ImageEncodeOptions)] - expected: FAIL - [OffscreenCanvasRenderingContext2D interface: operation arc(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, optional boolean)] expected: FAIL @@ -681,12 +678,6 @@ prefs: [dom.security.featurePolicy.experimental.enabled:true, dom.security.featu [Path2D interface: operation roundRect(unrestricted double, unrestricted double, unrestricted double, unrestricted double, sequence<(unrestricted double or DOMPointInit)>)] expected: FAIL - [OffscreenCanvas interface: attribute oncontextlost] - expected: FAIL - - [OffscreenCanvas interface: attribute oncontextrestored] - expected: FAIL - [OffscreenCanvasRenderingContext2D interface: operation isContextLost()] expected: FAIL diff --git a/testing/web-platform/meta/html/dom/idlharness.worker.js.ini b/testing/web-platform/meta/html/dom/idlharness.worker.js.ini index 39cf64111535..f472b299a10f 100644 --- a/testing/web-platform/meta/html/dom/idlharness.worker.js.ini +++ b/testing/web-platform/meta/html/dom/idlharness.worker.js.ini @@ -340,9 +340,6 @@ [OffscreenCanvasRenderingContext2D interface: operation fill(Path2D, optional CanvasFillRule)] expected: FAIL - [OffscreenCanvas interface: operation convertToBlob(optional ImageEncodeOptions)] - expected: FAIL - [OffscreenCanvasRenderingContext2D interface: operation clip(Path2D, optional CanvasFillRule)] expected: FAIL @@ -412,12 +409,6 @@ [Path2D interface: operation roundRect(unrestricted double, unrestricted double, unrestricted double, unrestricted double, sequence<(unrestricted double or DOMPointInit)>)] expected: FAIL - [OffscreenCanvas interface: attribute oncontextlost] - expected: FAIL - - [OffscreenCanvas interface: attribute oncontextrestored] - expected: FAIL - [OffscreenCanvasRenderingContext2D interface: operation isContextLost()] expected: FAIL diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py index d9fc5966a72c..5c3420274d03 100644 --- a/xpcom/ds/StaticAtoms.py +++ b/xpcom/ds/StaticAtoms.py @@ -783,6 +783,8 @@ STATIC_ATOMS = [ Atom("onconnect", "onconnect"), Atom("onconnectionavailable", "onconnectionavailable"), Atom("oncontextmenu", "oncontextmenu"), + Atom("oncontextlost", "oncontextlost"), + Atom("oncontextrestored", "oncontextrestored"), Atom("oncopy", "oncopy"), Atom("oncut", "oncut"), Atom("ondblclick", "ondblclick"),