HTMLCanvasElement.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #if !defined(mozilla_dom_HTMLCanvasElement_h)
  6. #define mozilla_dom_HTMLCanvasElement_h
  7. #include "mozilla/Attributes.h"
  8. #include "mozilla/WeakPtr.h"
  9. #include "nsIDOMEventListener.h"
  10. #include "nsIDOMHTMLCanvasElement.h"
  11. #include "nsIObserver.h"
  12. #include "nsGenericHTMLElement.h"
  13. #include "nsGkAtoms.h"
  14. #include "nsSize.h"
  15. #include "nsError.h"
  16. #include "mozilla/dom/CanvasRenderingContextHelper.h"
  17. #include "mozilla/gfx/Rect.h"
  18. #include "mozilla/layers/LayersTypes.h"
  19. class nsICanvasRenderingContextInternal;
  20. class nsITimerCallback;
  21. namespace mozilla {
  22. class WebGLContext;
  23. namespace layers {
  24. class AsyncCanvasRenderer;
  25. class CanvasLayer;
  26. class Image;
  27. class Layer;
  28. class LayerManager;
  29. class SharedSurfaceTextureClient;
  30. } // namespace layers
  31. namespace gfx {
  32. class SourceSurface;
  33. class VRLayerChild;
  34. } // namespace gfx
  35. namespace dom {
  36. class BlobCallback;
  37. class CanvasCaptureMediaStream;
  38. class File;
  39. class HTMLCanvasPrintState;
  40. class OffscreenCanvas;
  41. class PrintCallback;
  42. class RequestedFrameRefreshObserver;
  43. // Listen visibilitychange and memory-pressure event and inform
  44. // context when event is fired.
  45. class HTMLCanvasElementObserver final : public nsIObserver
  46. , public nsIDOMEventListener
  47. {
  48. public:
  49. NS_DECL_ISUPPORTS
  50. NS_DECL_NSIOBSERVER
  51. NS_DECL_NSIDOMEVENTLISTENER
  52. explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement);
  53. void Destroy();
  54. void RegisterVisibilityChangeEvent();
  55. void UnregisterVisibilityChangeEvent();
  56. void RegisterMemoryPressureEvent();
  57. void UnregisterMemoryPressureEvent();
  58. private:
  59. ~HTMLCanvasElementObserver();
  60. HTMLCanvasElement* mElement;
  61. };
  62. /*
  63. * FrameCaptureListener is used by captureStream() as a way of getting video
  64. * frames from the canvas. On a refresh driver tick after something has been
  65. * drawn to the canvas since the last such tick, all registered
  66. * FrameCaptureListeners whose `mFrameCaptureRequested` equals `true`,
  67. * will be given a copy of the just-painted canvas.
  68. * All FrameCaptureListeners get the same copy.
  69. */
  70. class FrameCaptureListener : public SupportsWeakPtr<FrameCaptureListener>
  71. {
  72. public:
  73. MOZ_DECLARE_WEAKREFERENCE_TYPENAME(FrameCaptureListener)
  74. FrameCaptureListener()
  75. : mFrameCaptureRequested(false) {}
  76. /*
  77. * Called when a frame capture is desired on next paint.
  78. */
  79. void RequestFrameCapture() { mFrameCaptureRequested = true; }
  80. /*
  81. * Indicates to the canvas whether or not this listener has requested a frame.
  82. */
  83. bool FrameCaptureRequested() const { return mFrameCaptureRequested; }
  84. /*
  85. * Interface through which new video frames will be provided while
  86. * `mFrameCaptureRequested` is `true`.
  87. */
  88. virtual void NewFrame(already_AddRefed<layers::Image> aImage) = 0;
  89. protected:
  90. virtual ~FrameCaptureListener() {}
  91. bool mFrameCaptureRequested;
  92. };
  93. class HTMLCanvasElement final : public nsGenericHTMLElement,
  94. public nsIDOMHTMLCanvasElement,
  95. public CanvasRenderingContextHelper
  96. {
  97. enum {
  98. DEFAULT_CANVAS_WIDTH = 300,
  99. DEFAULT_CANVAS_HEIGHT = 150
  100. };
  101. typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
  102. typedef layers::CanvasLayer CanvasLayer;
  103. typedef layers::Layer Layer;
  104. typedef layers::LayerManager LayerManager;
  105. public:
  106. explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
  107. NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLCanvasElement, canvas)
  108. // nsISupports
  109. NS_DECL_ISUPPORTS_INHERITED
  110. // nsIDOMHTMLCanvasElement
  111. NS_DECL_NSIDOMHTMLCANVASELEMENT
  112. // CC
  113. NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLCanvasElement,
  114. nsGenericHTMLElement)
  115. // WebIDL
  116. uint32_t Height()
  117. {
  118. return GetUnsignedIntAttr(nsGkAtoms::height, DEFAULT_CANVAS_HEIGHT);
  119. }
  120. void SetHeight(uint32_t aHeight, ErrorResult& aRv)
  121. {
  122. if (mOffscreenCanvas) {
  123. aRv.Throw(NS_ERROR_FAILURE);
  124. return;
  125. }
  126. SetUnsignedIntAttr(nsGkAtoms::height, aHeight, DEFAULT_CANVAS_HEIGHT, aRv);
  127. }
  128. uint32_t Width()
  129. {
  130. return GetUnsignedIntAttr(nsGkAtoms::width, DEFAULT_CANVAS_WIDTH);
  131. }
  132. void SetWidth(uint32_t aWidth, ErrorResult& aRv)
  133. {
  134. if (mOffscreenCanvas) {
  135. aRv.Throw(NS_ERROR_FAILURE);
  136. return;
  137. }
  138. SetUnsignedIntAttr(nsGkAtoms::width, aWidth, DEFAULT_CANVAS_WIDTH, aRv);
  139. }
  140. virtual already_AddRefed<nsISupports>
  141. GetContext(JSContext* aCx, const nsAString& aContextId,
  142. JS::Handle<JS::Value> aContextOptions,
  143. ErrorResult& aRv) override;
  144. void ToDataURL(JSContext* aCx, const nsAString& aType,
  145. JS::Handle<JS::Value> aParams,
  146. nsAString& aDataURL, ErrorResult& aRv)
  147. {
  148. aRv = ToDataURL(aType, aParams, aCx, aDataURL);
  149. }
  150. void ToBlob(JSContext* aCx,
  151. BlobCallback& aCallback,
  152. const nsAString& aType,
  153. JS::Handle<JS::Value> aParams,
  154. ErrorResult& aRv);
  155. OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
  156. bool MozOpaque() const
  157. {
  158. return GetBoolAttr(nsGkAtoms::moz_opaque);
  159. }
  160. void SetMozOpaque(bool aValue, ErrorResult& aRv)
  161. {
  162. if (mOffscreenCanvas) {
  163. aRv.Throw(NS_ERROR_FAILURE);
  164. return;
  165. }
  166. SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
  167. }
  168. already_AddRefed<File> MozGetAsFile(const nsAString& aName,
  169. const nsAString& aType,
  170. ErrorResult& aRv);
  171. already_AddRefed<nsISupports> MozGetIPCContext(const nsAString& aContextId,
  172. ErrorResult& aRv)
  173. {
  174. nsCOMPtr<nsISupports> context;
  175. aRv = MozGetIPCContext(aContextId, getter_AddRefs(context));
  176. return context.forget();
  177. }
  178. PrintCallback* GetMozPrintCallback() const;
  179. void SetMozPrintCallback(PrintCallback* aCallback);
  180. already_AddRefed<CanvasCaptureMediaStream>
  181. CaptureStream(const Optional<double>& aFrameRate, ErrorResult& aRv);
  182. /**
  183. * Get the size in pixels of this canvas element
  184. */
  185. nsIntSize GetSize();
  186. /**
  187. * Determine whether the canvas is write-only (tainted).
  188. */
  189. bool IsWriteOnly() const;
  190. /**
  191. * Force the canvas to be write-only.
  192. */
  193. void SetWriteOnly();
  194. /**
  195. * Notify that some canvas content has changed and the window may
  196. * need to be updated. aDamageRect is in canvas coordinates.
  197. */
  198. void InvalidateCanvasContent(const mozilla::gfx::Rect* aDamageRect);
  199. /*
  200. * Notify that we need to repaint the entire canvas, including updating of
  201. * the layer tree.
  202. */
  203. void InvalidateCanvas();
  204. /*
  205. * Get the number of contexts in this canvas, and request a context at
  206. * an index.
  207. */
  208. int32_t CountContexts ();
  209. nsICanvasRenderingContextInternal *GetContextAtIndex (int32_t index);
  210. /*
  211. * Returns true if the canvas context content is guaranteed to be opaque
  212. * across its entire area.
  213. */
  214. bool GetIsOpaque();
  215. virtual bool GetOpaqueAttr() override;
  216. virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr);
  217. /*
  218. * Register a FrameCaptureListener with this canvas.
  219. * The canvas hooks into the RefreshDriver while there are
  220. * FrameCaptureListeners registered.
  221. * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the
  222. * caller's responsibility to keep them alive. Once a registered
  223. * FrameCaptureListener is destroyed it will be automatically deregistered.
  224. */
  225. nsresult RegisterFrameCaptureListener(FrameCaptureListener* aListener);
  226. /*
  227. * Returns true when there is at least one registered FrameCaptureListener
  228. * that has requested a frame capture.
  229. */
  230. bool IsFrameCaptureRequested() const;
  231. /*
  232. * Processes destroyed FrameCaptureListeners and removes them if necessary.
  233. * Should there be none left, the FrameRefreshObserver will be unregistered.
  234. */
  235. void ProcessDestroyedFrameListeners();
  236. /*
  237. * Called by the RefreshDriver hook when a frame has been captured.
  238. * Makes a copy of the provided surface and hands it to all
  239. * FrameCaptureListeners having requested frame capture.
  240. */
  241. void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface);
  242. virtual bool ParseAttribute(int32_t aNamespaceID,
  243. nsIAtom* aAttribute,
  244. const nsAString& aValue,
  245. nsAttrValue& aResult) override;
  246. nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, int32_t aModType) const override;
  247. virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
  248. nsresult CopyInnerTo(mozilla::dom::Element* aDest);
  249. virtual nsresult GetEventTargetParent(
  250. mozilla::EventChainPreVisitor& aVisitor) override;
  251. /*
  252. * Helpers called by various users of Canvas
  253. */
  254. already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
  255. Layer *aOldLayer,
  256. LayerManager *aManager);
  257. // Should return true if the canvas layer should always be marked inactive.
  258. // We should return true here if we can't do accelerated compositing with
  259. // a non-BasicCanvasLayer.
  260. bool ShouldForceInactiveLayer(LayerManager *aManager);
  261. // Call this whenever we need future changes to the canvas
  262. // to trigger fresh invalidation requests. This needs to be called
  263. // whenever we render the canvas contents to the screen, or whenever we
  264. // take a snapshot of the canvas that needs to be "live" (e.g. -moz-element).
  265. void MarkContextClean();
  266. // Call this after capturing a frame, so we can avoid unnecessary surface
  267. // copies for future frames when no drawing has occurred.
  268. void MarkContextCleanForFrameCapture();
  269. // Starts returning false when something is drawn.
  270. bool IsContextCleanForFrameCapture();
  271. nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
  272. layers::LayersBackend GetCompositorBackendType() const;
  273. void OnVisibilityChange();
  274. void OnMemoryPressure();
  275. static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
  276. static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
  277. protected:
  278. virtual ~HTMLCanvasElement();
  279. virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
  280. virtual nsIntSize GetWidthHeight() override;
  281. virtual already_AddRefed<nsICanvasRenderingContextInternal>
  282. CreateContext(CanvasContextType aContextType) override;
  283. nsresult ExtractData(nsAString& aType,
  284. const nsAString& aOptions,
  285. nsIInputStream** aStream);
  286. nsresult ToDataURLImpl(JSContext* aCx,
  287. const nsAString& aMimeType,
  288. const JS::Value& aEncoderOptions,
  289. nsAString& aDataURL);
  290. nsresult MozGetAsBlobImpl(const nsAString& aName,
  291. const nsAString& aType,
  292. nsISupports** aResult);
  293. void CallPrintCallback();
  294. virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
  295. const nsAttrValue* aValue,
  296. const nsAttrValue* aOldValue,
  297. bool aNotify) override;
  298. virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName,
  299. const nsAttrValueOrString& aValue,
  300. bool aNotify) override;
  301. AsyncCanvasRenderer* GetAsyncCanvasRenderer();
  302. bool mResetLayer;
  303. RefPtr<HTMLCanvasElement> mOriginalCanvas;
  304. RefPtr<PrintCallback> mPrintCallback;
  305. RefPtr<HTMLCanvasPrintState> mPrintState;
  306. nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
  307. RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
  308. RefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer;
  309. RefPtr<OffscreenCanvas> mOffscreenCanvas;
  310. RefPtr<HTMLCanvasElementObserver> mContextObserver;
  311. bool mVRPresentationActive;
  312. public:
  313. // Record whether this canvas should be write-only or not.
  314. // We set this when script paints an image from a different origin.
  315. // We also transitively set it when script paints a canvas which
  316. // is itself write-only.
  317. bool mWriteOnly;
  318. bool IsPrintCallbackDone();
  319. void HandlePrintCallback(nsPresContext::nsPresContextType aType);
  320. nsresult DispatchPrintCallback(nsITimerCallback* aCallback);
  321. void ResetPrintCallback();
  322. HTMLCanvasElement* GetOriginalCanvas();
  323. CanvasContextType GetCurrentContextType() {
  324. return mCurrentContextType;
  325. }
  326. private:
  327. /**
  328. * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
  329. * This function will be called by AfterSetAttr whether the attribute is being
  330. * set or unset.
  331. *
  332. * @param aNamespaceID the namespace of the attr being set
  333. * @param aName the localname of the attribute being set
  334. * @param aNotify Whether we plan to notify document observers.
  335. */
  336. void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, bool aNotify);
  337. };
  338. class HTMLCanvasPrintState final : public nsWrapperCache
  339. {
  340. public:
  341. HTMLCanvasPrintState(HTMLCanvasElement* aCanvas,
  342. nsICanvasRenderingContextInternal* aContext,
  343. nsITimerCallback* aCallback);
  344. nsISupports* Context() const;
  345. void Done();
  346. void NotifyDone();
  347. bool mIsDone;
  348. NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLCanvasPrintState)
  349. NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(HTMLCanvasPrintState)
  350. virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
  351. HTMLCanvasElement* GetParentObject()
  352. {
  353. return mCanvas;
  354. }
  355. private:
  356. ~HTMLCanvasPrintState();
  357. bool mPendingNotify;
  358. protected:
  359. RefPtr<HTMLCanvasElement> mCanvas;
  360. nsCOMPtr<nsICanvasRenderingContextInternal> mContext;
  361. nsCOMPtr<nsITimerCallback> mCallback;
  362. };
  363. } // namespace dom
  364. } // namespace mozilla
  365. #endif /* mozilla_dom_HTMLCanvasElement_h */