RenderThread.h (19911B)
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_RENDERTHREAD_H 8 #define MOZILLA_LAYERS_RENDERTHREAD_H 9 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" 28 29 #include <list> 30 #include <queue> 31 #include <unordered_map> 32 33 namespace mozilla { 34 namespace gl { 35 class GLContext; 36 } // namespace gl 37 namespace layers { 38 class CompositorBridgeParent; 39 class Fence; 40 class ShaderProgramOGLsHolder; 41 class SurfacePool; 42 } // namespace layers 43 namespace wr { 44 45 typedef MozPromise<MemoryReport, bool, true> MemoryReportPromise; 46 47 class RendererOGL; 48 class RenderTextureHost; 49 class RenderTextureHostUsageInfo; 50 class RenderThread; 51 52 /// A rayon thread pool that is shared by all WebRender instances within a 53 /// process. 54 class WebRenderThreadPool { 55 public: 56 explicit WebRenderThreadPool(bool low_priority); 57 58 ~WebRenderThreadPool(); 59 60 wr::WrThreadPool* Raw() { 61 // If this pointer is null we are likely at some late shutdown stage, 62 // when threads are no longer safe to interact with. 63 MOZ_RELEASE_ASSERT(mThreadPool); 64 return mThreadPool; 65 } 66 67 /// Prematurely destroys this handle to the thread pool. 68 /// After calling this the object is useless. 69 void Release(); 70 71 protected: 72 wr::WrThreadPool* mThreadPool; 73 }; 74 75 /// An optional dedicated thread for glyph rasterization shared by all WebRender 76 /// instances within a process. 77 class MaybeWebRenderGlyphRasterThread { 78 public: 79 explicit MaybeWebRenderGlyphRasterThread(bool aEnabled); 80 81 ~MaybeWebRenderGlyphRasterThread(); 82 83 bool IsEnabled() const { return mThread != nullptr; } 84 85 const wr::WrGlyphRasterThread* Raw() { return mThread; } 86 87 protected: 88 wr::WrGlyphRasterThread* mThread; 89 }; 90 91 class WebRenderProgramCache final { 92 public: 93 explicit WebRenderProgramCache(wr::WrThreadPool* aThreadPool); 94 95 ~WebRenderProgramCache(); 96 97 wr::WrProgramCache* Raw() { return mProgramCache; } 98 99 protected: 100 wr::WrProgramCache* mProgramCache; 101 }; 102 103 class WebRenderShaders final { 104 public: 105 WebRenderShaders(gl::GLContext* gl, WebRenderProgramCache* programCache); 106 ~WebRenderShaders(); 107 108 // Returns true if ResumeWarmup() should be called again 109 bool ResumeWarmup(); 110 111 wr::WrShaders* RawShaders() { return mShaders; } 112 113 protected: 114 RefPtr<gl::GLContext> mGL; 115 wr::WrShaders* mShaders; 116 }; 117 118 class WebRenderPipelineInfo final { 119 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderPipelineInfo); 120 121 const wr::WrPipelineInfo& Raw() const { return mPipelineInfo; } 122 wr::WrPipelineInfo& Raw() { return mPipelineInfo; } 123 124 protected: 125 ~WebRenderPipelineInfo() = default; 126 wr::WrPipelineInfo mPipelineInfo; 127 }; 128 129 /// Base class for an event that can be scheduled to run on the render thread. 130 /// 131 /// The event can be passed through the same channels as regular WebRender 132 /// messages to preserve ordering. 133 class RendererEvent { 134 public: 135 RendererEvent() : mCreationTimeStamp(TimeStamp::Now()) {} 136 virtual ~RendererEvent() = default; 137 virtual void Run(RenderThread& aRenderThread, wr::WindowId aWindow) = 0; 138 virtual const char* Name() = 0; 139 140 const TimeStamp mCreationTimeStamp; 141 }; 142 143 /// The render thread is where WebRender issues all of its GPU work, and as much 144 /// as possible this thread should only serve this purpose. 145 /// 146 /// The render thread owns the different RendererOGLs (one per window) and 147 /// implements the RenderNotifier api exposed by the WebRender bindings. 148 /// 149 /// Callers are not allowed to post tasks to the render thread's event loop 150 /// directly and must instead use the RendererEvent mechanism which avoids races 151 /// between the events and WebRender's own messages. 152 /// 153 /// The GL context(s) should be created and used on this thread only. 154 /// XXX - I've tried to organize code so that we can potentially avoid making 155 /// this a singleton since this bad habit has a tendency to bite us later, but 156 /// I haven't gotten all the way there either, in order to focus on the more 157 /// important pieces first. So we are a bit in-between (this is totally a 158 /// singleton but in some places we pretend it's not). Hopefully we can evolve 159 /// this in a way that keeps the door open to removing the singleton bits. 160 class RenderThread final { 161 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(RenderThread) 162 163 public: 164 /// Can be called from any thread. 165 static RenderThread* Get(); 166 167 /// Can only be called from the main thread. 168 static void Start(uint32_t aNamespace); 169 170 /// Can only be called from the main thread. 171 static void ShutDown(); 172 173 /// Can be called from any thread. 174 static bool IsInRenderThread(); 175 176 /// Can be called from any thread. 177 static already_AddRefed<nsIThread> GetRenderThread(); 178 179 // Can be called from any thread. Dispatches an event to the Renderer thread 180 // to iterate over all Renderers, accumulates memory statistics, and resolves 181 // the return promise. 182 static RefPtr<MemoryReportPromise> AccumulateMemoryReport( 183 MemoryReport aInitial); 184 185 /// Can only be called from the main thread. 186 static void PostHandleDeviceReset(gfx::DeviceResetDetectPlace aPlace, 187 gfx::DeviceResetReason aReason); 188 189 /// Can only be called from the render thread. 190 void AddRenderer(wr::WindowId aWindowId, UniquePtr<RendererOGL> aRenderer); 191 192 /// Can only be called from the render thread. 193 void RemoveRenderer(wr::WindowId aWindowId); 194 195 /// Can only be called from the render thread. 196 RendererOGL* GetRenderer(wr::WindowId aWindowId); 197 198 /// Automatically forwarded to the render thread. 199 void SetClearColor(wr::WindowId aWindowId, wr::ColorF aColor); 200 201 /// Automatically forwarded to the render thread. 202 void SetProfilerUI(wr::WindowId aWindowId, const nsACString& aUI); 203 204 /// Automatically forwarded to the render thread. 205 void PipelineSizeChanged(wr::WindowId aWindowId, uint64_t aPipelineId, 206 float aWidth, float aHeight); 207 208 /// Post RendererEvent to the render thread. 209 void PostEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aEvent); 210 211 /// Can only be called from the render thread. 212 void SetFramePublishId(wr::WindowId aWindowId, FramePublishId aPublishId); 213 214 /// Can only be called from the render thread. 215 void UpdateAndRender(wr::WindowId aWindowId, const VsyncId& aStartId, 216 const TimeStamp& aStartTime, 217 const wr::FrameReadyParams& aParams, 218 const Maybe<gfx::IntSize>& aReadbackSize, 219 const Maybe<wr::ImageFormat>& aReadbackFormat, 220 const Maybe<Range<uint8_t>>& aReadbackBuffer, 221 RendererStats* aStats, bool* aNeedsYFlip = nullptr); 222 223 void Pause(wr::WindowId aWindowId); 224 bool Resume(wr::WindowId aWindowId); 225 void NotifyIdle(); 226 227 /// Can be called from any thread. 228 void RegisterExternalImage(const wr::ExternalImageId& aExternalImageId, 229 already_AddRefed<RenderTextureHost> aTexture); 230 231 /// Can be called from any thread. 232 void UnregisterExternalImage(const wr::ExternalImageId& aExternalImageId); 233 234 /// Can be called from any thread. 235 void DestroyExternalImagesSyncWait( 236 const std::vector<wr::ExternalImageId>&& aIds); 237 238 /// Can be called from any thread. 239 void PrepareForUse(const wr::ExternalImageId& aExternalImageId); 240 241 /// Can be called from any thread. 242 void NotifyNotUsed(const wr::ExternalImageId& aExternalImageId); 243 244 /// Can be called from any thread. 245 void NotifyForUse(const wr::ExternalImageId& aExternalImageId); 246 247 void HandleRenderTextureOps(); 248 249 /// Can be called from any thread. 250 RefPtr<RenderTextureHostUsageInfo> GetOrMergeUsageInfo( 251 const wr::ExternalImageId& aExternalImageId, 252 RefPtr<RenderTextureHostUsageInfo> aUsageInfo); 253 254 /// Can only be called from the render thread. 255 void UnregisterExternalImageDuringShutdown( 256 const wr::ExternalImageId& aExternalImageId); 257 258 /// Can only be called from the render thread. 259 RenderTextureHost* GetRenderTexture( 260 const wr::ExternalImageId& aExternalImageId); 261 262 /// Can only be called from the render thread. 263 std::tuple<RenderTextureHost*, RefPtr<RenderTextureHostUsageInfo>> 264 GetRenderTextureAndUsageInfo(const wr::ExternalImageId& aExternalImageId); 265 266 /// Can be called from any thread. 267 bool IsDestroyed(wr::WindowId aWindowId); 268 /// Can be called from any thread. 269 void SetDestroyed(wr::WindowId aWindowId); 270 /// Can be called from any thread. 271 bool TooManyPendingFrames(wr::WindowId aWindowId); 272 /// Can be called from any thread. 273 /// 274 /// Should always be paired with a call to `WebRenderAPI::GenerateFrame` that 275 /// has `tracked` set to true. 276 void IncPendingFrameCount(wr::WindowId aWindowId, const VsyncId& aStartId, 277 const TimeStamp& aStartTime); 278 /// Can be called from any thread. 279 void DecPendingFrameBuildCount(wr::WindowId aWindowId); 280 void DecPendingFrameCount(wr::WindowId aWindowId); 281 282 // RenderNotifier implementation 283 void WrNotifierEvent_WakeUp(WrWindowId aWindowId, bool aCompositeNeeded); 284 void WrNotifierEvent_NewFrameReady(WrWindowId aWindowId, 285 wr::FramePublishId aPublishId, 286 const wr::FrameReadyParams* aParams); 287 void WrNotifierEvent_ExternalEvent(WrWindowId aWindowId, size_t aRawEvent); 288 289 /// Can be called from any thread. 290 WebRenderThreadPool& ThreadPool() { return mThreadPool; } 291 292 /// Thread pool for low priority scene building 293 /// Can be called from any thread. 294 WebRenderThreadPool& ThreadPoolLP() { return mThreadPoolLP; } 295 296 /// A pool of large memory chunks used by the per-frame allocators. 297 WrChunkPool* MemoryChunkPool() { return mChunkPool; } 298 299 /// Optional global glyph raster thread. 300 /// Can be called from any thread. 301 MaybeWebRenderGlyphRasterThread& GlyphRasterThread() { 302 return mGlyphRasterThread; 303 } 304 305 /// Returns the cache used to serialize shader programs to disk, if enabled. 306 /// 307 /// Can only be called from the render thread. 308 WebRenderProgramCache* GetProgramCache() { 309 MOZ_ASSERT(IsInRenderThread()); 310 return mProgramCache.get(); 311 } 312 313 /// Can only be called from the render thread. 314 WebRenderShaders* GetShaders() { 315 MOZ_ASSERT(IsInRenderThread()); 316 return mShaders.get(); 317 } 318 319 /// Can only be called from the render thread. 320 gl::GLContext* SingletonGL(nsACString& aError); 321 gl::GLContext* SingletonGL(); 322 gl::GLContext* SingletonGLForCompositorOGL(); 323 void ClearSingletonGL(); 324 RefPtr<layers::SurfacePool> SharedSurfacePool(); 325 void ClearSharedSurfacePool(); 326 327 RefPtr<layers::ShaderProgramOGLsHolder> GetProgramsForCompositorOGL(); 328 329 /// Can only be called from the render thread. 330 void HandleDeviceReset(gfx::DeviceResetDetectPlace aPlace, 331 gfx::DeviceResetReason aReason); 332 /// Can only be called from the render thread. 333 bool IsHandlingDeviceReset(); 334 /// Can be called from any thread. 335 void SimulateDeviceReset(); 336 337 /// Can only be called from the render thread. 338 void NotifyWebRenderError(WebRenderError aError); 339 340 /// Can only be called from the render thread. 341 void HandleWebRenderError(WebRenderError aError); 342 /// Can only be called from the render thread. 343 bool IsHandlingWebRenderError(); 344 345 /// Can only be called from the render thread. 346 bool SyncObjectNeeded(); 347 348 size_t RendererCount() const; 349 size_t ActiveRendererCount() const { return sActiveRendererCount; }; 350 void UpdateActiveRendererCount(); 351 352 void BeginRecordingForWindow(wr::WindowId aWindowId, 353 const TimeStamp& aRecordingStart, 354 wr::PipelineId aRootPipelineId); 355 356 Maybe<layers::FrameRecording> EndRecordingForWindow(wr::WindowId aWindowId); 357 358 static void MaybeEnableGLDebugMessage(gl::GLContext* aGLContext); 359 360 void SetBatteryInfo(const hal::BatteryInformation& aBatteryInfo); 361 bool GetPowerIsCharging(); 362 363 void BeginShaderWarmupIfNeeded(); 364 365 private: 366 static size_t sRendererCount; 367 static size_t sActiveRendererCount; 368 369 enum class RenderTextureOp { 370 PrepareForUse, 371 NotifyForUse, 372 NotifyNotUsed, 373 }; 374 class WrNotifierEvent { 375 public: 376 enum class Tag { 377 WakeUp, 378 NewFrameReady, 379 ExternalEvent, 380 }; 381 const Tag mTag; 382 383 private: 384 WrNotifierEvent(const Tag aTag, wr::FramePublishId aPublishId, 385 wr::FrameReadyParams aParams) 386 : mTag(aTag), mPublishId(aPublishId), mParams(aParams) { 387 MOZ_ASSERT(mTag == Tag::NewFrameReady); 388 } 389 WrNotifierEvent(const Tag aTag, wr::FrameReadyParams aParams) 390 : mTag(aTag), mParams(aParams) { 391 MOZ_ASSERT(mTag == Tag::WakeUp); 392 } 393 WrNotifierEvent(const Tag aTag, UniquePtr<RendererEvent>&& aRendererEvent) 394 : mTag(aTag), mRendererEvent(std::move(aRendererEvent)) { 395 MOZ_ASSERT(mTag == Tag::ExternalEvent); 396 } 397 398 const wr::FramePublishId mPublishId = wr::FramePublishId::INVALID; 399 const wr::FrameReadyParams mParams = { 400 .present = false, 401 .render = false, 402 .scrolled = false, 403 .tracked = false, 404 }; 405 UniquePtr<RendererEvent> mRendererEvent; 406 407 public: 408 static WrNotifierEvent WakeUp(const bool aCompositeNeeded) { 409 wr::FrameReadyParams params = { 410 .present = aCompositeNeeded, 411 .render = aCompositeNeeded, 412 .scrolled = false, 413 .tracked = false, 414 }; 415 return WrNotifierEvent(Tag::WakeUp, params); 416 } 417 418 static WrNotifierEvent NewFrameReady(FramePublishId aPublishId, 419 const wr::FrameReadyParams* aParams) { 420 return WrNotifierEvent(Tag::NewFrameReady, aPublishId, *aParams); 421 } 422 423 static WrNotifierEvent ExternalEvent( 424 UniquePtr<RendererEvent>&& aRendererEvent) { 425 return WrNotifierEvent(Tag::ExternalEvent, std::move(aRendererEvent)); 426 } 427 428 const wr::FrameReadyParams& FrameReadyParams() const { 429 MOZ_ASSERT(mTag == Tag::NewFrameReady || mTag == Tag::WakeUp, 430 "Unexpected NotiferEvent tag"); 431 return mParams; 432 } 433 FramePublishId PublishId() { 434 if (mTag == Tag::NewFrameReady) { 435 return mPublishId; 436 } 437 MOZ_ASSERT_UNREACHABLE("Unexpected NotiferEvent tag"); 438 return FramePublishId::INVALID; 439 } 440 UniquePtr<RendererEvent> ExternalEvent() { 441 if (mTag == Tag::ExternalEvent) { 442 MOZ_ASSERT(mRendererEvent); 443 return std::move(mRendererEvent); 444 } 445 MOZ_ASSERT_UNREACHABLE("Unexpected NotiferEvent tag"); 446 return nullptr; 447 } 448 }; 449 450 explicit RenderThread(RefPtr<nsIThread> aThread); 451 452 void HandleFrameOneDocInner(wr::WindowId aWindowId, 453 const wr::FrameReadyParams& aParams, 454 Maybe<FramePublishId> aPublishId); 455 456 void DeferredRenderTextureHostDestroy(); 457 void ShutDownTask(); 458 void InitDeviceTask(); 459 void PostResumeShaderWarmupRunnable(); 460 void ResumeShaderWarmup(); 461 void HandleFrameOneDoc(wr::WindowId aWindowId, const wr::FrameReadyParams&, 462 Maybe<FramePublishId> aPublishId); 463 void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aEvent, 464 bool aViaWebRender); 465 void PostRunnable(already_AddRefed<nsIRunnable> aRunnable); 466 467 void DoAccumulateMemoryReport(MemoryReport, 468 const RefPtr<MemoryReportPromise::Private>&); 469 470 void AddRenderTextureOp(RenderTextureOp aOp, 471 const wr::ExternalImageId& aExternalImageId); 472 473 void CreateSingletonGL(nsACString& aError); 474 475 void DestroyExternalImages(const std::vector<wr::ExternalImageId>&& aIds); 476 477 struct WindowInfo; 478 479 void PostWrNotifierEvents(WrWindowId aWindowId); 480 void PostWrNotifierEvents(WrWindowId aWindowId, WindowInfo* aInfo); 481 void HandleWrNotifierEvents(WrWindowId aWindowId); 482 void WrNotifierEvent_HandleWakeUp(wr::WindowId aWindowId, 483 const wr::FrameReadyParams& aParams); 484 void WrNotifierEvent_HandleNewFrameReady(wr::WindowId aWindowId, 485 wr::FramePublishId aPublishId, 486 const wr::FrameReadyParams& aParams); 487 void WrNotifierEvent_HandleExternalEvent( 488 wr::WindowId aWindowId, UniquePtr<RendererEvent> aRendererEvent); 489 490 ~RenderThread(); 491 492 RefPtr<nsIThread> const mThread; 493 494 WebRenderThreadPool mThreadPool; 495 WebRenderThreadPool mThreadPoolLP; 496 WrChunkPool* mChunkPool; 497 MaybeWebRenderGlyphRasterThread mGlyphRasterThread; 498 499 UniquePtr<WebRenderProgramCache> mProgramCache; 500 UniquePtr<WebRenderShaders> mShaders; 501 RefPtr<layers::ShaderProgramOGLsHolder> mProgramsForCompositorOGL; 502 503 // An optional shared GLContext to be used for all 504 // windows. 505 RefPtr<gl::GLContext> mSingletonGL; 506 bool mSingletonGLIsForHardwareWebRender; 507 508 RefPtr<layers::SurfacePool> mSurfacePool; 509 510 std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers; 511 512 DataMutex<Maybe<hal::BatteryInformation>> mBatteryInfo; 513 514 struct PendingFrameInfo { 515 TimeStamp mStartTime; 516 VsyncId mStartId; 517 }; 518 519 struct WindowInfo { 520 int64_t PendingCount() { return mPendingFrames.size(); } 521 std::queue<PendingFrameInfo> mPendingFrames; 522 uint8_t mPendingFrameBuild = 0; 523 bool mIsDestroyed = false; 524 RefPtr<nsIRunnable> mWrNotifierEventsRunnable; 525 std::queue<WrNotifierEvent> mPendingWrNotifierEvents; 526 }; 527 528 DataMutex<std::unordered_map<uint64_t, UniquePtr<WindowInfo>>> mWindowInfos; 529 530 std::unordered_map<uint64_t, UniquePtr<std::queue<WrNotifierEvent>>> 531 mWrNotifierEventsQueues; 532 533 struct ExternalImageIdHashFn { 534 std::size_t operator()(const wr::ExternalImageId& aId) const { 535 return HashGeneric(wr::AsUint64(aId)); 536 } 537 }; 538 539 Mutex mRenderTextureMapLock; 540 std::unordered_map<wr::ExternalImageId, RefPtr<RenderTextureHost>, 541 ExternalImageIdHashFn> 542 mRenderTextures MOZ_GUARDED_BY(mRenderTextureMapLock); 543 std::unordered_map<wr::ExternalImageId, RefPtr<RenderTextureHost>, 544 ExternalImageIdHashFn> 545 mSyncObjectNeededRenderTextures MOZ_GUARDED_BY(mRenderTextureMapLock); 546 std::list<std::pair<RenderTextureOp, RefPtr<RenderTextureHost>>> 547 mRenderTextureOps MOZ_GUARDED_BY(mRenderTextureMapLock); 548 549 // Used to remove all RenderTextureHost that are going to be removed by 550 // a deferred callback and remove them right away without waiting for the 551 // callback. On device reset we have to remove all GL related resources right 552 // away. 553 std::list<RefPtr<RenderTextureHost>> mRenderTexturesDeferred 554 MOZ_GUARDED_BY(mRenderTextureMapLock); 555 556 RefPtr<nsIRunnable> mRenderTextureOpsRunnable 557 MOZ_GUARDED_BY(mRenderTextureMapLock); 558 559 #ifdef DEBUG 560 // used for tests only to ensure render textures don't increase 561 int32_t mRenderTexturesLastTime MOZ_GUARDED_BY(mRenderTextureMapLock) = -1; 562 #endif 563 564 // Set from MainThread, read from either MainThread or RenderThread 565 bool mHasShutdown; 566 567 // Only accessed from the RenderThread 568 bool mHandlingDeviceReset; 569 bool mHandlingWebRenderError; 570 }; 571 572 } // namespace wr 573 } // namespace mozilla 574 575 #endif