Source code

Revision control

Other Tools

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