WebRenderAPI.cpp (74829B)
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 #include "WebRenderAPI.h" 8 9 #include "mozilla/Logging.h" 10 #include "mozilla/ipc/ByteBuf.h" 11 #include "mozilla/webrender/RendererOGL.h" 12 #include "mozilla/gfx/gfxVars.h" 13 #include "mozilla/layers/CompositorThread.h" 14 #include "mozilla/HelperMacros.h" 15 #include "mozilla/StaticPrefs_gfx.h" 16 #include "mozilla/StaticPrefs_webgl.h" 17 #include "mozilla/ToString.h" 18 #include "mozilla/webrender/RenderCompositor.h" 19 #include "mozilla/widget/CompositorWidget.h" 20 #include "mozilla/layers/SynchronousTask.h" 21 #include "nsDisplayList.h" 22 #include "nsThreadUtils.h" 23 #include "TextDrawTarget.h" 24 #include "malloc_decls.h" 25 #include "GLContext.h" 26 27 #include "source-repo.h" 28 29 #ifdef MOZ_SOURCE_STAMP 30 # define MOZ_SOURCE_STAMP_VALUE MOZ_STRINGIFY(MOZ_SOURCE_STAMP) 31 #else 32 # define MOZ_SOURCE_STAMP_VALUE nullptr 33 #endif 34 35 static mozilla::LazyLogModule sWrDLLog("wr.dl"); 36 #define WRDL_LOG(...) \ 37 MOZ_LOG(sWrDLLog, LogLevel::Debug, ("WRDL(%p): " __VA_ARGS__)) 38 39 namespace mozilla { 40 using namespace layers; 41 42 namespace wr { 43 44 MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf) 45 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(WebRenderMallocEnclosingSizeOf) 46 47 class NewRenderer : public RendererEvent { 48 public: 49 NewRenderer(wr::DocumentHandle** aDocHandle, 50 layers::CompositorBridgeParent* aBridge, 51 WebRenderBackend* aBackend, WebRenderCompositor* aCompositor, 52 int32_t* aMaxTextureSize, bool* aUseANGLE, bool* aUseDComp, 53 bool* aUseLayerCompositor, bool* aUseTripleBuffering, 54 bool* aSupportsExternalBufferTextures, 55 RefPtr<widget::CompositorWidget>&& aWidget, 56 layers::SynchronousTask* aTask, LayoutDeviceIntSize aSize, 57 layers::WindowKind aWindowKind, layers::SyncHandle* aHandle, 58 nsACString* aError) 59 : mDocHandle(aDocHandle), 60 mBackend(aBackend), 61 mCompositor(aCompositor), 62 mMaxTextureSize(aMaxTextureSize), 63 mUseANGLE(aUseANGLE), 64 mUseDComp(aUseDComp), 65 mUseLayerCompositor(aUseLayerCompositor), 66 mUseTripleBuffering(aUseTripleBuffering), 67 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures), 68 mBridge(aBridge), 69 mCompositorWidget(std::move(aWidget)), 70 mTask(aTask), 71 mSize(aSize), 72 mWindowKind(aWindowKind), 73 mSyncHandle(aHandle), 74 mError(aError) { 75 MOZ_COUNT_CTOR(NewRenderer); 76 } 77 78 MOZ_COUNTED_DTOR(NewRenderer) 79 80 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 81 layers::AutoCompleteTask complete(mTask); 82 83 UniquePtr<RenderCompositor> compositor = 84 RenderCompositor::Create(std::move(mCompositorWidget), *mError); 85 if (!compositor) { 86 if (!mError->IsEmpty()) { 87 gfxCriticalNote << mError->BeginReading(); 88 } 89 return; 90 } 91 92 compositor->MakeCurrent(); 93 94 *mBackend = compositor->BackendType(); 95 *mCompositor = compositor->CompositorType(); 96 *mUseANGLE = compositor->UseANGLE(); 97 *mUseDComp = compositor->UseDComp(); 98 *mUseLayerCompositor = compositor->ShouldUseLayerCompositor(); 99 *mUseTripleBuffering = compositor->UseTripleBuffering(); 100 *mSupportsExternalBufferTextures = 101 compositor->SupportsExternalBufferTextures(); 102 103 // Only allow the panic on GL error functionality in nightly builds, 104 // since it (deliberately) crashes the GPU process if any GL call 105 // returns an error code. 106 bool panic_on_gl_error = false; 107 #ifdef NIGHTLY_BUILD 108 panic_on_gl_error = 109 StaticPrefs::gfx_webrender_panic_on_gl_error_AtStartup(); 110 #endif 111 112 bool isMainWindow = true; // TODO! 113 bool supportLowPriorityTransactions = isMainWindow; 114 bool supportLowPriorityThreadpool = 115 supportLowPriorityTransactions && 116 StaticPrefs::gfx_webrender_enable_low_priority_pool(); 117 wr::Renderer* wrRenderer = nullptr; 118 char* errorMessage = nullptr; 119 int picTileWidth = StaticPrefs::gfx_webrender_picture_tile_width(); 120 int picTileHeight = StaticPrefs::gfx_webrender_picture_tile_height(); 121 auto* swgl = compositor->swgl(); 122 auto* gl = (compositor->gl() && !swgl) ? compositor->gl() : nullptr; 123 auto* progCache = (aRenderThread.GetProgramCache() && !swgl) 124 ? aRenderThread.GetProgramCache()->Raw() 125 : nullptr; 126 auto* shaders = (aRenderThread.GetShaders() && !swgl) 127 ? aRenderThread.GetShaders()->RawShaders() 128 : nullptr; 129 130 // Check That if we are not using SWGL, we have at least a GL or GLES 3.0 131 // context. 132 if (gl && !swgl) { 133 bool versionCheck = 134 gl->IsAtLeast(gl::ContextProfile::OpenGLCore, 300) || 135 gl->IsAtLeast(gl::ContextProfile::OpenGLCompatibility, 300) || 136 gl->IsAtLeast(gl::ContextProfile::OpenGLES, 300); 137 138 if (!versionCheck) { 139 gfxCriticalNote << "GL context version (" << gl->Version() 140 << ") insufficent for hardware WebRender"; 141 142 mError->AssignASCII("GL context version insufficient"); 143 return; 144 } 145 } 146 147 if (!wr_window_new( 148 aWindowId, mSize.width, mSize.height, 149 mWindowKind == WindowKind::MAIN, supportLowPriorityTransactions, 150 supportLowPriorityThreadpool, gfx::gfxVars::UseGLSwizzle(), 151 gfx::gfxVars::UseWebRenderScissoredCacheClears(), swgl, gl, 152 compositor->SurfaceOriginIsTopLeft(), progCache, shaders, 153 aRenderThread.ThreadPool().Raw(), 154 aRenderThread.ThreadPoolLP().Raw(), aRenderThread.MemoryChunkPool(), 155 aRenderThread.GlyphRasterThread().Raw(), &WebRenderMallocSizeOf, 156 &WebRenderMallocEnclosingSizeOf, 0, compositor.get(), 157 compositor->ShouldUseNativeCompositor(), 158 compositor->UsePartialPresent(), 159 compositor->GetMaxPartialPresentRects(), 160 compositor->ShouldDrawPreviousPartialPresentRegions(), mDocHandle, 161 &wrRenderer, mMaxTextureSize, &errorMessage, 162 StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(), 163 panic_on_gl_error, picTileWidth, picTileHeight, 164 gfx::gfxVars::WebRenderRequiresHardwareDriver(), 165 StaticPrefs::gfx_webrender_low_quality_pinch_zoom_AtStartup(), 166 StaticPrefs::gfx_webrender_max_shared_surface_size_AtStartup(), 167 StaticPrefs::gfx_webrender_enable_subpixel_aa_AtStartup(), 168 compositor->ShouldUseLayerCompositor())) { 169 // wr_window_new puts a message into gfxCriticalNote if it returns false 170 MOZ_ASSERT(errorMessage); 171 mError->AssignASCII(errorMessage); 172 wr_api_free_error_msg(errorMessage); 173 return; 174 } 175 MOZ_ASSERT(wrRenderer); 176 177 RefPtr<RenderThread> thread = &aRenderThread; 178 auto renderer = 179 MakeUnique<RendererOGL>(std::move(thread), std::move(compositor), 180 aWindowId, wrRenderer, mBridge); 181 if (wrRenderer && renderer) { 182 wr::WrExternalImageHandler handler = renderer->GetExternalImageHandler(); 183 wr_renderer_set_external_image_handler(wrRenderer, &handler); 184 } 185 186 if (renderer) { 187 layers::SyncObjectHost* syncObj = renderer->GetSyncObject(); 188 if (syncObj) { 189 *mSyncHandle = syncObj->GetSyncHandle(); 190 } 191 } 192 193 aRenderThread.AddRenderer(aWindowId, std::move(renderer)); 194 195 // Kick off shader warmup, outside this NewRenderer task so that any 196 // threads which block on the NewRenderer work can proceed immediately. 197 aRenderThread.BeginShaderWarmupIfNeeded(); 198 } 199 200 const char* Name() override { return "NewRenderer"; } 201 202 private: 203 wr::DocumentHandle** mDocHandle; 204 WebRenderBackend* mBackend; 205 WebRenderCompositor* mCompositor; 206 int32_t* mMaxTextureSize; 207 bool* mUseANGLE; 208 bool* mUseDComp; 209 bool* mUseLayerCompositor; 210 bool* mUseTripleBuffering; 211 bool* mSupportsExternalBufferTextures; 212 layers::CompositorBridgeParent* mBridge; 213 RefPtr<widget::CompositorWidget> mCompositorWidget; 214 layers::SynchronousTask* mTask; 215 LayoutDeviceIntSize mSize; 216 layers::WindowKind mWindowKind; 217 layers::SyncHandle* mSyncHandle; 218 nsACString* mError; 219 }; 220 221 class RemoveRenderer : public RendererEvent { 222 public: 223 explicit RemoveRenderer(layers::SynchronousTask* aTask) : mTask(aTask) { 224 MOZ_COUNT_CTOR(RemoveRenderer); 225 } 226 227 MOZ_COUNTED_DTOR_OVERRIDE(RemoveRenderer) 228 229 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 230 aRenderThread.RemoveRenderer(aWindowId); 231 layers::AutoCompleteTask complete(mTask); 232 } 233 234 const char* Name() override { return "RemoveRenderer"; } 235 236 private: 237 layers::SynchronousTask* mTask; 238 }; 239 240 TransactionBuilder::TransactionBuilder( 241 WebRenderAPI* aApi, bool aUseSceneBuilderThread, 242 layers::RemoteTextureTxnScheduler* aRemoteTextureTxnScheduler, 243 layers::RemoteTextureTxnId aRemoteTextureTxnId) 244 : mRemoteTextureTxnScheduler(aRemoteTextureTxnScheduler), 245 mRemoteTextureTxnId(aRemoteTextureTxnId), 246 mUseSceneBuilderThread(aUseSceneBuilderThread), 247 mApiBackend(aApi->GetBackendType()), 248 mOwnsData(true) { 249 mTxn = wr_transaction_new(mUseSceneBuilderThread); 250 } 251 252 TransactionBuilder::TransactionBuilder( 253 WebRenderAPI* aApi, Transaction* aTxn, bool aUseSceneBuilderThread, 254 bool aOwnsData, 255 layers::RemoteTextureTxnScheduler* aRemoteTextureTxnScheduler, 256 layers::RemoteTextureTxnId aRemoteTextureTxnId) 257 : mRemoteTextureTxnScheduler(aRemoteTextureTxnScheduler), 258 mRemoteTextureTxnId(aRemoteTextureTxnId), 259 mTxn(aTxn), 260 mUseSceneBuilderThread(aUseSceneBuilderThread), 261 mApiBackend(aApi->GetBackendType()), 262 mOwnsData(aOwnsData) {} 263 264 TransactionBuilder::~TransactionBuilder() { 265 if (mOwnsData) { 266 wr_transaction_delete(mTxn); 267 } 268 } 269 270 void TransactionBuilder::SetLowPriority(bool aIsLowPriority) { 271 wr_transaction_set_low_priority(mTxn, aIsLowPriority); 272 } 273 274 void TransactionBuilder::UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch) { 275 wr_transaction_update_epoch(mTxn, aPipelineId, aEpoch); 276 } 277 278 void TransactionBuilder::SetRootPipeline(PipelineId aPipelineId) { 279 wr_transaction_set_root_pipeline(mTxn, aPipelineId); 280 } 281 282 void TransactionBuilder::RemovePipeline(PipelineId aPipelineId) { 283 wr_transaction_remove_pipeline(mTxn, aPipelineId); 284 } 285 286 void TransactionBuilder::SetDisplayList( 287 Epoch aEpoch, wr::WrPipelineId pipeline_id, 288 wr::BuiltDisplayListDescriptor dl_descriptor, 289 wr::Vec<uint8_t>& dl_items_data, wr::Vec<uint8_t>& dl_cache_data, 290 wr::Vec<uint8_t>& dl_spatial_tree) { 291 wr_transaction_set_display_list(mTxn, aEpoch, pipeline_id, dl_descriptor, 292 &dl_items_data.inner, &dl_cache_data.inner, 293 &dl_spatial_tree.inner); 294 } 295 296 void TransactionBuilder::ClearDisplayList(Epoch aEpoch, 297 wr::WrPipelineId aPipelineId) { 298 wr_transaction_clear_display_list(mTxn, aEpoch, aPipelineId); 299 } 300 301 void TransactionBuilder::GenerateFrame(const VsyncId& aVsyncId, bool aPresent, 302 bool aTracked, 303 wr::RenderReasons aReasons) { 304 wr_transaction_generate_frame(mTxn, aVsyncId.mId, aPresent, aTracked, 305 aReasons); 306 } 307 308 void TransactionBuilder::InvalidateRenderedFrame(wr::RenderReasons aReasons) { 309 wr_transaction_invalidate_rendered_frame(mTxn, aReasons); 310 } 311 312 bool TransactionBuilder::IsEmpty() const { 313 return wr_transaction_is_empty(mTxn); 314 } 315 316 bool TransactionBuilder::IsResourceUpdatesEmpty() const { 317 return wr_transaction_resource_updates_is_empty(mTxn); 318 } 319 320 bool TransactionBuilder::IsRenderedFrameInvalidated() const { 321 return wr_transaction_is_rendered_frame_invalidated(mTxn); 322 } 323 324 void TransactionBuilder::SetDocumentView( 325 const LayoutDeviceIntRect& aDocumentRect) { 326 wr::DeviceIntRect wrDocRect; 327 wrDocRect.min.x = aDocumentRect.x; 328 wrDocRect.min.y = aDocumentRect.y; 329 wrDocRect.max.x = aDocumentRect.x + aDocumentRect.width; 330 wrDocRect.max.y = aDocumentRect.y + aDocumentRect.height; 331 wr_transaction_set_document_view(mTxn, &wrDocRect); 332 } 333 334 void TransactionBuilder::RenderOffscreen(wr::WrPipelineId aPipelineId) { 335 wr_transaction_render_offscreen(mTxn, aPipelineId); 336 } 337 338 TransactionWrapper::TransactionWrapper(Transaction* aTxn) : mTxn(aTxn) {} 339 340 void TransactionWrapper::AppendDynamicProperties( 341 const nsTArray<wr::WrOpacityProperty>& aOpacityArray, 342 const nsTArray<wr::WrTransformProperty>& aTransformArray, 343 const nsTArray<wr::WrColorProperty>& aColorArray) { 344 wr_transaction_append_dynamic_properties( 345 mTxn, aOpacityArray.IsEmpty() ? nullptr : aOpacityArray.Elements(), 346 aOpacityArray.Length(), 347 aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(), 348 aTransformArray.Length(), 349 aColorArray.IsEmpty() ? nullptr : aColorArray.Elements(), 350 aColorArray.Length()); 351 } 352 353 void TransactionWrapper::AppendTransformProperties( 354 const nsTArray<wr::WrTransformProperty>& aTransformArray) { 355 wr_transaction_append_transform_properties( 356 mTxn, aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(), 357 aTransformArray.Length()); 358 } 359 360 void TransactionWrapper::UpdateScrollPosition( 361 const wr::ExternalScrollId& aScrollId, 362 const nsTArray<wr::SampledScrollOffset>& aSampledOffsets) { 363 wr_transaction_scroll_layer(mTxn, aScrollId, &aSampledOffsets); 364 } 365 366 void TransactionWrapper::UpdateIsTransformAsyncZooming(uint64_t aAnimationId, 367 bool aIsZooming) { 368 wr_transaction_set_is_transform_async_zooming(mTxn, aAnimationId, aIsZooming); 369 } 370 371 void TransactionWrapper::AddMinimapData(const wr::ExternalScrollId& aScrollId, 372 const MinimapData& aMinimapData) { 373 wr_transaction_add_minimap_data(mTxn, aScrollId, aMinimapData); 374 } 375 376 /*static*/ 377 already_AddRefed<WebRenderAPI> WebRenderAPI::Create( 378 layers::CompositorBridgeParent* aBridge, 379 RefPtr<widget::CompositorWidget>&& aWidget, const wr::WrWindowId& aWindowId, 380 LayoutDeviceIntSize aSize, layers::WindowKind aWindowKind, 381 nsACString& aError) { 382 MOZ_ASSERT(aBridge); 383 MOZ_ASSERT(aWidget); 384 static_assert( 385 sizeof(size_t) == sizeof(uintptr_t), 386 "The FFI bindings assume size_t is the same size as uintptr_t!"); 387 388 wr::DocumentHandle* docHandle = nullptr; 389 WebRenderBackend backend = WebRenderBackend::HARDWARE; 390 WebRenderCompositor compositor = WebRenderCompositor::DRAW; 391 int32_t maxTextureSize = 0; 392 bool useANGLE = false; 393 bool useDComp = false; 394 bool useLayerCompositor = false; 395 bool useTripleBuffering = false; 396 bool supportsExternalBufferTextures = false; 397 layers::SyncHandle syncHandle = {}; 398 399 // Dispatch a synchronous task because the DocumentHandle object needs to be 400 // created on the render thread. If need be we could delay waiting on this 401 // task until the next time we need to access the DocumentHandle object. 402 layers::SynchronousTask task("Create Renderer"); 403 auto event = MakeUnique<NewRenderer>( 404 &docHandle, aBridge, &backend, &compositor, &maxTextureSize, &useANGLE, 405 &useDComp, &useLayerCompositor, &useTripleBuffering, 406 &supportsExternalBufferTextures, std::move(aWidget), &task, aSize, 407 aWindowKind, &syncHandle, &aError); 408 RenderThread::Get()->PostEvent(aWindowId, std::move(event)); 409 410 task.Wait(); 411 412 if (!docHandle) { 413 return nullptr; 414 } 415 416 return RefPtr<WebRenderAPI>( 417 new WebRenderAPI(docHandle, aWindowId, backend, compositor, 418 maxTextureSize, useANGLE, useDComp, 419 useLayerCompositor, useTripleBuffering, 420 supportsExternalBufferTextures, syncHandle)) 421 .forget(); 422 } 423 424 already_AddRefed<WebRenderAPI> WebRenderAPI::Clone() { 425 wr::DocumentHandle* docHandle = nullptr; 426 wr_api_clone(mDocHandle, &docHandle); 427 428 RefPtr<WebRenderAPI> renderApi = new WebRenderAPI( 429 docHandle, mId, mBackend, mCompositor, mMaxTextureSize, mUseANGLE, 430 mUseDComp, mUseLayerCompositor, mUseTripleBuffering, 431 mSupportsExternalBufferTextures, mSyncHandle, this, this); 432 433 return renderApi.forget(); 434 } 435 436 wr::WrIdNamespace WebRenderAPI::GetNamespace() { 437 return wr_api_get_namespace(mDocHandle); 438 } 439 440 WebRenderAPI::WebRenderAPI( 441 wr::DocumentHandle* aHandle, wr::WindowId aId, WebRenderBackend aBackend, 442 WebRenderCompositor aCompositor, uint32_t aMaxTextureSize, bool aUseANGLE, 443 bool aUseDComp, bool aUseLayerCompositor, bool aUseTripleBuffering, 444 bool aSupportsExternalBufferTextures, layers::SyncHandle aSyncHandle, 445 wr::WebRenderAPI* aRootApi, wr::WebRenderAPI* aRootDocumentApi) 446 : mDocHandle(aHandle), 447 mId(aId), 448 mBackend(aBackend), 449 mCompositor(aCompositor), 450 mMaxTextureSize(aMaxTextureSize), 451 mUseANGLE(aUseANGLE), 452 mUseDComp(aUseDComp), 453 mUseLayerCompositor(aUseLayerCompositor), 454 mUseTripleBuffering(aUseTripleBuffering), 455 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures), 456 mCaptureSequence(false), 457 mSyncHandle(aSyncHandle), 458 mRendererDestroyed(false), 459 mRootApi(aRootApi), 460 mRootDocumentApi(aRootDocumentApi) {} 461 462 WebRenderAPI::~WebRenderAPI() { 463 if (!mRootDocumentApi) { 464 wr_api_delete_document(mDocHandle); 465 } 466 467 if (!mRootApi) { 468 MOZ_RELEASE_ASSERT(mRendererDestroyed); 469 wr_api_shut_down(mDocHandle); 470 } 471 472 wr_api_delete(mDocHandle); 473 } 474 475 void WebRenderAPI::DestroyRenderer() { 476 MOZ_RELEASE_ASSERT(!mRootApi); 477 478 RenderThread::Get()->SetDestroyed(GetId()); 479 // Call wr_api_stop_render_backend() before RemoveRenderer. 480 wr_api_stop_render_backend(mDocHandle); 481 482 layers::SynchronousTask task("Destroy WebRenderAPI"); 483 auto event = MakeUnique<RemoveRenderer>(&task); 484 RunOnRenderThread(std::move(event)); 485 task.Wait(); 486 487 mRendererDestroyed = true; 488 } 489 490 wr::WebRenderAPI* WebRenderAPI::GetRootAPI() { 491 if (mRootApi) { 492 return mRootApi; 493 } 494 return this; 495 } 496 497 void WebRenderAPI::UpdateDebugFlags(uint64_t aFlags) { 498 wr_api_set_debug_flags(mDocHandle, wr::DebugFlags{aFlags}); 499 } 500 501 void WebRenderAPI::SendTransaction(TransactionBuilder& aTxn) { 502 if (mRootApi && mRootApi->mRendererDestroyed) { 503 return; 504 } 505 506 if (mPendingRemoteTextureInfoList && 507 !mPendingRemoteTextureInfoList->mList.empty()) { 508 mPendingWrTransactionEvents.emplace( 509 WrTransactionEvent::PendingRemoteTextures( 510 std::move(mPendingRemoteTextureInfoList))); 511 } 512 513 if (mPendingAsyncImagePipelineOps && 514 !mPendingAsyncImagePipelineOps->mList.empty()) { 515 mPendingWrTransactionEvents.emplace( 516 WrTransactionEvent::PendingAsyncImagePipelineOps( 517 std::move(mPendingAsyncImagePipelineOps), this, aTxn)); 518 } 519 520 if (!mPendingWrTransactionEvents.empty()) { 521 mPendingWrTransactionEvents.emplace( 522 WrTransactionEvent::Transaction(this, aTxn)); 523 HandleWrTransactionEvents(RemoteTextureWaitType::AsyncWait); 524 } else { 525 wr_api_send_transaction(mDocHandle, aTxn.Raw(), 526 aTxn.UseSceneBuilderThread()); 527 if (aTxn.mRemoteTextureTxnScheduler) { 528 aTxn.mRemoteTextureTxnScheduler->NotifyTxn(aTxn.mRemoteTextureTxnId); 529 } 530 } 531 } 532 533 layers::RemoteTextureInfoList* WebRenderAPI::GetPendingRemoteTextureInfoList() { 534 if (!mRootApi) { 535 // root api does not support async wait RemoteTexture. 536 return nullptr; 537 } 538 539 if (!mPendingRemoteTextureInfoList) { 540 mPendingRemoteTextureInfoList = MakeUnique<layers::RemoteTextureInfoList>(); 541 } 542 return mPendingRemoteTextureInfoList.get(); 543 } 544 545 layers::AsyncImagePipelineOps* WebRenderAPI::GetPendingAsyncImagePipelineOps( 546 TransactionBuilder& aTxn) { 547 if (!mRootApi) { 548 // root api does not support async wait RemoteTexture. 549 return nullptr; 550 } 551 552 if (!mPendingAsyncImagePipelineOps || 553 mPendingAsyncImagePipelineOps->mTransaction != aTxn.Raw()) { 554 if (mPendingAsyncImagePipelineOps && 555 !mPendingAsyncImagePipelineOps->mList.empty()) { 556 MOZ_ASSERT_UNREACHABLE("unexpected to be called"); 557 gfxCriticalNoteOnce << "Invalid AsyncImagePipelineOps"; 558 } 559 mPendingAsyncImagePipelineOps = 560 MakeUnique<layers::AsyncImagePipelineOps>(aTxn.Raw()); 561 } else { 562 MOZ_RELEASE_ASSERT(mPendingAsyncImagePipelineOps->mTransaction == 563 aTxn.Raw()); 564 } 565 566 return mPendingAsyncImagePipelineOps.get(); 567 } 568 569 bool WebRenderAPI::CheckIsRemoteTextureReady( 570 layers::RemoteTextureInfoList* aList, const TimeStamp& aTimeStamp) { 571 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread()); 572 MOZ_ASSERT(aList); 573 574 RefPtr<WebRenderAPI> self = this; 575 auto callback = [self](const layers::RemoteTextureInfo&) { 576 RefPtr<nsIRunnable> runnable = NewRunnableMethod<RemoteTextureWaitType>( 577 "WebRenderAPI::HandleWrTransactionEvents", self, 578 &WebRenderAPI::HandleWrTransactionEvents, 579 RemoteTextureWaitType::AsyncWait); 580 layers::CompositorThread()->Dispatch(runnable.forget()); 581 }; 582 583 bool isReady = true; 584 while (!aList->mList.empty() && isReady) { 585 auto& front = aList->mList.front(); 586 isReady &= layers::RemoteTextureMap::Get()->CheckRemoteTextureReady( 587 front, callback); 588 if (isReady) { 589 aList->mList.pop(); 590 } 591 } 592 593 if (isReady) { 594 return true; 595 } 596 597 #ifndef DEBUG 598 const auto maxWaitDurationMs = 10000; 599 #else 600 const auto maxWaitDurationMs = 30000; 601 #endif 602 const auto now = TimeStamp::Now(); 603 const auto waitDurationMs = 604 static_cast<uint32_t>((now - aTimeStamp).ToMilliseconds()); 605 606 const auto isTimeout = waitDurationMs > maxWaitDurationMs; 607 if (isTimeout) { 608 MOZ_ASSERT_UNREACHABLE("unexpected to be called"); 609 gfxCriticalNote << "RemoteTexture ready timeout"; 610 } 611 612 return false; 613 } 614 615 void WebRenderAPI::WaitRemoteTextureReady( 616 layers::RemoteTextureInfoList* aList) { 617 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread()); 618 MOZ_ASSERT(aList); 619 620 while (!aList->mList.empty()) { 621 auto& front = aList->mList.front(); 622 layers::RemoteTextureMap::Get()->WaitRemoteTextureReady(front); 623 aList->mList.pop(); 624 } 625 } 626 627 void WebRenderAPI::FlushPendingWrTransactionEventsWithoutWait() { 628 HandleWrTransactionEvents(RemoteTextureWaitType::FlushWithoutWait); 629 } 630 631 void WebRenderAPI::FlushPendingWrTransactionEventsWithWait() { 632 HandleWrTransactionEvents(RemoteTextureWaitType::FlushWithWait); 633 } 634 635 void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType) { 636 auto& events = mPendingWrTransactionEvents; 637 638 while (!events.empty()) { 639 auto& front = events.front(); 640 switch (front.mTag) { 641 case WrTransactionEvent::Tag::Transaction: 642 wr_api_send_transaction(mDocHandle, front.RawTransaction(), 643 front.UseSceneBuilderThread()); 644 if (front.GetTransactionBuilder()->mRemoteTextureTxnScheduler) { 645 front.GetTransactionBuilder()->mRemoteTextureTxnScheduler->NotifyTxn( 646 front.GetTransactionBuilder()->mRemoteTextureTxnId); 647 } 648 break; 649 case WrTransactionEvent::Tag::PendingRemoteTextures: { 650 bool isReady = true; 651 if (aType == RemoteTextureWaitType::AsyncWait) { 652 isReady = CheckIsRemoteTextureReady(front.RemoteTextureInfoList(), 653 front.mTimeStamp); 654 } else if (aType == RemoteTextureWaitType::FlushWithWait) { 655 WaitRemoteTextureReady(front.RemoteTextureInfoList()); 656 } else { 657 MOZ_ASSERT(aType == RemoteTextureWaitType::FlushWithoutWait); 658 auto* list = front.RemoteTextureInfoList(); 659 while (!list->mList.empty()) { 660 auto& front = list->mList.front(); 661 layers::RemoteTextureMap::Get()->SuppressRemoteTextureReadyCheck( 662 front); 663 list->mList.pop(); 664 } 665 } 666 if (!isReady && (aType != RemoteTextureWaitType::FlushWithoutWait)) { 667 return; 668 } 669 break; 670 } 671 case WrTransactionEvent::Tag::PendingAsyncImagePipelineOps: { 672 auto* list = front.AsyncImagePipelineOps(); 673 TransactionBuilder& txn = *front.GetTransactionBuilder(); 674 675 list->HandleOps(txn); 676 break; 677 } 678 } 679 events.pop(); 680 } 681 } 682 683 std::vector<WrHitResult> WebRenderAPI::HitTest(const wr::WorldPoint& aPoint) { 684 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits<12>(), 685 "CompositorHitTestFlags MAX value has to be less than number " 686 "of bits in uint16_t minus 4 for SideBitsPacked"); 687 688 nsTArray<wr::HitResult> wrResults; 689 wr_api_hit_test(mDocHandle, aPoint, &wrResults); 690 691 std::vector<WrHitResult> geckoResults; 692 for (wr::HitResult wrResult : wrResults) { 693 WrHitResult geckoResult; 694 geckoResult.mLayersId = wr::AsLayersId(wrResult.pipeline_id); 695 geckoResult.mScrollId = 696 static_cast<layers::ScrollableLayerGuid::ViewID>(wrResult.scroll_id); 697 geckoResult.mHitInfo.deserialize(wrResult.hit_info & 0x0fff); 698 geckoResult.mSideBits = static_cast<SideBits>(wrResult.hit_info >> 12); 699 700 if (wrResult.animation_id != 0) { 701 geckoResult.mAnimationId = Some(wrResult.animation_id); 702 } else { 703 geckoResult.mAnimationId = Nothing(); 704 } 705 geckoResults.push_back(geckoResult); 706 } 707 return geckoResults; 708 } 709 710 void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size, 711 const gfx::SurfaceFormat& aFormat, 712 const Range<uint8_t>& buffer, bool* aNeedsYFlip) { 713 class Readback : public RendererEvent { 714 public: 715 explicit Readback(layers::SynchronousTask* aTask, TimeStamp aStartTime, 716 gfx::IntSize aSize, const gfx::SurfaceFormat& aFormat, 717 const Range<uint8_t>& aBuffer, bool* aNeedsYFlip) 718 : mTask(aTask), 719 mStartTime(aStartTime), 720 mSize(aSize), 721 mFormat(aFormat), 722 mBuffer(aBuffer), 723 mNeedsYFlip(aNeedsYFlip) { 724 MOZ_COUNT_CTOR(Readback); 725 } 726 727 MOZ_COUNTED_DTOR_OVERRIDE(Readback) 728 729 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 730 RendererStats stats = {0}; 731 wr::FrameReadyParams params = { 732 .present = true, 733 .render = true, 734 .scrolled = false, 735 .tracked = false, 736 }; 737 aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime, params, 738 Some(mSize), 739 wr::SurfaceFormatToImageFormat(mFormat), 740 Some(mBuffer), &stats, mNeedsYFlip); 741 layers::AutoCompleteTask complete(mTask); 742 } 743 744 const char* Name() override { return "Readback"; } 745 746 private: 747 layers::SynchronousTask* mTask; 748 TimeStamp mStartTime; 749 gfx::IntSize mSize; 750 gfx::SurfaceFormat mFormat; 751 const Range<uint8_t>& mBuffer; 752 bool* mNeedsYFlip; 753 }; 754 755 // Disable debug flags during readback. See bug 1436020. 756 UpdateDebugFlags(0); 757 758 layers::SynchronousTask task("Readback"); 759 auto event = MakeUnique<Readback>(&task, aStartTime, size, aFormat, buffer, 760 aNeedsYFlip); 761 // This event will be passed from wr_backend thread to renderer thread. That 762 // implies that all frame data have been processed when the renderer runs this 763 // read-back event. Then, we could make sure this read-back event gets the 764 // latest result. 765 RunOnRenderThread(std::move(event)); 766 767 task.Wait(); 768 769 UpdateDebugFlags(gfx::gfxVars::WebRenderDebugFlags()); 770 } 771 772 void WebRenderAPI::ClearAllCaches() { wr_api_clear_all_caches(mDocHandle); } 773 774 void WebRenderAPI::EnableNativeCompositor(bool aEnable) { 775 wr_api_enable_native_compositor(mDocHandle, aEnable); 776 } 777 778 void WebRenderAPI::SetBatchingLookback(uint32_t aCount) { 779 wr_api_set_batching_lookback(mDocHandle, aCount); 780 } 781 782 void WebRenderAPI::SetBool(wr::BoolParameter aKey, bool aValue) { 783 wr_api_set_bool(mDocHandle, aKey, aValue); 784 } 785 786 void WebRenderAPI::SetInt(wr::IntParameter aKey, int32_t aValue) { 787 wr_api_set_int(mDocHandle, aKey, aValue); 788 } 789 790 void WebRenderAPI::SetFloat(wr::FloatParameter aKey, float aValue) { 791 wr_api_set_float(mDocHandle, aKey, aValue); 792 } 793 794 void WebRenderAPI::SetClearColor(const gfx::DeviceColor& aColor) { 795 RenderThread::Get()->SetClearColor(mId, ToColorF(aColor)); 796 } 797 798 void WebRenderAPI::SetProfilerUI(const nsACString& aUIString) { 799 RenderThread::Get()->SetProfilerUI(mId, aUIString); 800 } 801 802 void WebRenderAPI::Pause() { 803 class PauseEvent : public RendererEvent { 804 public: 805 explicit PauseEvent(layers::SynchronousTask* aTask) : mTask(aTask) { 806 MOZ_COUNT_CTOR(PauseEvent); 807 } 808 809 MOZ_COUNTED_DTOR_OVERRIDE(PauseEvent) 810 811 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 812 aRenderThread.Pause(aWindowId); 813 layers::AutoCompleteTask complete(mTask); 814 } 815 816 const char* Name() override { return "PauseEvent"; } 817 818 private: 819 layers::SynchronousTask* mTask; 820 }; 821 822 layers::SynchronousTask task("Pause"); 823 auto event = MakeUnique<PauseEvent>(&task); 824 RenderThread::Get()->PostEvent(mId, std::move(event)); 825 826 task.Wait(); 827 } 828 829 bool WebRenderAPI::Resume() { 830 class ResumeEvent : public RendererEvent { 831 public: 832 explicit ResumeEvent(layers::SynchronousTask* aTask, bool* aResult) 833 : mTask(aTask), mResult(aResult) { 834 MOZ_COUNT_CTOR(ResumeEvent); 835 } 836 837 MOZ_COUNTED_DTOR_OVERRIDE(ResumeEvent) 838 839 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 840 *mResult = aRenderThread.Resume(aWindowId); 841 layers::AutoCompleteTask complete(mTask); 842 } 843 844 const char* Name() override { return "ResumeEvent"; } 845 846 private: 847 layers::SynchronousTask* mTask; 848 bool* mResult; 849 }; 850 851 bool result = false; 852 layers::SynchronousTask task("Resume"); 853 auto event = MakeUnique<ResumeEvent>(&task, &result); 854 RenderThread::Get()->PostEvent(mId, std::move(event)); 855 856 task.Wait(); 857 return result; 858 } 859 860 void WebRenderAPI::NotifyMemoryPressure() { 861 wr_api_notify_memory_pressure(mDocHandle); 862 } 863 864 void WebRenderAPI::AccumulateMemoryReport(MemoryReport* aReport) { 865 wr_api_accumulate_memory_report(mDocHandle, aReport, &WebRenderMallocSizeOf, 866 &WebRenderMallocEnclosingSizeOf); 867 } 868 869 void WebRenderAPI::WakeSceneBuilder() { wr_api_wake_scene_builder(mDocHandle); } 870 871 void WebRenderAPI::FlushSceneBuilder() { 872 wr_api_flush_scene_builder(mDocHandle); 873 } 874 875 void WebRenderAPI::WaitUntilPresentationFlushed() { 876 class WaitFlushedEvent : public RendererEvent { 877 public: 878 explicit WaitFlushedEvent(layers::SynchronousTask* aTask) : mTask(aTask) { 879 MOZ_COUNT_CTOR(WaitFlushedEvent); 880 } 881 882 MOZ_COUNTED_DTOR_OVERRIDE(WaitFlushedEvent) 883 884 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 885 if (RendererOGL* renderer = aRenderThread.GetRenderer(aWindowId)) { 886 if (RenderCompositor* compositor = renderer->GetCompositor()) { 887 compositor->WaitUntilPresentationFlushed(); 888 } 889 } 890 layers::AutoCompleteTask complete(mTask); 891 } 892 893 const char* Name() override { return "WaitFlushedEvent"; } 894 895 private: 896 layers::SynchronousTask* mTask; 897 }; 898 899 layers::SynchronousTask task("WaitUntilPresentationFlushed"); 900 auto event = MakeUnique<WaitFlushedEvent>(&task); 901 // This event will be passed from wr_backend thread to renderer thread. That 902 // implies that all frame data have been processed when the renderer runs this 903 // event. 904 RunOnRenderThread(std::move(event)); 905 906 task.Wait(); 907 } 908 909 void WebRenderAPI::Capture() { 910 // see CaptureBits 911 // SCENE | FRAME | TILE_CACHE 912 uint8_t bits = 15; // TODO: get from JavaScript 913 const char* path = "wr-capture"; // TODO: get from JavaScript 914 const char* revision = MOZ_SOURCE_STAMP_VALUE; 915 wr_api_capture(mDocHandle, path, revision, bits); 916 } 917 918 void WebRenderAPI::StartCaptureSequence(const nsACString& aPath, 919 uint32_t aFlags) { 920 if (mCaptureSequence) { 921 wr_api_stop_capture_sequence(mDocHandle); 922 } 923 924 wr_api_start_capture_sequence(mDocHandle, PromiseFlatCString(aPath).get(), 925 MOZ_SOURCE_STAMP_VALUE, aFlags); 926 927 mCaptureSequence = true; 928 } 929 930 void WebRenderAPI::StopCaptureSequence() { 931 if (mCaptureSequence) { 932 wr_api_stop_capture_sequence(mDocHandle); 933 } 934 935 mCaptureSequence = false; 936 } 937 938 void WebRenderAPI::BeginRecording(const TimeStamp& aRecordingStart, 939 wr::PipelineId aRootPipelineId) { 940 class BeginRecordingEvent final : public RendererEvent { 941 public: 942 explicit BeginRecordingEvent(const TimeStamp& aRecordingStart, 943 wr::PipelineId aRootPipelineId) 944 : mRecordingStart(aRecordingStart), mRootPipelineId(aRootPipelineId) { 945 MOZ_COUNT_CTOR(BeginRecordingEvent); 946 } 947 948 ~BeginRecordingEvent() { MOZ_COUNT_DTOR(BeginRecordingEvent); } 949 950 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 951 aRenderThread.BeginRecordingForWindow(aWindowId, mRecordingStart, 952 mRootPipelineId); 953 } 954 955 const char* Name() override { return "BeginRecordingEvent"; } 956 957 private: 958 TimeStamp mRecordingStart; 959 wr::PipelineId mRootPipelineId; 960 }; 961 962 auto event = 963 MakeUnique<BeginRecordingEvent>(aRecordingStart, aRootPipelineId); 964 RunOnRenderThread(std::move(event)); 965 } 966 967 RefPtr<WebRenderAPI::EndRecordingPromise> WebRenderAPI::EndRecording() { 968 class EndRecordingEvent final : public RendererEvent { 969 public: 970 explicit EndRecordingEvent() { MOZ_COUNT_CTOR(EndRecordingEvent); } 971 972 MOZ_COUNTED_DTOR(EndRecordingEvent); 973 974 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 975 Maybe<layers::FrameRecording> recording = 976 aRenderThread.EndRecordingForWindow(aWindowId); 977 978 if (recording) { 979 mPromise.Resolve(recording.extract(), __func__); 980 } else { 981 mPromise.Reject(NS_ERROR_UNEXPECTED, __func__); 982 } 983 } 984 985 RefPtr<WebRenderAPI::EndRecordingPromise> GetPromise() { 986 return mPromise.Ensure(__func__); 987 } 988 989 const char* Name() override { return "EndRecordingEvent"; } 990 991 private: 992 MozPromiseHolder<WebRenderAPI::EndRecordingPromise> mPromise; 993 }; 994 995 auto event = MakeUnique<EndRecordingEvent>(); 996 auto promise = event->GetPromise(); 997 998 RunOnRenderThread(std::move(event)); 999 return promise; 1000 } 1001 1002 void TransactionBuilder::Clear() { wr_resource_updates_clear(mTxn); } 1003 1004 Transaction* TransactionBuilder::Take() { 1005 if (!mOwnsData) { 1006 MOZ_ASSERT_UNREACHABLE("unexpected to be called"); 1007 return nullptr; 1008 } 1009 Transaction* txn = mTxn; 1010 mTxn = wr_transaction_new(mUseSceneBuilderThread); 1011 return txn; 1012 } 1013 1014 void TransactionBuilder::Notify(wr::Checkpoint aWhen, 1015 UniquePtr<NotificationHandler> aEvent) { 1016 wr_transaction_notify(mTxn, aWhen, 1017 reinterpret_cast<uintptr_t>(aEvent.release())); 1018 } 1019 1020 void TransactionBuilder::AddImage(ImageKey key, 1021 const ImageDescriptor& aDescriptor, 1022 wr::Vec<uint8_t>& aBytes) { 1023 wr_resource_updates_add_image(mTxn, key, &aDescriptor, &aBytes.inner); 1024 } 1025 1026 void TransactionBuilder::AddBlobImage(BlobImageKey key, 1027 const ImageDescriptor& aDescriptor, 1028 uint16_t aTileSize, 1029 wr::Vec<uint8_t>& aBytes, 1030 const wr::DeviceIntRect& aVisibleRect) { 1031 wr_resource_updates_add_blob_image(mTxn, key, &aDescriptor, aTileSize, 1032 &aBytes.inner, aVisibleRect); 1033 } 1034 1035 void TransactionBuilder::AddExternalImage(ImageKey key, 1036 const ImageDescriptor& aDescriptor, 1037 ExternalImageId aExtID, 1038 wr::ExternalImageType aImageType, 1039 uint8_t aChannelIndex, 1040 bool aNormalizedUvs) { 1041 wr_resource_updates_add_external_image(mTxn, key, &aDescriptor, aExtID, 1042 &aImageType, aChannelIndex, 1043 aNormalizedUvs); 1044 } 1045 1046 void TransactionBuilder::AddExternalImageBuffer( 1047 ImageKey aKey, const ImageDescriptor& aDescriptor, 1048 ExternalImageId aHandle) { 1049 auto channelIndex = 0; 1050 AddExternalImage(aKey, aDescriptor, aHandle, wr::ExternalImageType::Buffer(), 1051 channelIndex); 1052 } 1053 1054 void TransactionBuilder::UpdateImageBuffer(ImageKey aKey, 1055 const ImageDescriptor& aDescriptor, 1056 wr::Vec<uint8_t>& aBytes) { 1057 wr_resource_updates_update_image(mTxn, aKey, &aDescriptor, &aBytes.inner); 1058 } 1059 1060 void TransactionBuilder::UpdateBlobImage(BlobImageKey aKey, 1061 const ImageDescriptor& aDescriptor, 1062 wr::Vec<uint8_t>& aBytes, 1063 const wr::DeviceIntRect& aVisibleRect, 1064 const wr::LayoutIntRect& aDirtyRect) { 1065 wr_resource_updates_update_blob_image(mTxn, aKey, &aDescriptor, &aBytes.inner, 1066 aVisibleRect, aDirtyRect); 1067 } 1068 1069 void TransactionBuilder::UpdateExternalImage(ImageKey aKey, 1070 const ImageDescriptor& aDescriptor, 1071 ExternalImageId aExtID, 1072 wr::ExternalImageType aImageType, 1073 uint8_t aChannelIndex, 1074 bool aNormalizedUvs) { 1075 wr_resource_updates_update_external_image(mTxn, aKey, &aDescriptor, aExtID, 1076 &aImageType, aChannelIndex, 1077 aNormalizedUvs); 1078 } 1079 1080 void TransactionBuilder::UpdateExternalImageWithDirtyRect( 1081 ImageKey aKey, const ImageDescriptor& aDescriptor, ExternalImageId aExtID, 1082 wr::ExternalImageType aImageType, const wr::DeviceIntRect& aDirtyRect, 1083 uint8_t aChannelIndex, bool aNormalizedUvs) { 1084 wr_resource_updates_update_external_image_with_dirty_rect( 1085 mTxn, aKey, &aDescriptor, aExtID, &aImageType, aChannelIndex, 1086 aNormalizedUvs, aDirtyRect); 1087 } 1088 1089 void TransactionBuilder::SetBlobImageVisibleArea( 1090 BlobImageKey aKey, const wr::DeviceIntRect& aArea) { 1091 wr_resource_updates_set_blob_image_visible_area(mTxn, aKey, &aArea); 1092 } 1093 1094 void TransactionBuilder::DeleteImage(ImageKey aKey) { 1095 wr_resource_updates_delete_image(mTxn, aKey); 1096 } 1097 1098 void TransactionBuilder::DeleteBlobImage(BlobImageKey aKey) { 1099 wr_resource_updates_delete_blob_image(mTxn, aKey); 1100 } 1101 1102 void TransactionBuilder::AddSnapshotImage(wr::SnapshotImageKey aKey) { 1103 wr_resource_updates_add_snapshot_image(mTxn, aKey); 1104 } 1105 1106 void TransactionBuilder::DeleteSnapshotImage(wr::SnapshotImageKey aKey) { 1107 wr_resource_updates_delete_snapshot_image(mTxn, aKey); 1108 } 1109 1110 void TransactionBuilder::AddRawFont(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes, 1111 uint32_t aIndex) { 1112 wr_resource_updates_add_raw_font(mTxn, aKey, &aBytes.inner, aIndex); 1113 } 1114 1115 void TransactionBuilder::AddFontDescriptor(wr::FontKey aKey, 1116 wr::Vec<uint8_t>& aBytes, 1117 uint32_t aIndex) { 1118 wr_resource_updates_add_font_descriptor(mTxn, aKey, &aBytes.inner, aIndex); 1119 } 1120 1121 void TransactionBuilder::DeleteFont(wr::FontKey aKey) { 1122 wr_resource_updates_delete_font(mTxn, aKey); 1123 } 1124 1125 void TransactionBuilder::AddFontInstance( 1126 wr::FontInstanceKey aKey, wr::FontKey aFontKey, float aGlyphSize, 1127 const wr::FontInstanceOptions* aOptions, 1128 const wr::FontInstancePlatformOptions* aPlatformOptions, 1129 wr::Vec<uint8_t>& aVariations) { 1130 wr_resource_updates_add_font_instance(mTxn, aKey, aFontKey, aGlyphSize, 1131 aOptions, aPlatformOptions, 1132 &aVariations.inner); 1133 } 1134 1135 void TransactionBuilder::DeleteFontInstance(wr::FontInstanceKey aKey) { 1136 wr_resource_updates_delete_font_instance(mTxn, aKey); 1137 } 1138 1139 void TransactionBuilder::UpdateQualitySettings( 1140 bool aForceSubpixelAAWherePossible) { 1141 wr_transaction_set_quality_settings(mTxn, aForceSubpixelAAWherePossible); 1142 } 1143 1144 class FrameStartTime : public RendererEvent { 1145 public: 1146 explicit FrameStartTime(const TimeStamp& aTime) : mTime(aTime) { 1147 MOZ_COUNT_CTOR(FrameStartTime); 1148 } 1149 1150 MOZ_COUNTED_DTOR_OVERRIDE(FrameStartTime) 1151 1152 void Run(RenderThread& aRenderThread, WindowId aWindowId) override { 1153 auto renderer = aRenderThread.GetRenderer(aWindowId); 1154 if (renderer) { 1155 renderer->SetFrameStartTime(mTime); 1156 } 1157 } 1158 1159 const char* Name() override { return "FrameStartTime"; } 1160 1161 private: 1162 TimeStamp mTime; 1163 }; 1164 1165 void WebRenderAPI::SetFrameStartTime(const TimeStamp& aTime) { 1166 auto event = MakeUnique<FrameStartTime>(aTime); 1167 RunOnRenderThread(std::move(event)); 1168 } 1169 1170 void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) { 1171 auto event = reinterpret_cast<uintptr_t>(aEvent.release()); 1172 wr_api_send_external_event(mDocHandle, event); 1173 } 1174 1175 DisplayListBuilder::DisplayListBuilder(PipelineId aId, 1176 WebRenderBackend aBackend) 1177 : mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()), 1178 mActiveFixedPosTracker(nullptr), 1179 mPipelineId(aId), 1180 mBackend(aBackend), 1181 mDisplayItemCache(nullptr) { 1182 MOZ_COUNT_CTOR(DisplayListBuilder); 1183 mWrState = wr_state_new(aId); 1184 1185 if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) { 1186 mDisplayItemCache->SetPipelineId(aId); 1187 } 1188 } 1189 1190 DisplayListBuilder::~DisplayListBuilder() { 1191 MOZ_COUNT_DTOR(DisplayListBuilder); 1192 wr_state_delete(mWrState); 1193 } 1194 1195 void DisplayListBuilder::Save() { wr_dp_save(mWrState); } 1196 void DisplayListBuilder::Restore() { wr_dp_restore(mWrState); } 1197 void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState); } 1198 1199 usize DisplayListBuilder::Dump(usize aIndent, const Maybe<usize>& aStart, 1200 const Maybe<usize>& aEnd) { 1201 return wr_dump_display_list(mWrState, aIndent, aStart.ptrOr(nullptr), 1202 aEnd.ptrOr(nullptr)); 1203 } 1204 1205 void DisplayListBuilder::DumpSerializedDisplayList() { 1206 wr_dump_serialized_display_list(mWrState); 1207 } 1208 1209 void DisplayListBuilder::Begin(layers::DisplayItemCache* aCache) { 1210 wr_api_begin_builder(mWrState); 1211 1212 mScrollIds.clear(); 1213 mASRToSpatialIdMap.clear(); 1214 mCurrentSpaceAndClipChain = wr::RootScrollNodeWithChain(); 1215 mClipChainLeaf = Nothing(); 1216 mSuspendedSpaceAndClipChain = Nothing(); 1217 mSuspendedClipChainLeaf = Nothing(); 1218 mCachedTextDT = nullptr; 1219 mCachedContext = nullptr; 1220 mActiveFixedPosTracker = nullptr; 1221 mDisplayItemCache = aCache; 1222 mCurrentCacheSlot = Nothing(); 1223 } 1224 1225 void DisplayListBuilder::End(BuiltDisplayList& aOutDisplayList) { 1226 wr_api_end_builder( 1227 mWrState, &aOutDisplayList.dl_desc, &aOutDisplayList.dl_items.inner, 1228 &aOutDisplayList.dl_cache.inner, &aOutDisplayList.dl_spatial_tree.inner); 1229 1230 mDisplayItemCache = nullptr; 1231 } 1232 1233 void DisplayListBuilder::End(layers::DisplayListData& aOutTransaction) { 1234 if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) { 1235 wr_dp_set_cache_size(mWrState, mDisplayItemCache->CurrentSize()); 1236 } 1237 1238 wr::VecU8 dlItems, dlCache, dlSpatialTree; 1239 wr_api_end_builder(mWrState, &aOutTransaction.mDLDesc, &dlItems.inner, 1240 &dlCache.inner, &dlSpatialTree.inner); 1241 aOutTransaction.mDLItems.emplace(dlItems.inner.data, dlItems.inner.length, 1242 dlItems.inner.capacity); 1243 aOutTransaction.mDLCache.emplace(dlCache.inner.data, dlCache.inner.length, 1244 dlCache.inner.capacity); 1245 aOutTransaction.mDLSpatialTree.emplace(dlSpatialTree.inner.data, 1246 dlSpatialTree.inner.length, 1247 dlSpatialTree.inner.capacity); 1248 dlItems.inner.capacity = 0; 1249 dlItems.inner.data = nullptr; 1250 dlCache.inner.capacity = 0; 1251 dlCache.inner.data = nullptr; 1252 dlSpatialTree.inner.capacity = 0; 1253 dlSpatialTree.inner.data = nullptr; 1254 } 1255 1256 Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext( 1257 const wr::StackingContextParams& aParams, const wr::LayoutRect& aBounds, 1258 const wr::RasterSpace& aRasterSpace) { 1259 MOZ_ASSERT(mClipChainLeaf.isNothing(), 1260 "Non-empty leaf from clip chain given, but not used with SC!"); 1261 1262 WRDL_LOG( 1263 "PushStackingContext b=%s t=%s id=0x%" PRIx64 "\n", mWrState, 1264 ToString(aBounds).c_str(), 1265 aParams.mTransformPtr ? ToString(*aParams.mTransformPtr).c_str() : "none", 1266 aParams.animation ? aParams.animation->id : 0); 1267 1268 auto spatialId = wr_dp_push_stacking_context( 1269 mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aParams, 1270 aParams.mTransformPtr, aParams.mFilters.Elements(), 1271 aParams.mFilters.Length(), aParams.mFilterDatas.Elements(), 1272 aParams.mFilterDatas.Length(), aRasterSpace); 1273 1274 return spatialId.id != 0 ? Some(spatialId) : Nothing(); 1275 } 1276 1277 void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame) { 1278 WRDL_LOG("PopStackingContext\n", mWrState); 1279 wr_dp_pop_stacking_context(mWrState, aIsReferenceFrame); 1280 } 1281 1282 wr::WrClipChainId DisplayListBuilder::DefineClipChain( 1283 Span<const wr::WrClipId> aClips, const Maybe<wr::WrClipChainId>& aParent) { 1284 CancelGroup(); 1285 1286 const uint64_t* parent = aParent ? &aParent->id : nullptr; 1287 uint64_t clipchainId = wr_dp_define_clipchain( 1288 mWrState, parent, aClips.Elements(), aClips.Length()); 1289 if (MOZ_LOG_TEST(sWrDLLog, LogLevel::Debug)) { 1290 nsCString message; 1291 message.AppendPrintf("DefineClipChain id=%" PRIu64 1292 " clipCount=%zu clipIds=[", 1293 clipchainId, aClips.Length()); 1294 for (const auto& clip : aClips) { 1295 message.AppendPrintf("%" PRIuPTR ",", clip.id); 1296 } 1297 message.Append("]"); 1298 WRDL_LOG("%s", mWrState, message.get()); 1299 } 1300 return wr::WrClipChainId{clipchainId}; 1301 } 1302 1303 wr::WrClipId DisplayListBuilder::DefineImageMaskClip( 1304 const wr::ImageMask& aMask, const nsTArray<wr::LayoutPoint>& aPoints, 1305 wr::FillRule aFillRule) { 1306 CancelGroup(); 1307 1308 WrClipId clipId = wr_dp_define_image_mask_clip_with_parent_clip_chain( 1309 mWrState, mCurrentSpaceAndClipChain.space, aMask, aPoints.Elements(), 1310 aPoints.Length(), aFillRule); 1311 1312 return clipId; 1313 } 1314 1315 wr::WrClipId DisplayListBuilder::DefineRoundedRectClip( 1316 Maybe<wr::WrSpatialId> aSpace, const wr::ComplexClipRegion& aComplex) { 1317 CancelGroup(); 1318 1319 WrClipId clipId; 1320 if (aSpace) { 1321 clipId = wr_dp_define_rounded_rect_clip(mWrState, *aSpace, aComplex); 1322 } else { 1323 clipId = wr_dp_define_rounded_rect_clip( 1324 mWrState, mCurrentSpaceAndClipChain.space, aComplex); 1325 } 1326 1327 return clipId; 1328 } 1329 1330 wr::WrClipId DisplayListBuilder::DefineRectClip(Maybe<wr::WrSpatialId> aSpace, 1331 wr::LayoutRect aClipRect) { 1332 CancelGroup(); 1333 1334 WrClipId clipId; 1335 if (aSpace) { 1336 clipId = wr_dp_define_rect_clip(mWrState, *aSpace, aClipRect); 1337 } else { 1338 clipId = wr_dp_define_rect_clip(mWrState, mCurrentSpaceAndClipChain.space, 1339 aClipRect); 1340 } 1341 1342 return clipId; 1343 } 1344 1345 wr::WrSpatialId DisplayListBuilder::DefineStickyFrame( 1346 const ActiveScrolledRoot* aStickyAsr, 1347 Maybe<wr::WrSpatialId> aParentSpatialId, const wr::LayoutRect& aContentRect, 1348 const float* aTopMargin, const float* aRightMargin, 1349 const float* aBottomMargin, const float* aLeftMargin, 1350 const StickyOffsetBounds& aVerticalBounds, 1351 const StickyOffsetBounds& aHorizontalBounds, 1352 const wr::LayoutVector2D& aAppliedOffset, wr::SpatialTreeItemKey aKey, 1353 const WrAnimationProperty* aAnimation) { 1354 auto spatialId = wr_dp_define_sticky_frame( 1355 mWrState, aParentSpatialId.valueOr(mCurrentSpaceAndClipChain.space), 1356 aContentRect, aTopMargin, aRightMargin, aBottomMargin, aLeftMargin, 1357 aVerticalBounds, aHorizontalBounds, aAppliedOffset, aKey, aAnimation); 1358 1359 mASRToSpatialIdMap.emplace(aStickyAsr, spatialId); 1360 1361 WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n", 1362 mWrState, spatialId.id, ToString(aContentRect).c_str(), 1363 aTopMargin ? ToString(*aTopMargin).c_str() : "none", 1364 aRightMargin ? ToString(*aRightMargin).c_str() : "none", 1365 aBottomMargin ? ToString(*aBottomMargin).c_str() : "none", 1366 aLeftMargin ? ToString(*aLeftMargin).c_str() : "none", 1367 ToString(aVerticalBounds).c_str(), 1368 ToString(aHorizontalBounds).c_str(), 1369 ToString(aAppliedOffset).c_str()); 1370 1371 return spatialId; 1372 } 1373 1374 Maybe<wr::WrSpatialId> DisplayListBuilder::GetScrollIdForDefinedScrollLayer( 1375 layers::ScrollableLayerGuid::ViewID aViewId) const { 1376 if (aViewId == layers::ScrollableLayerGuid::NULL_SCROLL_ID) { 1377 return Some(wr::RootScrollNode()); 1378 } 1379 1380 auto it = mScrollIds.find(aViewId); 1381 if (it == mScrollIds.end()) { 1382 return Nothing(); 1383 } 1384 1385 return Some(it->second); 1386 } 1387 1388 Maybe<wr::WrSpatialId> DisplayListBuilder::GetSpatialIdForDefinedStickyLayer( 1389 const ActiveScrolledRoot* aASR) const { 1390 MOZ_ASSERT(aASR->mKind == ActiveScrolledRoot::ASRKind::Sticky); 1391 auto it = mASRToSpatialIdMap.find(aASR); 1392 if (it == mASRToSpatialIdMap.end()) { 1393 return Nothing(); 1394 } 1395 1396 return Some(it->second); 1397 } 1398 1399 wr::WrSpatialId DisplayListBuilder::DefineScrollLayer( 1400 const layers::ScrollableLayerGuid::ViewID& aViewId, 1401 const Maybe<wr::WrSpatialId>& aParent, const wr::LayoutRect& aContentRect, 1402 const wr::LayoutRect& aClipRect, const wr::LayoutVector2D& aScrollOffset, 1403 wr::APZScrollGeneration aScrollOffsetGeneration, 1404 wr::HasScrollLinkedEffect aHasScrollLinkedEffect, 1405 wr::SpatialTreeItemKey aKey) { 1406 auto it = mScrollIds.find(aViewId); 1407 if (it != mScrollIds.end()) { 1408 return it->second; 1409 } 1410 1411 // We haven't defined aViewId before, so let's define it now. 1412 wr::WrSpatialId defaultParent = mCurrentSpaceAndClipChain.space; 1413 1414 auto space = wr_dp_define_scroll_layer( 1415 mWrState, aViewId, aParent ? aParent.ptr() : &defaultParent, aContentRect, 1416 aClipRect, aScrollOffset, aScrollOffsetGeneration, aHasScrollLinkedEffect, 1417 aKey); 1418 1419 WRDL_LOG("DefineScrollLayer id=%" PRIu64 1420 "/%zu p=%s co=%s cl=%s generation=%s hasScrollLinkedEffect=%s\n", 1421 mWrState, aViewId, space.id, 1422 aParent ? ToString(aParent->id).c_str() : "(nil)", 1423 ToString(aContentRect).c_str(), ToString(aClipRect).c_str(), 1424 ToString(aScrollOffsetGeneration).c_str(), 1425 ToString(aHasScrollLinkedEffect).c_str()); 1426 1427 mScrollIds[aViewId] = space; 1428 return space; 1429 } 1430 1431 void DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds, 1432 const wr::LayoutRect& aClip, 1433 bool aIsBackfaceVisible, 1434 bool aForceAntiAliasing, bool aIsCheckerboard, 1435 const wr::ColorF& aColor) { 1436 wr::LayoutRect clip = MergeClipLeaf(aClip); 1437 WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState, ToString(aBounds).c_str(), 1438 ToString(clip).c_str(), ToString(aColor).c_str()); 1439 wr_dp_push_rect(mWrState, aBounds, clip, aIsBackfaceVisible, 1440 aForceAntiAliasing, aIsCheckerboard, 1441 &mCurrentSpaceAndClipChain, aColor); 1442 } 1443 1444 void DisplayListBuilder::PushRoundedRect(const wr::LayoutRect& aBounds, 1445 const wr::LayoutRect& aClip, 1446 bool aIsBackfaceVisible, 1447 const wr::ColorF& aColor) { 1448 wr::LayoutRect clip = MergeClipLeaf(aClip); 1449 WRDL_LOG("PushRoundedRect b=%s cl=%s c=%s\n", mWrState, 1450 ToString(aBounds).c_str(), ToString(clip).c_str(), 1451 ToString(aColor).c_str()); 1452 1453 // Draw the rounded rectangle as a border with rounded corners. We could also 1454 // draw this as a rectangle clipped to a rounded rectangle, but: 1455 // - clips are not cached; borders are 1456 // - a simple border like this will be drawn as an image 1457 // - Processing lots of clips is not WebRender's strong point. 1458 // 1459 // Made the borders thicker than one half the width/height, to avoid 1460 // little white dots at the center at some magnifications. 1461 wr::BorderSide side = {aColor, wr::BorderStyle::Solid}; 1462 float h = aBounds.width() * 0.6f; 1463 float v = aBounds.height() * 0.6f; 1464 wr::LayoutSideOffsets widths = {v, h, v, h}; 1465 wr::BorderRadius radii = {{h, v}, {h, v}, {h, v}, {h, v}}; 1466 1467 // Anti-aliased borders are required for rounded borders. 1468 wr_dp_push_border(mWrState, aBounds, clip, aIsBackfaceVisible, 1469 &mCurrentSpaceAndClipChain, wr::AntialiasBorder::Yes, 1470 widths, side, side, side, side, radii); 1471 } 1472 1473 void DisplayListBuilder::PushHitTest( 1474 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1475 bool aIsBackfaceVisible, 1476 const layers::ScrollableLayerGuid::ViewID& aScrollId, 1477 const gfx::CompositorHitTestInfo& aHitInfo, SideBits aSideBits) { 1478 wr::LayoutRect clip = MergeClipLeaf(aClip); 1479 WRDL_LOG("PushHitTest b=%s cl=%s\n", mWrState, ToString(aBounds).c_str(), 1480 ToString(clip).c_str()); 1481 1482 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits<12>(), 1483 "CompositorHitTestFlags MAX value has to be less than number " 1484 "of bits in uint16_t minus 4 for SideBitsPacked"); 1485 1486 uint16_t hitInfoBits = static_cast<uint16_t>(aHitInfo.serialize()) | 1487 (static_cast<uint16_t>(aSideBits) << 12); 1488 1489 wr_dp_push_hit_test(mWrState, aBounds, clip, aIsBackfaceVisible, 1490 &mCurrentSpaceAndClipChain, aScrollId, hitInfoBits); 1491 } 1492 1493 void DisplayListBuilder::PushRectWithAnimation( 1494 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1495 bool aIsBackfaceVisible, const wr::ColorF& aColor, 1496 const WrAnimationProperty* aAnimation) { 1497 wr::LayoutRect clip = MergeClipLeaf(aClip); 1498 WRDL_LOG("PushRectWithAnimation b=%s cl=%s c=%s\n", mWrState, 1499 ToString(aBounds).c_str(), ToString(clip).c_str(), 1500 ToString(aColor).c_str()); 1501 1502 wr_dp_push_rect_with_animation(mWrState, aBounds, clip, aIsBackfaceVisible, 1503 &mCurrentSpaceAndClipChain, aColor, 1504 aAnimation); 1505 } 1506 1507 void DisplayListBuilder::PushBackdropFilter( 1508 const wr::LayoutRect& aBounds, const wr::ComplexClipRegion& aRegion, 1509 const nsTArray<wr::FilterOp>& aFilters, 1510 const nsTArray<wr::WrFilterData>& aFilterDatas, bool aIsBackfaceVisible) { 1511 wr::LayoutRect clip = MergeClipLeaf(aBounds); 1512 WRDL_LOG("PushBackdropFilter b=%s c=%s\n", mWrState, 1513 ToString(aBounds).c_str(), ToString(clip).c_str()); 1514 1515 auto clipId = DefineRoundedRectClip(Nothing(), aRegion); 1516 auto clipChainId = 1517 DefineClipChain({&clipId, 1}, CurrentClipChainIdIfNotRoot()); 1518 auto spaceAndClip = 1519 WrSpaceAndClipChain{mCurrentSpaceAndClipChain.space, clipChainId.id}; 1520 1521 wr_dp_push_backdrop_filter(mWrState, aBounds, clip, aIsBackfaceVisible, 1522 &spaceAndClip, aFilters.Elements(), 1523 aFilters.Length(), aFilterDatas.Elements(), 1524 aFilterDatas.Length()); 1525 } 1526 1527 void DisplayListBuilder::PushLinearGradient( 1528 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1529 bool aIsBackfaceVisible, const wr::LayoutPoint& aStartPoint, 1530 const wr::LayoutPoint& aEndPoint, const nsTArray<wr::GradientStop>& aStops, 1531 wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize, 1532 const wr::LayoutSize aTileSpacing) { 1533 wr_dp_push_linear_gradient( 1534 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1535 &mCurrentSpaceAndClipChain, aStartPoint, aEndPoint, aStops.Elements(), 1536 aStops.Length(), aExtendMode, aTileSize, aTileSpacing); 1537 } 1538 1539 void DisplayListBuilder::PushRadialGradient( 1540 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1541 bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter, 1542 const wr::LayoutSize& aRadius, const nsTArray<wr::GradientStop>& aStops, 1543 wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize, 1544 const wr::LayoutSize aTileSpacing) { 1545 wr_dp_push_radial_gradient( 1546 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1547 &mCurrentSpaceAndClipChain, aCenter, aRadius, aStops.Elements(), 1548 aStops.Length(), aExtendMode, aTileSize, aTileSpacing); 1549 } 1550 1551 void DisplayListBuilder::PushConicGradient( 1552 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1553 bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter, const float aAngle, 1554 const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode, 1555 const wr::LayoutSize aTileSize, const wr::LayoutSize aTileSpacing) { 1556 wr_dp_push_conic_gradient(mWrState, aBounds, MergeClipLeaf(aClip), 1557 aIsBackfaceVisible, &mCurrentSpaceAndClipChain, 1558 aCenter, aAngle, aStops.Elements(), aStops.Length(), 1559 aExtendMode, aTileSize, aTileSpacing); 1560 } 1561 1562 void DisplayListBuilder::PushImage( 1563 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1564 bool aIsBackfaceVisible, bool aForceAntiAliasing, 1565 wr::ImageRendering aFilter, wr::ImageKey aImage, bool aPremultipliedAlpha, 1566 const wr::ColorF& aColor, bool aPreferCompositorSurface, 1567 bool aSupportsExternalCompositing) { 1568 wr::LayoutRect clip = MergeClipLeaf(aClip); 1569 WRDL_LOG("PushImage b=%s cl=%s\n", mWrState, ToString(aBounds).c_str(), 1570 ToString(clip).c_str()); 1571 wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible, 1572 aForceAntiAliasing, &mCurrentSpaceAndClipChain, aFilter, 1573 aImage, aPremultipliedAlpha, aColor, 1574 aPreferCompositorSurface, aSupportsExternalCompositing); 1575 } 1576 1577 void DisplayListBuilder::PushRepeatingImage( 1578 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1579 bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize, 1580 const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter, 1581 wr::ImageKey aImage, bool aPremultipliedAlpha, const wr::ColorF& aColor) { 1582 wr::LayoutRect clip = MergeClipLeaf(aClip); 1583 WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState, 1584 ToString(aBounds).c_str(), ToString(clip).c_str(), 1585 ToString(aStretchSize).c_str(), ToString(aTileSpacing).c_str()); 1586 wr_dp_push_repeating_image( 1587 mWrState, aBounds, clip, aIsBackfaceVisible, &mCurrentSpaceAndClipChain, 1588 aStretchSize, aTileSpacing, aFilter, aImage, aPremultipliedAlpha, aColor); 1589 } 1590 1591 void DisplayListBuilder::PushYCbCrPlanarImage( 1592 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1593 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, 1594 wr::ImageKey aImageChannel1, wr::ImageKey aImageChannel2, 1595 wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace, 1596 wr::WrColorRange aColorRange, wr::ImageRendering aRendering, 1597 bool aPreferCompositorSurface, bool aSupportsExternalCompositing) { 1598 wr_dp_push_yuv_planar_image( 1599 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1600 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1, 1601 aImageChannel2, aColorDepth, aColorSpace, aColorRange, aRendering, 1602 aPreferCompositorSurface, aSupportsExternalCompositing); 1603 } 1604 1605 void DisplayListBuilder::PushNV12Image( 1606 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1607 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, 1608 wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth, 1609 wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, 1610 wr::ImageRendering aRendering, bool aPreferCompositorSurface, 1611 bool aSupportsExternalCompositing) { 1612 wr_dp_push_yuv_NV12_image( 1613 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1614 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1, aColorDepth, 1615 aColorSpace, aColorRange, aRendering, aPreferCompositorSurface, 1616 aSupportsExternalCompositing); 1617 } 1618 1619 void DisplayListBuilder::PushP010Image( 1620 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1621 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, 1622 wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth, 1623 wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, 1624 wr::ImageRendering aRendering, bool aPreferCompositorSurface, 1625 bool aSupportsExternalCompositing) { 1626 wr_dp_push_yuv_P010_image( 1627 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1628 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1, aColorDepth, 1629 aColorSpace, aColorRange, aRendering, aPreferCompositorSurface, 1630 aSupportsExternalCompositing); 1631 } 1632 1633 void DisplayListBuilder::PushNV16Image( 1634 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1635 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, 1636 wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth, 1637 wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, 1638 wr::ImageRendering aRendering, bool aPreferCompositorSurface, 1639 bool aSupportsExternalCompositing) { 1640 wr_dp_push_yuv_NV16_image( 1641 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1642 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1, aColorDepth, 1643 aColorSpace, aColorRange, aRendering, aPreferCompositorSurface, 1644 aSupportsExternalCompositing); 1645 } 1646 1647 void DisplayListBuilder::PushYCbCrInterleavedImage( 1648 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1649 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, 1650 wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace, 1651 wr::WrColorRange aColorRange, wr::ImageRendering aRendering, 1652 bool aPreferCompositorSurface, bool aSupportsExternalCompositing) { 1653 wr_dp_push_yuv_interleaved_image( 1654 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1655 &mCurrentSpaceAndClipChain, aImageChannel0, aColorDepth, aColorSpace, 1656 aColorRange, aRendering, aPreferCompositorSurface, 1657 aSupportsExternalCompositing); 1658 } 1659 1660 void DisplayListBuilder::PushIFrame(const LayoutDeviceRect& aDevPxBounds, 1661 bool aIsBackfaceVisible, 1662 PipelineId aPipeline, 1663 bool aIgnoreMissingPipeline) { 1664 // If the incoming bounds size has decimals (As it could when zoom is 1665 // involved), and is pushed straight through here, the compositor would end up 1666 // calculating the destination rect to paint the rendered iframe into 1667 // with those decimal values, rounding the result, instead of snapping. This 1668 // can cause the rendered iframe rect and its destination rect to be 1669 // mismatched, resulting in interpolation artifacts. 1670 auto snapped = aDevPxBounds; 1671 auto tl = snapped.TopLeft().Round(); 1672 auto br = snapped.BottomRight().Round(); 1673 1674 snapped.SizeTo(LayoutDeviceSize(br.x - tl.x, br.y - tl.y)); 1675 1676 const auto bounds = wr::ToLayoutRect(snapped); 1677 wr_dp_push_iframe(mWrState, bounds, MergeClipLeaf(bounds), aIsBackfaceVisible, 1678 &mCurrentSpaceAndClipChain, aPipeline, 1679 aIgnoreMissingPipeline); 1680 } 1681 1682 void DisplayListBuilder::PushBorder(const wr::LayoutRect& aBounds, 1683 const wr::LayoutRect& aClip, 1684 bool aIsBackfaceVisible, 1685 const wr::LayoutSideOffsets& aWidths, 1686 const Range<const wr::BorderSide>& aSides, 1687 const wr::BorderRadius& aRadius, 1688 wr::AntialiasBorder aAntialias) { 1689 MOZ_ASSERT(aSides.length() == 4); 1690 if (aSides.length() != 4) { 1691 return; 1692 } 1693 wr_dp_push_border(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1694 &mCurrentSpaceAndClipChain, aAntialias, aWidths, aSides[0], 1695 aSides[1], aSides[2], aSides[3], aRadius); 1696 } 1697 1698 void DisplayListBuilder::PushBorderImage(const wr::LayoutRect& aBounds, 1699 const wr::LayoutRect& aClip, 1700 bool aIsBackfaceVisible, 1701 const wr::WrBorderImage& aParams) { 1702 wr_dp_push_border_image(mWrState, aBounds, MergeClipLeaf(aClip), 1703 aIsBackfaceVisible, &mCurrentSpaceAndClipChain, 1704 &aParams); 1705 } 1706 1707 void DisplayListBuilder::PushBorderGradient( 1708 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1709 bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, 1710 const int32_t aWidth, const int32_t aHeight, bool aFill, 1711 const wr::DeviceIntSideOffsets& aSlice, const wr::LayoutPoint& aStartPoint, 1712 const wr::LayoutPoint& aEndPoint, const nsTArray<wr::GradientStop>& aStops, 1713 wr::ExtendMode aExtendMode) { 1714 wr_dp_push_border_gradient( 1715 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1716 &mCurrentSpaceAndClipChain, aWidths, aWidth, aHeight, aFill, aSlice, 1717 aStartPoint, aEndPoint, aStops.Elements(), aStops.Length(), aExtendMode); 1718 } 1719 1720 void DisplayListBuilder::PushBorderRadialGradient( 1721 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1722 bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill, 1723 const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius, 1724 const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode) { 1725 wr_dp_push_border_radial_gradient( 1726 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1727 &mCurrentSpaceAndClipChain, aWidths, aFill, aCenter, aRadius, 1728 aStops.Elements(), aStops.Length(), aExtendMode); 1729 } 1730 1731 void DisplayListBuilder::PushBorderConicGradient( 1732 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, 1733 bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill, 1734 const wr::LayoutPoint& aCenter, const float aAngle, 1735 const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode) { 1736 wr_dp_push_border_conic_gradient( 1737 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1738 &mCurrentSpaceAndClipChain, aWidths, aFill, aCenter, aAngle, 1739 aStops.Elements(), aStops.Length(), aExtendMode); 1740 } 1741 1742 void DisplayListBuilder::PushText(const wr::LayoutRect& aBounds, 1743 const wr::LayoutRect& aClip, 1744 bool aIsBackfaceVisible, 1745 const wr::ColorF& aColor, 1746 wr::FontInstanceKey aFontKey, 1747 Range<const wr::GlyphInstance> aGlyphBuffer, 1748 const wr::GlyphOptions* aGlyphOptions) { 1749 wr_dp_push_text(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, 1750 &mCurrentSpaceAndClipChain, aColor, aFontKey, 1751 &aGlyphBuffer[0], aGlyphBuffer.length(), aGlyphOptions); 1752 } 1753 1754 void DisplayListBuilder::PushLine(const wr::LayoutRect& aClip, 1755 bool aIsBackfaceVisible, 1756 const wr::Line& aLine) { 1757 wr::LayoutRect clip = MergeClipLeaf(aClip); 1758 wr_dp_push_line(mWrState, &clip, aIsBackfaceVisible, 1759 &mCurrentSpaceAndClipChain, &aLine.bounds, 1760 aLine.wavyLineThickness, aLine.orientation, &aLine.color, 1761 aLine.style); 1762 } 1763 1764 void DisplayListBuilder::PushShadow(const wr::LayoutRect& aRect, 1765 const wr::LayoutRect& aClip, 1766 bool aIsBackfaceVisible, 1767 const wr::Shadow& aShadow, 1768 bool aShouldInflate) { 1769 // Local clip_rects are translated inside of shadows, as they are assumed to 1770 // be part of the element drawing itself, and not a parent frame clipping it. 1771 // As such, it is not sound to apply the MergeClipLeaf optimization inside of 1772 // shadows. So we disable the optimization when we encounter a shadow. 1773 // Shadows don't span frames, so we don't have to worry about MergeClipLeaf 1774 // being re-enabled mid-shadow. The optimization is restored in PopAllShadows. 1775 SuspendClipLeafMerging(); 1776 wr_dp_push_shadow(mWrState, aRect, aClip, aIsBackfaceVisible, 1777 &mCurrentSpaceAndClipChain, aShadow, aShouldInflate); 1778 } 1779 1780 void DisplayListBuilder::PopAllShadows() { 1781 wr_dp_pop_all_shadows(mWrState); 1782 ResumeClipLeafMerging(); 1783 } 1784 1785 void DisplayListBuilder::SuspendClipLeafMerging() { 1786 if (mClipChainLeaf) { 1787 // No one should reinitialize mClipChainLeaf while we're suspended 1788 MOZ_ASSERT(!mSuspendedClipChainLeaf); 1789 1790 mSuspendedClipChainLeaf = mClipChainLeaf; 1791 mSuspendedSpaceAndClipChain = Some(mCurrentSpaceAndClipChain); 1792 1793 auto clipId = DefineRectClip(Nothing(), *mClipChainLeaf); 1794 auto clipChainId = 1795 DefineClipChain({&clipId, 1}, CurrentClipChainIdIfNotRoot()); 1796 1797 mCurrentSpaceAndClipChain.clip_chain = clipChainId.id; 1798 mClipChainLeaf = Nothing(); 1799 } 1800 } 1801 1802 void DisplayListBuilder::ResumeClipLeafMerging() { 1803 if (mSuspendedClipChainLeaf) { 1804 mCurrentSpaceAndClipChain = *mSuspendedSpaceAndClipChain; 1805 mClipChainLeaf = mSuspendedClipChainLeaf; 1806 1807 mSuspendedClipChainLeaf = Nothing(); 1808 mSuspendedSpaceAndClipChain = Nothing(); 1809 } 1810 } 1811 1812 void DisplayListBuilder::PushBoxShadow( 1813 const wr::LayoutRect& aRect, const wr::LayoutRect& aClip, 1814 bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds, 1815 const wr::LayoutVector2D& aOffset, const wr::ColorF& aColor, 1816 const float& aBlurRadius, const float& aSpreadRadius, 1817 const wr::BorderRadius& aBorderRadius, 1818 const wr::BoxShadowClipMode& aClipMode) { 1819 wr_dp_push_box_shadow(mWrState, aRect, MergeClipLeaf(aClip), 1820 aIsBackfaceVisible, &mCurrentSpaceAndClipChain, 1821 aBoxBounds, aOffset, aColor, aBlurRadius, aSpreadRadius, 1822 aBorderRadius, aClipMode); 1823 } 1824 1825 void DisplayListBuilder::PushDebug(uint32_t aVal) { 1826 wr_dp_push_debug(mWrState, aVal); 1827 } 1828 1829 void DisplayListBuilder::StartGroup(nsPaintedDisplayItem* aItem) { 1830 if (!mDisplayItemCache || mDisplayItemCache->IsFull()) { 1831 return; 1832 } 1833 1834 MOZ_ASSERT(!mCurrentCacheSlot); 1835 mCurrentCacheSlot = mDisplayItemCache->AssignSlot(aItem); 1836 1837 if (mCurrentCacheSlot) { 1838 wr_dp_start_item_group(mWrState); 1839 } 1840 } 1841 1842 void DisplayListBuilder::CancelGroup(const bool aDiscard) { 1843 if (!mDisplayItemCache || !mCurrentCacheSlot) { 1844 return; 1845 } 1846 1847 wr_dp_cancel_item_group(mWrState, aDiscard); 1848 mCurrentCacheSlot = Nothing(); 1849 } 1850 1851 void DisplayListBuilder::FinishGroup() { 1852 if (!mDisplayItemCache || !mCurrentCacheSlot) { 1853 return; 1854 } 1855 1856 MOZ_ASSERT(mCurrentCacheSlot); 1857 1858 if (wr_dp_finish_item_group(mWrState, mCurrentCacheSlot.ref())) { 1859 mDisplayItemCache->MarkSlotOccupied(mCurrentCacheSlot.ref(), 1860 CurrentSpaceAndClipChain()); 1861 mDisplayItemCache->Stats().AddCached(); 1862 } 1863 1864 mCurrentCacheSlot = Nothing(); 1865 } 1866 1867 bool DisplayListBuilder::ReuseItem(nsPaintedDisplayItem* aItem) { 1868 if (!mDisplayItemCache) { 1869 return false; 1870 } 1871 1872 mDisplayItemCache->Stats().AddTotal(); 1873 1874 if (mDisplayItemCache->IsEmpty()) { 1875 return false; 1876 } 1877 1878 Maybe<uint16_t> slot = 1879 mDisplayItemCache->CanReuseItem(aItem, CurrentSpaceAndClipChain()); 1880 1881 if (slot) { 1882 mDisplayItemCache->Stats().AddReused(); 1883 wr_dp_push_reuse_items(mWrState, slot.ref()); 1884 return true; 1885 } 1886 1887 return false; 1888 } 1889 1890 Maybe<layers::ScrollableLayerGuid::ViewID> 1891 DisplayListBuilder::GetContainingFixedPosScrollTarget( 1892 const ActiveScrolledRoot* aAsr) { 1893 return mActiveFixedPosTracker 1894 ? mActiveFixedPosTracker->GetScrollTargetForASR(aAsr) 1895 : Nothing(); 1896 } 1897 1898 Maybe<SideBits> DisplayListBuilder::GetContainingFixedPosSideBits( 1899 const ActiveScrolledRoot* aAsr) { 1900 return mActiveFixedPosTracker 1901 ? mActiveFixedPosTracker->GetSideBitsForASR(aAsr) 1902 : Nothing(); 1903 } 1904 1905 DisplayListBuilder::FixedPosScrollTargetTracker::FixedPosScrollTargetTracker( 1906 DisplayListBuilder& aBuilder, const ActiveScrolledRoot* aAsr, 1907 layers::ScrollableLayerGuid::ViewID aScrollId, SideBits aSideBits) 1908 : mParentTracker(aBuilder.mActiveFixedPosTracker), 1909 mBuilder(aBuilder), 1910 mAsr(aAsr), 1911 mScrollId(aScrollId), 1912 mSideBits(aSideBits) { 1913 aBuilder.mActiveFixedPosTracker = this; 1914 } 1915 1916 DisplayListBuilder::FixedPosScrollTargetTracker:: 1917 ~FixedPosScrollTargetTracker() { 1918 mBuilder.mActiveFixedPosTracker = mParentTracker; 1919 } 1920 1921 Maybe<layers::ScrollableLayerGuid::ViewID> 1922 DisplayListBuilder::FixedPosScrollTargetTracker::GetScrollTargetForASR( 1923 const ActiveScrolledRoot* aAsr) { 1924 return aAsr == mAsr ? Some(mScrollId) : Nothing(); 1925 } 1926 1927 Maybe<SideBits> 1928 DisplayListBuilder::FixedPosScrollTargetTracker::GetSideBitsForASR( 1929 const ActiveScrolledRoot* aAsr) { 1930 return aAsr == mAsr ? Some(mSideBits) : Nothing(); 1931 } 1932 1933 gfxContext* DisplayListBuilder::GetTextContext( 1934 wr::IpcResourceUpdateQueue& aResources, 1935 const layers::StackingContextHelper& aSc, 1936 layers::RenderRootStateManager* aManager, nsDisplayItem* aItem, 1937 nsRect& aBounds, const gfx::Point& aDeviceOffset) { 1938 if (!mCachedTextDT) { 1939 mCachedTextDT = new layout::TextDrawTarget(*this, aResources, aSc, aManager, 1940 aItem, aBounds); 1941 if (mCachedTextDT->IsValid()) { 1942 mCachedContext = MakeUnique<gfxContext>(mCachedTextDT, aDeviceOffset); 1943 } 1944 } else { 1945 mCachedTextDT->Reinitialize(aResources, aSc, aManager, aItem, aBounds); 1946 mCachedContext->SetDeviceOffset(aDeviceOffset); 1947 mCachedContext->SetMatrix(gfx::Matrix()); 1948 } 1949 1950 return mCachedContext.get(); 1951 } 1952 1953 void DisplayListBuilder::PushInheritedClipChain( 1954 nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aClipChain) { 1955 if (!aClipChain || mInheritedClipChain == aClipChain) { 1956 return; 1957 } 1958 if (!mInheritedClipChain) { 1959 mInheritedClipChain = aClipChain; 1960 return; 1961 } 1962 1963 mInheritedClipChain = 1964 aBuilder->CreateClipChainIntersection(mInheritedClipChain, aClipChain); 1965 } 1966 1967 } // namespace wr 1968 } // namespace mozilla 1969 1970 extern "C" { 1971 1972 void wr_transaction_notification_notified(uintptr_t aHandler, 1973 mozilla::wr::Checkpoint aWhen) { 1974 auto handler = reinterpret_cast<mozilla::wr::NotificationHandler*>(aHandler); 1975 handler->Notify(aWhen); 1976 // TODO: it would be better to get a callback when the object is destroyed on 1977 // the rust side and delete then. 1978 delete handler; 1979 } 1980 1981 void wr_register_thread_local_arena() { 1982 #ifdef MOZ_MEMORY 1983 jemalloc_thread_local_arena(true); 1984 #endif 1985 } 1986 1987 } // extern C