Backed out changeset 62f7af8fe549 (bug 1843981) for causing valgrind bustage. CLOSED...
[gecko.git] / dom / html / HTMLCanvasElement.h
blob28228f7abca5002aa24eaf00c4399d52cd9121d5
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 * Determine whether the canvas is write-only.
181 bool IsWriteOnly() const;
184 * Force the canvas to be write-only, except for readers from
185 * a specific extension's content script expanded principal, if
186 * available.
188 void SetWriteOnly(nsIPrincipal* aExpandedReader = nullptr);
191 * Notify the placeholder offscreen canvas of an updated size.
193 void InvalidateCanvasPlaceholder(uint32_t aWidth, uint32_t aHeight);
196 * Notify that some canvas content has changed and the window may
197 * need to be updated. aDamageRect is in canvas coordinates.
199 void InvalidateCanvasContent(const mozilla::gfx::Rect* aDamageRect);
201 * Notify that we need to repaint the entire canvas, including updating of
202 * the layer tree.
204 void InvalidateCanvas();
206 nsICanvasRenderingContextInternal* GetCurrentContext() {
207 return mCurrentContext;
211 * Returns true if the canvas context content is guaranteed to be opaque
212 * across its entire area.
214 bool GetIsOpaque();
215 virtual bool GetOpaqueAttr() override;
218 * Retrieve a snapshot of the internal surface, returning the alpha type if
219 * requested. An optional target may be supplied for which the snapshot will
220 * be optimized for, if possible.
222 virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(
223 gfxAlphaType* aOutAlphaType = nullptr,
224 gfx::DrawTarget* aTarget = nullptr);
227 * Register a FrameCaptureListener with this canvas.
228 * The canvas hooks into the RefreshDriver while there are
229 * FrameCaptureListeners registered.
230 * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the
231 * caller's responsibility to keep them alive. Once a registered
232 * FrameCaptureListener is destroyed it will be automatically deregistered.
234 nsresult RegisterFrameCaptureListener(FrameCaptureListener* aListener,
235 bool aReturnPlaceholderData);
238 * Returns true when there is at least one registered FrameCaptureListener
239 * that has requested a frame capture.
241 bool IsFrameCaptureRequested(const TimeStamp& aTime) const;
244 * Processes destroyed FrameCaptureListeners and removes them if necessary.
245 * Should there be none left, the FrameRefreshObserver will be unregistered.
247 void ProcessDestroyedFrameListeners();
250 * Called by the RefreshDriver hook when a frame has been captured.
251 * Makes a copy of the provided surface and hands it to all
252 * FrameCaptureListeners having requested frame capture.
254 void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface,
255 const TimeStamp& aTime);
257 virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
258 const nsAString& aValue,
259 nsIPrincipal* aMaybeScriptedPrincipal,
260 nsAttrValue& aResult) override;
261 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
262 nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
263 int32_t aModType) const override;
264 nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
266 virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
267 nsresult CopyInnerTo(HTMLCanvasElement* aDest);
269 static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
272 * Helpers called by various users of Canvas
275 already_AddRefed<layers::Image> GetAsImage();
276 bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
277 WebRenderCanvasData* aCanvasData);
278 bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
279 CanvasRenderer* aRenderer);
281 // Call this whenever we need future changes to the canvas
282 // to trigger fresh invalidation requests. This needs to be called
283 // whenever we render the canvas contents to the screen, or whenever we
284 // take a snapshot of the canvas that needs to be "live" (e.g. -moz-element).
285 void MarkContextClean();
287 // Call this after capturing a frame, so we can avoid unnecessary surface
288 // copies for future frames when no drawing has occurred.
289 void MarkContextCleanForFrameCapture();
291 // Returns non-null when the current context supports captureStream().
292 // The FrameCaptureState gets set to DIRTY when something is drawn.
293 Watchable<FrameCaptureState>* GetFrameCaptureState();
295 nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
297 layers::LayersBackend GetCompositorBackendType() const;
299 void OnMemoryPressure();
300 void OnDeviceReset();
302 already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
303 void ClearVRFrame();
305 bool MaybeModified() const { return mMaybeModified; };
307 protected:
308 virtual ~HTMLCanvasElement();
309 void Destroy();
311 virtual JSObject* WrapNode(JSContext* aCx,
312 JS::Handle<JSObject*> aGivenProto) override;
314 virtual nsIntSize GetWidthHeight() override;
316 virtual already_AddRefed<nsICanvasRenderingContextInternal> CreateContext(
317 CanvasContextType aContextType) override;
319 nsresult UpdateContext(JSContext* aCx,
320 JS::Handle<JS::Value> aNewContextOptions,
321 ErrorResult& aRvForDictionaryInit) override;
323 nsresult ExtractData(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
324 nsAString& aType, const nsAString& aOptions,
325 nsIInputStream** aStream);
326 nsresult ToDataURLImpl(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
327 const nsAString& aMimeType,
328 const JS::Value& aEncoderOptions, nsAString& aDataURL);
330 UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aOutFormat,
331 gfx::IntSize* aOutImageSize) override;
333 MOZ_CAN_RUN_SCRIPT void CallPrintCallback();
335 virtual void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
336 const nsAttrValue* aValue,
337 const nsAttrValue* aOldValue,
338 nsIPrincipal* aSubjectPrincipal,
339 bool aNotify) override;
340 virtual void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
341 const nsAttrValueOrString& aValue,
342 bool aNotify) override;
344 public:
345 ClientWebGLContext* GetWebGLContext();
346 webgpu::CanvasContext* GetWebGPUContext();
348 bool IsOffscreen() const { return !!mOffscreenCanvas; }
349 OffscreenCanvas* GetOffscreenCanvas() const { return mOffscreenCanvas; }
350 void FlushOffscreenCanvas();
352 layers::ImageContainer* GetImageContainer() const { return mImageContainer; }
354 protected:
355 bool mResetLayer;
356 bool mMaybeModified; // we fetched the context, so we may have written to the
357 // canvas
358 RefPtr<HTMLCanvasElement> mOriginalCanvas;
359 RefPtr<PrintCallback> mPrintCallback;
360 RefPtr<HTMLCanvasPrintState> mPrintState;
361 nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
362 RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
363 RefPtr<OffscreenCanvas> mOffscreenCanvas;
364 RefPtr<OffscreenCanvasDisplayHelper> mOffscreenDisplay;
365 RefPtr<layers::ImageContainer> mImageContainer;
366 RefPtr<HTMLCanvasElementObserver> mContextObserver;
368 public:
369 // Record whether this canvas should be write-only or not.
370 // We set this when script paints an image from a different origin.
371 // We also transitively set it when script paints a canvas which
372 // is itself write-only.
373 bool mWriteOnly;
375 // When this canvas is (only) tainted by an image from an extension
376 // content script, allow reads from the same extension afterwards.
377 RefPtr<nsIPrincipal> mExpandedReader;
379 // Determines if the caller should be able to read the content.
380 bool CallerCanRead(nsIPrincipal& aPrincipal) const;
382 bool IsPrintCallbackDone();
384 void HandlePrintCallback(nsPresContext*);
386 nsresult DispatchPrintCallback(nsITimerCallback* aCallback);
388 void ResetPrintCallback();
390 HTMLCanvasElement* GetOriginalCanvas();
392 CanvasContextType GetCurrentContextType();
394 private:
396 * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
397 * This function will be called by AfterSetAttr whether the attribute is being
398 * set or unset.
400 * @param aNamespaceID the namespace of the attr being set
401 * @param aName the localname of the attribute being set
402 * @param aNotify Whether we plan to notify document observers.
404 void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName, bool aNotify);
407 class HTMLCanvasPrintState final : public nsWrapperCache {
408 public:
409 HTMLCanvasPrintState(HTMLCanvasElement* aCanvas,
410 nsICanvasRenderingContextInternal* aContext,
411 nsITimerCallback* aCallback);
413 nsISupports* Context() const;
415 void Done();
417 void NotifyDone();
419 bool mIsDone;
421 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLCanvasPrintState)
422 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(HTMLCanvasPrintState)
424 virtual JSObject* WrapObject(JSContext* cx,
425 JS::Handle<JSObject*> aGivenProto) override;
427 HTMLCanvasElement* GetParentObject() { return mCanvas; }
429 private:
430 ~HTMLCanvasPrintState();
431 bool mPendingNotify;
433 protected:
434 RefPtr<HTMLCanvasElement> mCanvas;
435 nsCOMPtr<nsICanvasRenderingContextInternal> mContext;
436 nsCOMPtr<nsITimerCallback> mCallback;
439 } // namespace dom
440 } // namespace mozilla
442 #endif /* mozilla_dom_HTMLCanvasElement_h */