Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 :
7 : #ifndef MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
8 : #define MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
9 :
10 : #include "LayersTypes.h"
11 : #include "mozilla/gfx/Point.h" // for IntSize
12 : #include "mozilla/Mutex.h"
13 : #include "nsCOMPtr.h" // for nsCOMPtr
14 :
15 : class nsICanvasRenderingContextInternal;
16 : class nsIInputStream;
17 : class nsISerialEventTarget;
18 :
19 : namespace mozilla {
20 :
21 : namespace gfx {
22 : class DataSourceSurface;
23 : }
24 :
25 : namespace gl {
26 : class GLContext;
27 : }
28 :
29 : namespace dom {
30 : class HTMLCanvasElement;
31 : }
32 :
33 : namespace layers {
34 :
35 : class CanvasClient;
36 : class TextureClient;
37 :
38 : /**
39 : * Since HTMLCanvasElement and OffscreenCanvas are not thread-safe, we create
40 : * AsyncCanvasRenderer which is thread-safe wrapper object for communicating
41 : * among main, worker and ImageBridgeChild threads.
42 : *
43 : * Each HTMLCanvasElement object is responsible for creating
44 : * AsyncCanvasRenderer object. Once Canvas is transfered to worker,
45 : * OffscreenCanvas will keep reference pointer of this object.
46 : *
47 : * Sometimes main thread needs AsyncCanvasRenderer's result, such as layers
48 : * fallback to BasicLayerManager or calling toDataURL in Javascript. Simply call
49 : * GetSurface() in main thread will readback the result to mSurface.
50 : *
51 : * If layers backend is LAYERS_CLIENT, this object will pass to ImageBridgeChild
52 : * for submitting frames to Compositor.
53 : */
54 : class AsyncCanvasRenderer final
55 : {
56 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncCanvasRenderer)
57 :
58 : public:
59 : AsyncCanvasRenderer();
60 :
61 : void NotifyElementAboutAttributesChanged();
62 : void NotifyElementAboutInvalidation();
63 :
64 : void SetCanvasClient(CanvasClient* aClient);
65 :
66 0 : void SetWidth(uint32_t aWidth)
67 : {
68 0 : mWidth = aWidth;
69 0 : }
70 :
71 0 : void SetHeight(uint32_t aHeight)
72 : {
73 0 : mHeight = aHeight;
74 0 : }
75 :
76 0 : void SetIsAlphaPremultiplied(bool aIsAlphaPremultiplied)
77 : {
78 0 : mIsAlphaPremultiplied = aIsAlphaPremultiplied;
79 0 : }
80 :
81 : // Active thread means the thread which spawns GLContext.
82 : void SetActiveEventTarget();
83 : void ResetActiveEventTarget();
84 :
85 : // This will readback surface and return the surface
86 : // in the DataSourceSurface.
87 : // Can be called in main thread only.
88 : already_AddRefed<gfx::DataSourceSurface> GetSurface();
89 :
90 : // For SharedSurface_Basic case, before the frame sending to the compositor,
91 : // we readback it to a texture client because SharedSurface_Basic cannot shared.
92 : // We don't want to readback it again here, so just copy the content of that
93 : // texture client here to avoid readback again.
94 : void CopyFromTextureClient(TextureClient *aClient);
95 :
96 : // Readback current WebGL's content and convert it to InputStream. This
97 : // function called GetSurface implicitly and GetSurface handles only get
98 : // called in the main thread. So this function can be called in main thread.
99 : nsresult
100 : GetInputStream(const char *aMimeType,
101 : const char16_t *aEncoderOptions,
102 : nsIInputStream **aStream);
103 :
104 0 : gfx::IntSize GetSize() const
105 : {
106 0 : return gfx::IntSize(mWidth, mHeight);
107 : }
108 :
109 0 : CompositableHandle GetCanvasClientAsyncHandle() const
110 : {
111 0 : return mCanvasClientAsyncHandle;
112 : }
113 :
114 0 : CanvasClient* GetCanvasClient() const
115 : {
116 0 : return mCanvasClient;
117 : }
118 :
119 : already_AddRefed<nsISerialEventTarget> GetActiveEventTarget();
120 :
121 : // The lifetime is controllered by HTMLCanvasElement.
122 : // Only accessed in main thread.
123 : dom::HTMLCanvasElement* mHTMLCanvasElement;
124 :
125 : // Only accessed in active thread.
126 : nsICanvasRenderingContextInternal* mContext;
127 :
128 : // We need to keep a reference to the context around here, otherwise the
129 : // canvas' surface texture destructor will deref and destroy it too early
130 : // Only accessed in active thread.
131 : RefPtr<gl::GLContext> mGLContext;
132 : private:
133 :
134 : virtual ~AsyncCanvasRenderer();
135 :
136 : // Readback current WebGL's content and return it as DataSourceSurface.
137 : already_AddRefed<gfx::DataSourceSurface> UpdateTarget();
138 :
139 : bool mIsAlphaPremultiplied;
140 :
141 : uint32_t mWidth;
142 : uint32_t mHeight;
143 : CompositableHandle mCanvasClientAsyncHandle;
144 :
145 : // The lifetime of this pointer is controlled by OffscreenCanvas
146 : // Can be accessed in active thread and ImageBridge thread.
147 : // But we never accessed it at the same time on both thread. So no
148 : // need to protect this member.
149 : CanvasClient* mCanvasClient;
150 :
151 : // When backend is LAYER_BASIC and SharedSurface type is Basic.
152 : // CanvasClient will readback the GLContext to a TextureClient
153 : // in order to send frame to compositor. To avoid readback again,
154 : // we copy from this TextureClient to this mSurfaceForBasic directly
155 : // by calling CopyFromTextureClient().
156 : RefPtr<gfx::DataSourceSurface> mSurfaceForBasic;
157 :
158 : // Protect non thread-safe objects.
159 : Mutex mMutex;
160 :
161 : // Can be accessed in any thread, need protect by mutex.
162 : nsCOMPtr<nsISerialEventTarget> mActiveEventTarget;
163 : };
164 :
165 : } // namespace layers
166 : } // namespace mozilla
167 :
168 : #endif // MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
|