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/. */
7 #ifndef MOZILLA_LAYERS_RENDERTHREAD_H
8 #define MOZILLA_LAYERS_RENDERTHREAD_H
10 #include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS
11 #include "base/platform_thread.h" // for PlatformThreadId
12 #include "base/thread.h" // for Thread
13 #include "base/message_loop.h"
14 #include "GLTypes.h" // for GLenum
15 #include "nsISupportsImpl.h"
16 #include "mozilla/gfx/Point.h"
17 #include "mozilla/MozPromise.h"
18 #include "mozilla/DataMutex.h"
19 #include "mozilla/Maybe.h"
20 #include "mozilla/webrender/webrender_ffi.h"
21 #include "mozilla/UniquePtr.h"
22 #include "mozilla/webrender/WebRenderTypes.h"
23 #include "mozilla/layers/CompositionRecorder.h"
24 #include "mozilla/layers/SynchronousTask.h"
25 #include "mozilla/UniquePtr.h"
26 #include "mozilla/VsyncDispatcher.h"
30 #include <unordered_map>
37 class CompositorBridgeParent
;
38 class ShaderProgramOGLsHolder
;
43 typedef MozPromise
<MemoryReport
, bool, true> MemoryReportPromise
;
46 class RenderTextureHost
;
49 /// A rayon thread pool that is shared by all WebRender instances within a
51 class WebRenderThreadPool
{
53 explicit WebRenderThreadPool(bool low_priority
);
55 ~WebRenderThreadPool();
57 wr::WrThreadPool
* Raw() {
58 // If this pointer is null we are likely at some late shutdown stage,
59 // when threads are no longer safe to interact with.
60 MOZ_RELEASE_ASSERT(mThreadPool
);
64 /// Prematurely destroys this handle to the thread pool.
65 /// After calling this the object is useless.
69 wr::WrThreadPool
* mThreadPool
;
72 class WebRenderProgramCache final
{
74 explicit WebRenderProgramCache(wr::WrThreadPool
* aThreadPool
);
76 ~WebRenderProgramCache();
78 wr::WrProgramCache
* Raw() { return mProgramCache
; }
81 wr::WrProgramCache
* mProgramCache
;
84 class WebRenderShaders final
{
86 WebRenderShaders(gl::GLContext
* gl
, WebRenderProgramCache
* programCache
);
89 wr::WrShaders
* RawShaders() { return mShaders
; }
92 RefPtr
<gl::GLContext
> mGL
;
93 wr::WrShaders
* mShaders
;
96 class WebRenderPipelineInfo final
{
97 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderPipelineInfo
);
99 const wr::WrPipelineInfo
& Raw() const { return mPipelineInfo
; }
100 wr::WrPipelineInfo
& Raw() { return mPipelineInfo
; }
103 ~WebRenderPipelineInfo() = default;
104 wr::WrPipelineInfo mPipelineInfo
;
107 /// Base class for an event that can be scheduled to run on the render thread.
109 /// The event can be passed through the same channels as regular WebRender
110 /// messages to preserve ordering.
111 class RendererEvent
{
113 virtual ~RendererEvent() = default;
114 virtual void Run(RenderThread
& aRenderThread
, wr::WindowId aWindow
) = 0;
117 /// The render thread is where WebRender issues all of its GPU work, and as much
118 /// as possible this thread should only serve this purpose.
120 /// The render thread owns the different RendererOGLs (one per window) and
121 /// implements the RenderNotifier api exposed by the WebRender bindings.
123 /// Callers are not allowed to post tasks to the render thread's event loop
124 /// directly and must instead use the RendererEvent mechanism which avoids races
125 /// between the events and WebRender's own messages.
127 /// The GL context(s) should be created and used on this thread only.
128 /// XXX - I've tried to organize code so that we can potentially avoid making
129 /// this a singleton since this bad habit has a tendency to bite us later, but
130 /// I haven't gotten all the way there either, in order to focus on the more
131 /// important pieces first. So we are a bit in-between (this is totally a
132 /// singleton but in some places we pretend it's not). Hopefully we can evolve
133 /// this in a way that keeps the door open to removing the singleton bits.
134 class RenderThread final
{
135 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(RenderThread
)
138 /// Can be called from any thread.
139 static RenderThread
* Get();
141 /// Can only be called from the main thread.
142 static void Start(uint32_t aNamespace
);
144 /// Can only be called from the main thread.
145 static void ShutDown();
147 /// Can be called from any thread.
148 static bool IsInRenderThread();
150 /// Can be called from any thread.
151 static already_AddRefed
<nsIThread
> GetRenderThread();
153 // Can be called from any thread. Dispatches an event to the Renderer thread
154 // to iterate over all Renderers, accumulates memory statistics, and resolves
155 // the return promise.
156 static RefPtr
<MemoryReportPromise
> AccumulateMemoryReport(
157 MemoryReport aInitial
);
159 /// Can only be called from the render thread.
160 void AddRenderer(wr::WindowId aWindowId
, UniquePtr
<RendererOGL
> aRenderer
);
162 /// Can only be called from the render thread.
163 void RemoveRenderer(wr::WindowId aWindowId
);
165 /// Can only be called from the render thread.
166 RendererOGL
* GetRenderer(wr::WindowId aWindowId
);
168 /// Automatically forwarded to the render thread.
169 void SetClearColor(wr::WindowId aWindowId
, wr::ColorF aColor
);
171 /// Automatically forwarded to the render thread.
172 void SetProfilerUI(wr::WindowId aWindowId
, const nsACString
& aUI
);
174 /// Automatically forwarded to the render thread.
175 void PipelineSizeChanged(wr::WindowId aWindowId
, uint64_t aPipelineId
,
176 float aWidth
, float aHeight
);
178 /// Post RendererEvent to the render thread.
179 void PostEvent(wr::WindowId aWindowId
, UniquePtr
<RendererEvent
> aEvent
);
181 /// Can only be called from the render thread.
182 void SetFramePublishId(wr::WindowId aWindowId
, FramePublishId aPublishId
);
184 /// Can only be called from the render thread.
185 void UpdateAndRender(wr::WindowId aWindowId
, const VsyncId
& aStartId
,
186 const TimeStamp
& aStartTime
, bool aRender
,
187 const Maybe
<gfx::IntSize
>& aReadbackSize
,
188 const Maybe
<wr::ImageFormat
>& aReadbackFormat
,
189 const Maybe
<Range
<uint8_t>>& aReadbackBuffer
,
190 bool* aNeedsYFlip
= nullptr);
192 void Pause(wr::WindowId aWindowId
);
193 bool Resume(wr::WindowId aWindowId
);
195 /// Can be called from any thread.
196 void RegisterExternalImage(const wr::ExternalImageId
& aExternalImageId
,
197 already_AddRefed
<RenderTextureHost
> aTexture
);
199 /// Can be called from any thread.
200 void UnregisterExternalImage(const wr::ExternalImageId
& aExternalImageId
);
202 /// Can be called from any thread.
203 void DestroyExternalImagesSyncWait(
204 const std::vector
<wr::ExternalImageId
>&& aIds
);
206 /// Can be called from any thread.
207 void PrepareForUse(const wr::ExternalImageId
& aExternalImageId
);
209 /// Can be called from any thread.
210 void NotifyNotUsed(const wr::ExternalImageId
& aExternalImageId
);
212 /// Can be called from any thread.
213 void NotifyForUse(const wr::ExternalImageId
& aExternalImageId
);
215 void HandleRenderTextureOps();
217 /// Can only be called from the render thread.
218 void UnregisterExternalImageDuringShutdown(
219 const wr::ExternalImageId
& aExternalImageId
);
221 /// Can only be called from the render thread.
222 RenderTextureHost
* GetRenderTexture(
223 const wr::ExternalImageId
& aExternalImageId
);
225 /// Can be called from any thread.
226 bool IsDestroyed(wr::WindowId aWindowId
);
227 /// Can be called from any thread.
228 void SetDestroyed(wr::WindowId aWindowId
);
229 /// Can be called from any thread.
230 bool TooManyPendingFrames(wr::WindowId aWindowId
);
231 /// Can be called from any thread.
232 void IncPendingFrameCount(wr::WindowId aWindowId
, const VsyncId
& aStartId
,
233 const TimeStamp
& aStartTime
);
234 /// Can be called from any thread.
235 void DecPendingFrameBuildCount(wr::WindowId aWindowId
);
236 void DecPendingFrameCount(wr::WindowId aWindowId
);
238 // RenderNotifier implementation
239 void WrNotifierEvent_WakeUp(WrWindowId aWindowId
, bool aCompositeNeeded
);
240 void WrNotifierEvent_NewFrameReady(WrWindowId aWindowId
,
241 bool aCompositeNeeded
,
242 FramePublishId aPublishId
);
243 void WrNotifierEvent_ExternalEvent(WrWindowId aWindowId
, size_t aRawEvent
);
245 /// Can be called from any thread.
246 WebRenderThreadPool
& ThreadPool() { return mThreadPool
; }
248 /// Thread pool for low priority scene building
249 /// Can be called from any thread.
250 WebRenderThreadPool
& ThreadPoolLP() { return mThreadPoolLP
; }
252 /// Returns the cache used to serialize shader programs to disk, if enabled.
254 /// Can only be called from the render thread.
255 WebRenderProgramCache
* GetProgramCache() {
256 MOZ_ASSERT(IsInRenderThread());
257 return mProgramCache
.get();
260 /// Can only be called from the render thread.
261 WebRenderShaders
* GetShaders() {
262 MOZ_ASSERT(IsInRenderThread());
263 return mShaders
.get();
266 /// Can only be called from the render thread.
267 gl::GLContext
* SingletonGL(nsACString
& aError
);
268 gl::GLContext
* SingletonGL();
269 gl::GLContext
* SingletonGLForCompositorOGL();
270 void ClearSingletonGL();
271 RefPtr
<layers::SurfacePool
> SharedSurfacePool();
272 void ClearSharedSurfacePool();
274 RefPtr
<layers::ShaderProgramOGLsHolder
> GetProgramsForCompositorOGL();
276 /// Can only be called from the render thread.
277 void HandleDeviceReset(const char* aWhere
, GLenum aReason
);
278 /// Can only be called from the render thread.
279 bool IsHandlingDeviceReset();
280 /// Can be called from any thread.
281 void SimulateDeviceReset();
283 /// Can only be called from the render thread.
284 void NotifyWebRenderError(WebRenderError aError
);
286 /// Can only be called from the render thread.
287 void HandleWebRenderError(WebRenderError aError
);
288 /// Can only be called from the render thread.
289 bool IsHandlingWebRenderError();
291 /// Can only be called from the render thread.
292 bool SyncObjectNeeded();
294 size_t RendererCount() const;
295 size_t ActiveRendererCount() const;
297 void BeginRecordingForWindow(wr::WindowId aWindowId
,
298 const TimeStamp
& aRecordingStart
,
299 wr::PipelineId aRootPipelineId
);
301 Maybe
<layers::FrameRecording
> EndRecordingForWindow(wr::WindowId aWindowId
);
303 static void MaybeEnableGLDebugMessage(gl::GLContext
* aGLContext
);
306 enum class RenderTextureOp
{
311 class WrNotifierEvent
{
321 WrNotifierEvent(const Tag aTag
, const bool aCompositeNeeded
)
322 : mTag(aTag
), mCompositeNeeded(aCompositeNeeded
) {
323 MOZ_ASSERT(mTag
== Tag::WakeUp
);
325 WrNotifierEvent(const Tag aTag
, bool aCompositeNeeded
,
326 FramePublishId aPublishId
)
328 mCompositeNeeded(aCompositeNeeded
),
329 mPublishId(aPublishId
) {
330 MOZ_ASSERT(mTag
== Tag::NewFrameReady
);
332 WrNotifierEvent(const Tag aTag
, UniquePtr
<RendererEvent
>&& aRendererEvent
)
333 : mTag(aTag
), mRendererEvent(std::move(aRendererEvent
)) {
334 MOZ_ASSERT(mTag
== Tag::ExternalEvent
);
337 const bool mCompositeNeeded
= false;
338 const FramePublishId mPublishId
= FramePublishId::INVALID
;
339 UniquePtr
<RendererEvent
> mRendererEvent
;
342 static WrNotifierEvent
WakeUp(const bool aCompositeNeeded
) {
343 return WrNotifierEvent(Tag::WakeUp
, aCompositeNeeded
);
346 static WrNotifierEvent
NewFrameReady(const bool aCompositeNeeded
,
347 const FramePublishId aPublishId
) {
348 return WrNotifierEvent(Tag::NewFrameReady
, aCompositeNeeded
, aPublishId
);
351 static WrNotifierEvent
ExternalEvent(
352 UniquePtr
<RendererEvent
>&& aRendererEvent
) {
353 return WrNotifierEvent(Tag::ExternalEvent
, std::move(aRendererEvent
));
356 bool CompositeNeeded() {
357 if (mTag
== Tag::WakeUp
|| mTag
== Tag::NewFrameReady
) {
358 return mCompositeNeeded
;
360 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
363 FramePublishId
PublishId() {
364 if (mTag
== Tag::NewFrameReady
) {
367 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
368 return FramePublishId::INVALID
;
370 UniquePtr
<RendererEvent
> ExternalEvent() {
371 if (mTag
== Tag::ExternalEvent
) {
372 MOZ_ASSERT(mRendererEvent
);
373 return std::move(mRendererEvent
);
375 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
380 explicit RenderThread(RefPtr
<nsIThread
> aThread
);
382 void HandleFrameOneDocInner(wr::WindowId aWindowId
, bool aRender
,
384 Maybe
<FramePublishId
> aPublishId
);
386 void DeferredRenderTextureHostDestroy();
388 void InitDeviceTask();
389 void HandleFrameOneDoc(wr::WindowId aWindowId
, bool aRender
,
390 bool aTrackedFrame
, Maybe
<FramePublishId
> aPublishId
);
391 void RunEvent(wr::WindowId aWindowId
, UniquePtr
<RendererEvent
> aEvent
);
392 void PostRunnable(already_AddRefed
<nsIRunnable
> aRunnable
);
394 void DoAccumulateMemoryReport(MemoryReport
,
395 const RefPtr
<MemoryReportPromise::Private
>&);
397 void AddRenderTextureOp(RenderTextureOp aOp
,
398 const wr::ExternalImageId
& aExternalImageId
);
400 void CreateSingletonGL(nsACString
& aError
);
402 void DestroyExternalImages(const std::vector
<wr::ExternalImageId
>&& aIds
);
406 void PostWrNotifierEvents(WrWindowId aWindowId
);
407 void PostWrNotifierEvents(WrWindowId aWindowId
, WindowInfo
* aInfo
);
408 void HandleWrNotifierEvents(WrWindowId aWindowId
);
409 void WrNotifierEvent_HandleWakeUp(wr::WindowId aWindowId
,
410 bool aCompositeNeeded
);
411 void WrNotifierEvent_HandleNewFrameReady(wr::WindowId aWindowId
,
412 bool aCompositeNeeded
,
413 FramePublishId aPublishId
);
414 void WrNotifierEvent_HandleExternalEvent(
415 wr::WindowId aWindowId
, UniquePtr
<RendererEvent
> aRendererEvent
);
419 RefPtr
<nsIThread
> const mThread
;
421 WebRenderThreadPool mThreadPool
;
422 WebRenderThreadPool mThreadPoolLP
;
424 UniquePtr
<WebRenderProgramCache
> mProgramCache
;
425 UniquePtr
<WebRenderShaders
> mShaders
;
426 RefPtr
<layers::ShaderProgramOGLsHolder
> mProgramsForCompositorOGL
;
428 // An optional shared GLContext to be used for all
430 RefPtr
<gl::GLContext
> mSingletonGL
;
431 bool mSingletonGLIsForHardwareWebRender
;
433 RefPtr
<layers::SurfacePool
> mSurfacePool
;
435 std::map
<wr::WindowId
, UniquePtr
<RendererOGL
>> mRenderers
;
437 struct PendingFrameInfo
{
438 TimeStamp mStartTime
;
440 bool mFrameNeedsRender
= false;
444 int64_t PendingCount() { return mPendingFrames
.size(); }
445 std::queue
<PendingFrameInfo
> mPendingFrames
;
446 uint8_t mPendingFrameBuild
= 0;
447 bool mIsDestroyed
= false;
448 RefPtr
<nsIRunnable
> mWrNotifierEventsRunnable
;
449 std::queue
<WrNotifierEvent
> mPendingWrNotifierEvents
;
452 DataMutex
<std::unordered_map
<uint64_t, UniquePtr
<WindowInfo
>>> mWindowInfos
;
454 std::unordered_map
<uint64_t, UniquePtr
<std::queue
<WrNotifierEvent
>>>
455 mWrNotifierEventsQueues
;
457 struct ExternalImageIdHashFn
{
458 std::size_t operator()(const wr::ExternalImageId
& aId
) const {
459 return HashGeneric(wr::AsUint64(aId
));
463 Mutex mRenderTextureMapLock MOZ_UNANNOTATED
;
464 std::unordered_map
<wr::ExternalImageId
, RefPtr
<RenderTextureHost
>,
465 ExternalImageIdHashFn
>
467 std::unordered_map
<wr::ExternalImageId
, RefPtr
<RenderTextureHost
>,
468 ExternalImageIdHashFn
>
469 mSyncObjectNeededRenderTextures
;
470 std::list
<std::pair
<RenderTextureOp
, RefPtr
<RenderTextureHost
>>>
473 // Used to remove all RenderTextureHost that are going to be removed by
474 // a deferred callback and remove them right away without waiting for the
475 // callback. On device reset we have to remove all GL related resources right
477 std::list
<RefPtr
<RenderTextureHost
>> mRenderTexturesDeferred
;
479 RefPtr
<nsIRunnable
> mRenderTextureOpsRunnable
;
483 bool mHandlingDeviceReset
;
484 bool mHandlingWebRenderError
;
488 } // namespace mozilla