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/Hal.h"
18 #include "mozilla/MozPromise.h"
19 #include "mozilla/DataMutex.h"
20 #include "mozilla/Maybe.h"
21 #include "mozilla/webrender/webrender_ffi.h"
22 #include "mozilla/UniquePtr.h"
23 #include "mozilla/webrender/WebRenderTypes.h"
24 #include "mozilla/layers/CompositionRecorder.h"
25 #include "mozilla/layers/SynchronousTask.h"
26 #include "mozilla/UniquePtr.h"
27 #include "mozilla/VsyncDispatcher.h"
31 #include <unordered_map>
38 class CompositorBridgeParent
;
39 class ShaderProgramOGLsHolder
;
44 typedef MozPromise
<MemoryReport
, bool, true> MemoryReportPromise
;
47 class RenderTextureHost
;
50 /// A rayon thread pool that is shared by all WebRender instances within a
52 class WebRenderThreadPool
{
54 explicit WebRenderThreadPool(bool low_priority
);
56 ~WebRenderThreadPool();
58 wr::WrThreadPool
* Raw() {
59 // If this pointer is null we are likely at some late shutdown stage,
60 // when threads are no longer safe to interact with.
61 MOZ_RELEASE_ASSERT(mThreadPool
);
65 /// Prematurely destroys this handle to the thread pool.
66 /// After calling this the object is useless.
70 wr::WrThreadPool
* mThreadPool
;
73 class WebRenderProgramCache final
{
75 explicit WebRenderProgramCache(wr::WrThreadPool
* aThreadPool
);
77 ~WebRenderProgramCache();
79 wr::WrProgramCache
* Raw() { return mProgramCache
; }
82 wr::WrProgramCache
* mProgramCache
;
85 class WebRenderShaders final
{
87 WebRenderShaders(gl::GLContext
* gl
, WebRenderProgramCache
* programCache
);
90 wr::WrShaders
* RawShaders() { return mShaders
; }
93 RefPtr
<gl::GLContext
> mGL
;
94 wr::WrShaders
* mShaders
;
97 class WebRenderPipelineInfo final
{
98 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderPipelineInfo
);
100 const wr::WrPipelineInfo
& Raw() const { return mPipelineInfo
; }
101 wr::WrPipelineInfo
& Raw() { return mPipelineInfo
; }
104 ~WebRenderPipelineInfo() = default;
105 wr::WrPipelineInfo mPipelineInfo
;
108 /// Base class for an event that can be scheduled to run on the render thread.
110 /// The event can be passed through the same channels as regular WebRender
111 /// messages to preserve ordering.
112 class RendererEvent
{
114 virtual ~RendererEvent() = default;
115 virtual void Run(RenderThread
& aRenderThread
, wr::WindowId aWindow
) = 0;
118 /// The render thread is where WebRender issues all of its GPU work, and as much
119 /// as possible this thread should only serve this purpose.
121 /// The render thread owns the different RendererOGLs (one per window) and
122 /// implements the RenderNotifier api exposed by the WebRender bindings.
124 /// Callers are not allowed to post tasks to the render thread's event loop
125 /// directly and must instead use the RendererEvent mechanism which avoids races
126 /// between the events and WebRender's own messages.
128 /// The GL context(s) should be created and used on this thread only.
129 /// XXX - I've tried to organize code so that we can potentially avoid making
130 /// this a singleton since this bad habit has a tendency to bite us later, but
131 /// I haven't gotten all the way there either, in order to focus on the more
132 /// important pieces first. So we are a bit in-between (this is totally a
133 /// singleton but in some places we pretend it's not). Hopefully we can evolve
134 /// this in a way that keeps the door open to removing the singleton bits.
135 class RenderThread final
{
136 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(RenderThread
)
139 /// Can be called from any thread.
140 static RenderThread
* Get();
142 /// Can only be called from the main thread.
143 static void Start(uint32_t aNamespace
);
145 /// Can only be called from the main thread.
146 static void ShutDown();
148 /// Can be called from any thread.
149 static bool IsInRenderThread();
151 /// Can be called from any thread.
152 static already_AddRefed
<nsIThread
> GetRenderThread();
154 // Can be called from any thread. Dispatches an event to the Renderer thread
155 // to iterate over all Renderers, accumulates memory statistics, and resolves
156 // the return promise.
157 static RefPtr
<MemoryReportPromise
> AccumulateMemoryReport(
158 MemoryReport aInitial
);
160 /// Can only be called from the render thread.
161 void AddRenderer(wr::WindowId aWindowId
, UniquePtr
<RendererOGL
> aRenderer
);
163 /// Can only be called from the render thread.
164 void RemoveRenderer(wr::WindowId aWindowId
);
166 /// Can only be called from the render thread.
167 RendererOGL
* GetRenderer(wr::WindowId aWindowId
);
169 /// Automatically forwarded to the render thread.
170 void SetClearColor(wr::WindowId aWindowId
, wr::ColorF aColor
);
172 /// Automatically forwarded to the render thread.
173 void SetProfilerUI(wr::WindowId aWindowId
, const nsACString
& aUI
);
175 /// Automatically forwarded to the render thread.
176 void PipelineSizeChanged(wr::WindowId aWindowId
, uint64_t aPipelineId
,
177 float aWidth
, float aHeight
);
179 /// Post RendererEvent to the render thread.
180 void PostEvent(wr::WindowId aWindowId
, UniquePtr
<RendererEvent
> aEvent
);
182 /// Can only be called from the render thread.
183 void SetFramePublishId(wr::WindowId aWindowId
, FramePublishId aPublishId
);
185 /// Can only be called from the render thread.
186 void UpdateAndRender(wr::WindowId aWindowId
, const VsyncId
& aStartId
,
187 const TimeStamp
& aStartTime
, bool aRender
,
188 const Maybe
<gfx::IntSize
>& aReadbackSize
,
189 const Maybe
<wr::ImageFormat
>& aReadbackFormat
,
190 const Maybe
<Range
<uint8_t>>& aReadbackBuffer
,
191 bool* aNeedsYFlip
= nullptr);
193 void Pause(wr::WindowId aWindowId
);
194 bool Resume(wr::WindowId aWindowId
);
196 /// Can be called from any thread.
197 void RegisterExternalImage(const wr::ExternalImageId
& aExternalImageId
,
198 already_AddRefed
<RenderTextureHost
> aTexture
);
200 /// Can be called from any thread.
201 void UnregisterExternalImage(const wr::ExternalImageId
& aExternalImageId
);
203 /// Can be called from any thread.
204 void DestroyExternalImagesSyncWait(
205 const std::vector
<wr::ExternalImageId
>&& aIds
);
207 /// Can be called from any thread.
208 void PrepareForUse(const wr::ExternalImageId
& aExternalImageId
);
210 /// Can be called from any thread.
211 void NotifyNotUsed(const wr::ExternalImageId
& aExternalImageId
);
213 /// Can be called from any thread.
214 void NotifyForUse(const wr::ExternalImageId
& aExternalImageId
);
216 void HandleRenderTextureOps();
218 /// Can only be called from the render thread.
219 void UnregisterExternalImageDuringShutdown(
220 const wr::ExternalImageId
& aExternalImageId
);
222 /// Can only be called from the render thread.
223 RenderTextureHost
* GetRenderTexture(
224 const wr::ExternalImageId
& aExternalImageId
);
226 /// Can be called from any thread.
227 bool IsDestroyed(wr::WindowId aWindowId
);
228 /// Can be called from any thread.
229 void SetDestroyed(wr::WindowId aWindowId
);
230 /// Can be called from any thread.
231 bool TooManyPendingFrames(wr::WindowId aWindowId
);
232 /// Can be called from any thread.
233 void IncPendingFrameCount(wr::WindowId aWindowId
, const VsyncId
& aStartId
,
234 const TimeStamp
& aStartTime
);
235 /// Can be called from any thread.
236 void DecPendingFrameBuildCount(wr::WindowId aWindowId
);
237 void DecPendingFrameCount(wr::WindowId aWindowId
);
239 // RenderNotifier implementation
240 void WrNotifierEvent_WakeUp(WrWindowId aWindowId
, bool aCompositeNeeded
);
241 void WrNotifierEvent_NewFrameReady(WrWindowId aWindowId
,
242 bool aCompositeNeeded
,
243 FramePublishId aPublishId
);
244 void WrNotifierEvent_ExternalEvent(WrWindowId aWindowId
, size_t aRawEvent
);
246 /// Can be called from any thread.
247 WebRenderThreadPool
& ThreadPool() { return mThreadPool
; }
249 /// Thread pool for low priority scene building
250 /// Can be called from any thread.
251 WebRenderThreadPool
& ThreadPoolLP() { return mThreadPoolLP
; }
253 /// Returns the cache used to serialize shader programs to disk, if enabled.
255 /// Can only be called from the render thread.
256 WebRenderProgramCache
* GetProgramCache() {
257 MOZ_ASSERT(IsInRenderThread());
258 return mProgramCache
.get();
261 /// Can only be called from the render thread.
262 WebRenderShaders
* GetShaders() {
263 MOZ_ASSERT(IsInRenderThread());
264 return mShaders
.get();
267 /// Can only be called from the render thread.
268 gl::GLContext
* SingletonGL(nsACString
& aError
);
269 gl::GLContext
* SingletonGL();
270 gl::GLContext
* SingletonGLForCompositorOGL();
271 void ClearSingletonGL();
272 RefPtr
<layers::SurfacePool
> SharedSurfacePool();
273 void ClearSharedSurfacePool();
275 RefPtr
<layers::ShaderProgramOGLsHolder
> GetProgramsForCompositorOGL();
277 /// Can only be called from the render thread.
278 void HandleDeviceReset(const char* aWhere
, GLenum aReason
);
279 /// Can only be called from the render thread.
280 bool IsHandlingDeviceReset();
281 /// Can be called from any thread.
282 void SimulateDeviceReset();
284 /// Can only be called from the render thread.
285 void NotifyWebRenderError(WebRenderError aError
);
287 /// Can only be called from the render thread.
288 void HandleWebRenderError(WebRenderError aError
);
289 /// Can only be called from the render thread.
290 bool IsHandlingWebRenderError();
292 /// Can only be called from the render thread.
293 bool SyncObjectNeeded();
295 size_t RendererCount() const;
296 size_t ActiveRendererCount() const { return sActiveRendererCount
; };
297 void UpdateActiveRendererCount();
299 void BeginRecordingForWindow(wr::WindowId aWindowId
,
300 const TimeStamp
& aRecordingStart
,
301 wr::PipelineId aRootPipelineId
);
303 Maybe
<layers::FrameRecording
> EndRecordingForWindow(wr::WindowId aWindowId
);
305 static void MaybeEnableGLDebugMessage(gl::GLContext
* aGLContext
);
307 void SetBatteryInfo(const hal::BatteryInformation
& aBatteryInfo
);
308 bool GetPowerIsCharging();
311 static size_t sRendererCount
;
312 static size_t sActiveRendererCount
;
314 enum class RenderTextureOp
{
319 class WrNotifierEvent
{
329 WrNotifierEvent(const Tag aTag
, const bool aCompositeNeeded
)
330 : mTag(aTag
), mCompositeNeeded(aCompositeNeeded
) {
331 MOZ_ASSERT(mTag
== Tag::WakeUp
);
333 WrNotifierEvent(const Tag aTag
, bool aCompositeNeeded
,
334 FramePublishId aPublishId
)
336 mCompositeNeeded(aCompositeNeeded
),
337 mPublishId(aPublishId
) {
338 MOZ_ASSERT(mTag
== Tag::NewFrameReady
);
340 WrNotifierEvent(const Tag aTag
, UniquePtr
<RendererEvent
>&& aRendererEvent
)
341 : mTag(aTag
), mRendererEvent(std::move(aRendererEvent
)) {
342 MOZ_ASSERT(mTag
== Tag::ExternalEvent
);
345 const bool mCompositeNeeded
= false;
346 const FramePublishId mPublishId
= FramePublishId::INVALID
;
347 UniquePtr
<RendererEvent
> mRendererEvent
;
350 static WrNotifierEvent
WakeUp(const bool aCompositeNeeded
) {
351 return WrNotifierEvent(Tag::WakeUp
, aCompositeNeeded
);
354 static WrNotifierEvent
NewFrameReady(const bool aCompositeNeeded
,
355 const FramePublishId aPublishId
) {
356 return WrNotifierEvent(Tag::NewFrameReady
, aCompositeNeeded
, aPublishId
);
359 static WrNotifierEvent
ExternalEvent(
360 UniquePtr
<RendererEvent
>&& aRendererEvent
) {
361 return WrNotifierEvent(Tag::ExternalEvent
, std::move(aRendererEvent
));
364 bool CompositeNeeded() {
365 if (mTag
== Tag::WakeUp
|| mTag
== Tag::NewFrameReady
) {
366 return mCompositeNeeded
;
368 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
371 FramePublishId
PublishId() {
372 if (mTag
== Tag::NewFrameReady
) {
375 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
376 return FramePublishId::INVALID
;
378 UniquePtr
<RendererEvent
> ExternalEvent() {
379 if (mTag
== Tag::ExternalEvent
) {
380 MOZ_ASSERT(mRendererEvent
);
381 return std::move(mRendererEvent
);
383 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
388 explicit RenderThread(RefPtr
<nsIThread
> aThread
);
390 void HandleFrameOneDocInner(wr::WindowId aWindowId
, bool aRender
,
392 Maybe
<FramePublishId
> aPublishId
);
394 void DeferredRenderTextureHostDestroy();
396 void InitDeviceTask();
397 void HandleFrameOneDoc(wr::WindowId aWindowId
, bool aRender
,
398 bool aTrackedFrame
, Maybe
<FramePublishId
> aPublishId
);
399 void RunEvent(wr::WindowId aWindowId
, UniquePtr
<RendererEvent
> aEvent
);
400 void PostRunnable(already_AddRefed
<nsIRunnable
> aRunnable
);
402 void DoAccumulateMemoryReport(MemoryReport
,
403 const RefPtr
<MemoryReportPromise::Private
>&);
405 void AddRenderTextureOp(RenderTextureOp aOp
,
406 const wr::ExternalImageId
& aExternalImageId
);
408 void CreateSingletonGL(nsACString
& aError
);
410 void DestroyExternalImages(const std::vector
<wr::ExternalImageId
>&& aIds
);
414 void PostWrNotifierEvents(WrWindowId aWindowId
);
415 void PostWrNotifierEvents(WrWindowId aWindowId
, WindowInfo
* aInfo
);
416 void HandleWrNotifierEvents(WrWindowId aWindowId
);
417 void WrNotifierEvent_HandleWakeUp(wr::WindowId aWindowId
,
418 bool aCompositeNeeded
);
419 void WrNotifierEvent_HandleNewFrameReady(wr::WindowId aWindowId
,
420 bool aCompositeNeeded
,
421 FramePublishId aPublishId
);
422 void WrNotifierEvent_HandleExternalEvent(
423 wr::WindowId aWindowId
, UniquePtr
<RendererEvent
> aRendererEvent
);
427 RefPtr
<nsIThread
> const mThread
;
429 WebRenderThreadPool mThreadPool
;
430 WebRenderThreadPool mThreadPoolLP
;
432 UniquePtr
<WebRenderProgramCache
> mProgramCache
;
433 UniquePtr
<WebRenderShaders
> mShaders
;
434 RefPtr
<layers::ShaderProgramOGLsHolder
> mProgramsForCompositorOGL
;
436 // An optional shared GLContext to be used for all
438 RefPtr
<gl::GLContext
> mSingletonGL
;
439 bool mSingletonGLIsForHardwareWebRender
;
441 RefPtr
<layers::SurfacePool
> mSurfacePool
;
443 std::map
<wr::WindowId
, UniquePtr
<RendererOGL
>> mRenderers
;
445 DataMutex
<Maybe
<hal::BatteryInformation
>> mBatteryInfo
;
447 struct PendingFrameInfo
{
448 TimeStamp mStartTime
;
453 int64_t PendingCount() { return mPendingFrames
.size(); }
454 std::queue
<PendingFrameInfo
> mPendingFrames
;
455 uint8_t mPendingFrameBuild
= 0;
456 bool mIsDestroyed
= false;
457 RefPtr
<nsIRunnable
> mWrNotifierEventsRunnable
;
458 std::queue
<WrNotifierEvent
> mPendingWrNotifierEvents
;
461 DataMutex
<std::unordered_map
<uint64_t, UniquePtr
<WindowInfo
>>> mWindowInfos
;
463 std::unordered_map
<uint64_t, UniquePtr
<std::queue
<WrNotifierEvent
>>>
464 mWrNotifierEventsQueues
;
466 struct ExternalImageIdHashFn
{
467 std::size_t operator()(const wr::ExternalImageId
& aId
) const {
468 return HashGeneric(wr::AsUint64(aId
));
472 Mutex mRenderTextureMapLock
;
473 std::unordered_map
<wr::ExternalImageId
, RefPtr
<RenderTextureHost
>,
474 ExternalImageIdHashFn
>
475 mRenderTextures
MOZ_GUARDED_BY(mRenderTextureMapLock
);
476 std::unordered_map
<wr::ExternalImageId
, RefPtr
<RenderTextureHost
>,
477 ExternalImageIdHashFn
>
478 mSyncObjectNeededRenderTextures
MOZ_GUARDED_BY(mRenderTextureMapLock
);
479 std::list
<std::pair
<RenderTextureOp
, RefPtr
<RenderTextureHost
>>>
480 mRenderTextureOps
MOZ_GUARDED_BY(mRenderTextureMapLock
);
482 // Used to remove all RenderTextureHost that are going to be removed by
483 // a deferred callback and remove them right away without waiting for the
484 // callback. On device reset we have to remove all GL related resources right
486 std::list
<RefPtr
<RenderTextureHost
>> mRenderTexturesDeferred
487 MOZ_GUARDED_BY(mRenderTextureMapLock
);
489 RefPtr
<nsIRunnable
> mRenderTextureOpsRunnable
490 MOZ_GUARDED_BY(mRenderTextureMapLock
);
492 // Set from MainThread, read from either MainThread or RenderThread
495 // Only accessed from the RenderThread
496 bool mHandlingDeviceReset
;
497 bool mHandlingWebRenderError
;
501 } // namespace mozilla