Bug 1867190 - Initialise the PHC allocate delay later r=glandium
[gecko.git] / dom / html / HTMLCanvasElement.h
blob586a43fedc9ff62dc20ff1bc7560782aa06c2614
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #if !defined(mozilla_dom_HTMLCanvasElement_h)
7 # define mozilla_dom_HTMLCanvasElement_h
9 # include "mozilla/Attributes.h"
10 # include "mozilla/StateWatching.h"
11 # include "mozilla/WeakPtr.h"
12 # include "nsIDOMEventListener.h"
13 # include "nsIObserver.h"
14 # include "nsGenericHTMLElement.h"
15 # include "nsGkAtoms.h"
16 # include "nsSize.h"
17 # include "nsError.h"
19 # include "mozilla/dom/CanvasRenderingContextHelper.h"
20 # include "mozilla/gfx/Rect.h"
21 # include "mozilla/layers/LayersTypes.h"
23 class nsICanvasRenderingContextInternal;
24 class nsIInputStream;
25 class nsITimerCallback;
26 enum class gfxAlphaType;
27 enum class FrameCaptureState : uint8_t;
29 namespace mozilla {
31 class nsDisplayListBuilder;
32 class ClientWebGLContext;
34 namespace layers {
35 class CanvasRenderer;
36 class Image;
37 class ImageContainer;
38 class Layer;
39 class LayerManager;
40 class OOPCanvasRenderer;
41 class SharedSurfaceTextureClient;
42 class WebRenderCanvasData;
43 } // namespace layers
44 namespace gfx {
45 class DrawTarget;
46 class SourceSurface;
47 class VRLayerChild;
48 } // namespace gfx
49 namespace webgpu {
50 class CanvasContext;
51 } // namespace webgpu
53 namespace dom {
54 class BlobCallback;
55 class CanvasCaptureMediaStream;
56 class File;
57 class HTMLCanvasPrintState;
58 class OffscreenCanvas;
59 class OffscreenCanvasDisplayHelper;
60 class PrintCallback;
61 class PWebGLChild;
62 class RequestedFrameRefreshObserver;
64 // Listen visibilitychange and memory-pressure event and inform
65 // context when event is fired.
66 class HTMLCanvasElementObserver final : public nsIObserver {
67 public:
68 NS_DECL_ISUPPORTS
69 NS_DECL_NSIOBSERVER
71 explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement);
72 void Destroy();
74 void RegisterObserverEvents();
75 void UnregisterObserverEvents();
77 private:
78 ~HTMLCanvasElementObserver();
80 HTMLCanvasElement* mElement;
84 * FrameCaptureListener is used by captureStream() as a way of getting video
85 * frames from the canvas. On a refresh driver tick after something has been
86 * drawn to the canvas since the last such tick, all registered
87 * FrameCaptureListeners that report true for FrameCaptureRequested() will be
88 * given a copy of the just-painted canvas.
89 * All FrameCaptureListeners get the same copy.
91 class FrameCaptureListener : public SupportsWeakPtr {
92 public:
93 FrameCaptureListener() = default;
96 * Indicates to the canvas whether or not this listener has requested a frame.
98 virtual bool FrameCaptureRequested(const TimeStamp& aTime) const = 0;
101 * Interface through which new video frames will be provided while
102 * `mFrameCaptureRequested` is `true`.
104 virtual void NewFrame(already_AddRefed<layers::Image> aImage,
105 const TimeStamp& aTime) = 0;
107 protected:
108 virtual ~FrameCaptureListener() = default;
111 class HTMLCanvasElement final : public nsGenericHTMLElement,
112 public CanvasRenderingContextHelper,
113 public SupportsWeakPtr {
114 enum { DEFAULT_CANVAS_WIDTH = 300, DEFAULT_CANVAS_HEIGHT = 150 };
116 typedef layers::CanvasRenderer CanvasRenderer;
117 typedef layers::LayerManager LayerManager;
118 typedef layers::WebRenderCanvasData WebRenderCanvasData;
120 public:
121 explicit HTMLCanvasElement(
122 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
124 NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLCanvasElement, canvas)
126 // nsISupports
127 NS_DECL_ISUPPORTS_INHERITED
129 // CC
130 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLCanvasElement,
131 nsGenericHTMLElement)
133 // WebIDL
134 uint32_t Height() {
135 return GetUnsignedIntAttr(nsGkAtoms::height, DEFAULT_CANVAS_HEIGHT);
137 uint32_t Width() {
138 return GetUnsignedIntAttr(nsGkAtoms::width, DEFAULT_CANVAS_WIDTH);
140 void SetHeight(uint32_t aHeight, ErrorResult& aRv);
141 void SetWidth(uint32_t aWidth, ErrorResult& aRv);
143 already_AddRefed<nsISupports> GetContext(
144 JSContext* aCx, const nsAString& aContextId,
145 JS::Handle<JS::Value> aContextOptions, ErrorResult& aRv);
147 void ToDataURL(JSContext* aCx, const nsAString& aType,
148 JS::Handle<JS::Value> aParams, nsAString& aDataURL,
149 nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
151 void ToBlob(JSContext* aCx, BlobCallback& aCallback, const nsAString& aType,
152 JS::Handle<JS::Value> aParams, nsIPrincipal& aSubjectPrincipal,
153 ErrorResult& aRv);
155 OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
157 bool MozOpaque() const { return GetBoolAttr(nsGkAtoms::moz_opaque); }
158 void SetMozOpaque(bool aValue, ErrorResult& aRv) {
159 if (mOffscreenCanvas) {
160 aRv.Throw(NS_ERROR_FAILURE);
161 return;
164 SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
166 PrintCallback* GetMozPrintCallback() const;
167 void SetMozPrintCallback(PrintCallback* aCallback);
169 already_AddRefed<CanvasCaptureMediaStream> CaptureStream(
170 const Optional<double>& aFrameRate, nsIPrincipal& aSubjectPrincipal,
171 ErrorResult& aRv);
174 * Get the size in pixels of this canvas element
176 nsIntSize GetSize();
179 * Set the size in pixels of this canvas element.
181 void SetSize(const nsIntSize& aSize, ErrorResult& aRv);
184 * Determine whether the canvas is write-only.
186 bool IsWriteOnly() const;
189 * Force the canvas to be write-only, except for readers from
190 * a specific extension's content script expanded principal, if
191 * available.
193 void SetWriteOnly(nsIPrincipal* aExpandedReader = nullptr);
196 * Notify the placeholder offscreen canvas of an updated size.
198 void InvalidateCanvasPlaceholder(uint32_t aWidth, uint32_t aHeight);
201 * Notify that some canvas content has changed and the window may
202 * need to be updated. aDamageRect is in canvas coordinates.
204 void InvalidateCanvasContent(const mozilla::gfx::Rect* aDamageRect);
206 * Notify that we need to repaint the entire canvas, including updating of
207 * the layer tree.
209 void InvalidateCanvas();
211 nsICanvasRenderingContextInternal* GetCurrentContext() {
212 return mCurrentContext;
216 * Returns true if the canvas context content is guaranteed to be opaque
217 * across its entire area.
219 bool GetIsOpaque();
220 virtual bool GetOpaqueAttr() override;
223 * Retrieve a snapshot of the internal surface, returning the alpha type if
224 * requested. An optional target may be supplied for which the snapshot will
225 * be optimized for, if possible.
227 virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(
228 gfxAlphaType* aOutAlphaType = nullptr,
229 gfx::DrawTarget* aTarget = nullptr);
232 * Register a FrameCaptureListener with this canvas.
233 * The canvas hooks into the RefreshDriver while there are
234 * FrameCaptureListeners registered.
235 * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the
236 * caller's responsibility to keep them alive. Once a registered
237 * FrameCaptureListener is destroyed it will be automatically deregistered.
239 nsresult RegisterFrameCaptureListener(FrameCaptureListener* aListener,
240 bool aReturnPlaceholderData);
243 * Returns true when there is at least one registered FrameCaptureListener
244 * that has requested a frame capture.
246 bool IsFrameCaptureRequested(const TimeStamp& aTime) const;
249 * Processes destroyed FrameCaptureListeners and removes them if necessary.
250 * Should there be none left, the FrameRefreshObserver will be unregistered.
252 void ProcessDestroyedFrameListeners();
255 * Called by the RefreshDriver hook when a frame has been captured.
256 * Makes a copy of the provided surface and hands it to all
257 * FrameCaptureListeners having requested frame capture.
259 void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface,
260 const TimeStamp& aTime);
262 virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
263 const nsAString& aValue,
264 nsIPrincipal* aMaybeScriptedPrincipal,
265 nsAttrValue& aResult) override;
266 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
267 nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
268 int32_t aModType) const override;
269 nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
271 virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
272 nsresult CopyInnerTo(HTMLCanvasElement* aDest);
274 static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
277 * Helpers called by various users of Canvas
280 already_AddRefed<layers::Image> GetAsImage();
281 bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
282 WebRenderCanvasData* aCanvasData);
283 bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
284 CanvasRenderer* aRenderer);
286 // Call this whenever we need future changes to the canvas
287 // to trigger fresh invalidation requests. This needs to be called
288 // whenever we render the canvas contents to the screen, or whenever we
289 // take a snapshot of the canvas that needs to be "live" (e.g. -moz-element).
290 void MarkContextClean();
292 // Call this after capturing a frame, so we can avoid unnecessary surface
293 // copies for future frames when no drawing has occurred.
294 void MarkContextCleanForFrameCapture();
296 // Returns non-null when the current context supports captureStream().
297 // The FrameCaptureState gets set to DIRTY when something is drawn.
298 Watchable<FrameCaptureState>* GetFrameCaptureState();
300 nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
302 layers::LayersBackend GetCompositorBackendType() const;
304 void OnMemoryPressure();
305 void OnDeviceReset();
307 already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
308 void ClearVRFrame();
310 bool MaybeModified() const { return mMaybeModified; };
312 protected:
313 virtual ~HTMLCanvasElement();
314 void Destroy();
316 virtual JSObject* WrapNode(JSContext* aCx,
317 JS::Handle<JSObject*> aGivenProto) override;
319 virtual nsIntSize GetWidthHeight() override;
321 virtual already_AddRefed<nsICanvasRenderingContextInternal> CreateContext(
322 CanvasContextType aContextType) override;
324 nsresult UpdateContext(JSContext* aCx,
325 JS::Handle<JS::Value> aNewContextOptions,
326 ErrorResult& aRvForDictionaryInit) override;
328 nsresult ExtractData(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
329 nsAString& aType, const nsAString& aOptions,
330 nsIInputStream** aStream);
331 nsresult ToDataURLImpl(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
332 const nsAString& aMimeType,
333 const JS::Value& aEncoderOptions, nsAString& aDataURL);
335 UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aOutFormat,
336 gfx::IntSize* aOutImageSize) override;
338 MOZ_CAN_RUN_SCRIPT void CallPrintCallback();
340 virtual void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
341 const nsAttrValue* aValue,
342 const nsAttrValue* aOldValue,
343 nsIPrincipal* aSubjectPrincipal,
344 bool aNotify) override;
345 virtual void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
346 const nsAttrValueOrString& aValue,
347 bool aNotify) override;
349 public:
350 ClientWebGLContext* GetWebGLContext();
351 webgpu::CanvasContext* GetWebGPUContext();
353 bool IsOffscreen() const { return !!mOffscreenCanvas; }
354 OffscreenCanvas* GetOffscreenCanvas() const { return mOffscreenCanvas; }
355 void FlushOffscreenCanvas();
357 layers::ImageContainer* GetImageContainer() const { return mImageContainer; }
359 protected:
360 bool mResetLayer;
361 bool mMaybeModified; // we fetched the context, so we may have written to the
362 // canvas
363 RefPtr<HTMLCanvasElement> mOriginalCanvas;
364 RefPtr<PrintCallback> mPrintCallback;
365 RefPtr<HTMLCanvasPrintState> mPrintState;
366 nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
367 RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
368 RefPtr<OffscreenCanvas> mOffscreenCanvas;
369 RefPtr<OffscreenCanvasDisplayHelper> mOffscreenDisplay;
370 RefPtr<layers::ImageContainer> mImageContainer;
371 RefPtr<HTMLCanvasElementObserver> mContextObserver;
373 public:
374 // Record whether this canvas should be write-only or not.
375 // We set this when script paints an image from a different origin.
376 // We also transitively set it when script paints a canvas which
377 // is itself write-only.
378 bool mWriteOnly;
380 // When this canvas is (only) tainted by an image from an extension
381 // content script, allow reads from the same extension afterwards.
382 RefPtr<nsIPrincipal> mExpandedReader;
384 // Determines if the caller should be able to read the content.
385 bool CallerCanRead(nsIPrincipal& aPrincipal) const;
387 bool IsPrintCallbackDone();
389 void HandlePrintCallback(nsPresContext*);
391 nsresult DispatchPrintCallback(nsITimerCallback* aCallback);
393 void ResetPrintCallback();
395 HTMLCanvasElement* GetOriginalCanvas();
397 CanvasContextType GetCurrentContextType();
399 private:
401 * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
402 * This function will be called by AfterSetAttr whether the attribute is being
403 * set or unset.
405 * @param aNamespaceID the namespace of the attr being set
406 * @param aName the localname of the attribute being set
407 * @param aNotify Whether we plan to notify document observers.
409 void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName, bool aNotify);
412 class HTMLCanvasPrintState final : public nsWrapperCache {
413 public:
414 HTMLCanvasPrintState(HTMLCanvasElement* aCanvas,
415 nsICanvasRenderingContextInternal* aContext,
416 nsITimerCallback* aCallback);
418 nsISupports* Context() const;
420 void Done();
422 void NotifyDone();
424 bool mIsDone;
426 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLCanvasPrintState)
427 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(HTMLCanvasPrintState)
429 virtual JSObject* WrapObject(JSContext* cx,
430 JS::Handle<JSObject*> aGivenProto) override;
432 HTMLCanvasElement* GetParentObject() { return mCanvas; }
434 private:
435 ~HTMLCanvasPrintState();
436 bool mPendingNotify;
438 protected:
439 RefPtr<HTMLCanvasElement> mCanvas;
440 nsCOMPtr<nsICanvasRenderingContextInternal> mContext;
441 nsCOMPtr<nsITimerCallback> mCallback;
444 } // namespace dom
445 } // namespace mozilla
447 #endif /* mozilla_dom_HTMLCanvasElement_h */