1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WebRenderAPI.h"
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/StaticPrefs_gfx.h"
15 #include "mozilla/StaticPrefs_webgl.h"
16 #include "mozilla/ToString.h"
17 #include "mozilla/webrender/RenderCompositor.h"
18 #include "mozilla/widget/CompositorWidget.h"
19 #include "mozilla/layers/SynchronousTask.h"
20 #include "nsThreadUtils.h"
21 #include "TextDrawTarget.h"
22 #include "malloc_decls.h"
23 #include "GLContext.h"
25 static mozilla::LazyLogModule
sWrDLLog("wr.dl");
26 #define WRDL_LOG(...) \
27 MOZ_LOG(sWrDLLog, LogLevel::Debug, ("WRDL(%p): " __VA_ARGS__))
30 using namespace layers
;
34 MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf
)
35 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(WebRenderMallocEnclosingSizeOf
)
37 class NewRenderer
: public RendererEvent
{
39 NewRenderer(wr::DocumentHandle
** aDocHandle
,
40 layers::CompositorBridgeParent
* aBridge
,
41 WebRenderBackend
* aBackend
, WebRenderCompositor
* aCompositor
,
42 int32_t* aMaxTextureSize
, bool* aUseANGLE
, bool* aUseDComp
,
43 bool* aUseTripleBuffering
, bool* aSupportsExternalBufferTextures
,
44 RefPtr
<widget::CompositorWidget
>&& aWidget
,
45 layers::SynchronousTask
* aTask
, LayoutDeviceIntSize aSize
,
46 layers::WindowKind aWindowKind
, layers::SyncHandle
* aHandle
,
48 : mDocHandle(aDocHandle
),
50 mCompositor(aCompositor
),
51 mMaxTextureSize(aMaxTextureSize
),
54 mUseTripleBuffering(aUseTripleBuffering
),
55 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures
),
57 mCompositorWidget(std::move(aWidget
)),
60 mWindowKind(aWindowKind
),
63 MOZ_COUNT_CTOR(NewRenderer
);
66 MOZ_COUNTED_DTOR(NewRenderer
)
68 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
69 layers::AutoCompleteTask
complete(mTask
);
71 UniquePtr
<RenderCompositor
> compositor
=
72 RenderCompositor::Create(std::move(mCompositorWidget
), *mError
);
74 if (!mError
->IsEmpty()) {
75 gfxCriticalNote
<< mError
->BeginReading();
80 compositor
->MakeCurrent();
82 *mBackend
= compositor
->BackendType();
83 *mCompositor
= compositor
->CompositorType();
84 *mUseANGLE
= compositor
->UseANGLE();
85 *mUseDComp
= compositor
->UseDComp();
86 *mUseTripleBuffering
= compositor
->UseTripleBuffering();
87 *mSupportsExternalBufferTextures
=
88 compositor
->SupportsExternalBufferTextures();
90 // Only allow the panic on GL error functionality in nightly builds,
91 // since it (deliberately) crashes the GPU process if any GL call
92 // returns an error code.
93 bool panic_on_gl_error
= false;
96 StaticPrefs::gfx_webrender_panic_on_gl_error_AtStartup();
99 bool isMainWindow
= true; // TODO!
100 bool supportLowPriorityTransactions
= isMainWindow
;
101 bool supportLowPriorityThreadpool
=
102 supportLowPriorityTransactions
&&
103 StaticPrefs::gfx_webrender_enable_low_priority_pool();
104 wr::Renderer
* wrRenderer
= nullptr;
105 char* errorMessage
= nullptr;
106 int picTileWidth
= StaticPrefs::gfx_webrender_picture_tile_width();
107 int picTileHeight
= StaticPrefs::gfx_webrender_picture_tile_height();
108 auto* swgl
= compositor
->swgl();
109 auto* gl
= (compositor
->gl() && !swgl
) ? compositor
->gl() : nullptr;
110 auto* progCache
= (aRenderThread
.GetProgramCache() && !swgl
)
111 ? aRenderThread
.GetProgramCache()->Raw()
113 auto* shaders
= (aRenderThread
.GetShaders() && !swgl
)
114 ? aRenderThread
.GetShaders()->RawShaders()
117 // Check That if we are not using SWGL, we have at least a GL or GLES 3.0
121 gl
->IsAtLeast(gl::ContextProfile::OpenGLCore
, 300) ||
122 gl
->IsAtLeast(gl::ContextProfile::OpenGLCompatibility
, 300) ||
123 gl
->IsAtLeast(gl::ContextProfile::OpenGLES
, 300);
126 gfxCriticalNote
<< "GL context version (" << gl
->Version()
127 << ") insufficent for hardware WebRender";
129 mError
->AssignASCII("GL context version insufficient");
135 aWindowId
, mSize
.width
, mSize
.height
,
136 mWindowKind
== WindowKind::MAIN
, supportLowPriorityTransactions
,
137 supportLowPriorityThreadpool
, gfx::gfxVars::UseGLSwizzle(),
138 gfx::gfxVars::UseWebRenderScissoredCacheClears(), swgl
, gl
,
139 compositor
->SurfaceOriginIsTopLeft(), progCache
, shaders
,
140 aRenderThread
.ThreadPool().Raw(),
141 aRenderThread
.ThreadPoolLP().Raw(), &WebRenderMallocSizeOf
,
142 &WebRenderMallocEnclosingSizeOf
, 0, compositor
.get(),
143 compositor
->ShouldUseNativeCompositor(),
144 compositor
->UsePartialPresent(),
145 compositor
->GetMaxPartialPresentRects(),
146 compositor
->ShouldDrawPreviousPartialPresentRegions(), mDocHandle
,
147 &wrRenderer
, mMaxTextureSize
, &errorMessage
,
148 StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(),
149 panic_on_gl_error
, picTileWidth
, picTileHeight
,
150 gfx::gfxVars::WebRenderRequiresHardwareDriver(),
151 StaticPrefs::gfx_webrender_low_quality_pinch_zoom_AtStartup(),
152 StaticPrefs::gfx_webrender_max_shared_surface_size_AtStartup(),
153 StaticPrefs::gfx_webrender_enable_subpixel_aa_AtStartup())) {
154 // wr_window_new puts a message into gfxCriticalNote if it returns false
155 MOZ_ASSERT(errorMessage
);
156 mError
->AssignASCII(errorMessage
);
157 wr_api_free_error_msg(errorMessage
);
160 MOZ_ASSERT(wrRenderer
);
162 RefPtr
<RenderThread
> thread
= &aRenderThread
;
164 MakeUnique
<RendererOGL
>(std::move(thread
), std::move(compositor
),
165 aWindowId
, wrRenderer
, mBridge
);
166 if (wrRenderer
&& renderer
) {
167 wr::WrExternalImageHandler handler
= renderer
->GetExternalImageHandler();
168 wr_renderer_set_external_image_handler(wrRenderer
, &handler
);
172 layers::SyncObjectHost
* syncObj
= renderer
->GetSyncObject();
174 *mSyncHandle
= syncObj
->GetSyncHandle();
178 aRenderThread
.AddRenderer(aWindowId
, std::move(renderer
));
182 wr::DocumentHandle
** mDocHandle
;
183 WebRenderBackend
* mBackend
;
184 WebRenderCompositor
* mCompositor
;
185 int32_t* mMaxTextureSize
;
188 bool* mUseTripleBuffering
;
189 bool* mSupportsExternalBufferTextures
;
190 layers::CompositorBridgeParent
* mBridge
;
191 RefPtr
<widget::CompositorWidget
> mCompositorWidget
;
192 layers::SynchronousTask
* mTask
;
193 LayoutDeviceIntSize mSize
;
194 layers::WindowKind mWindowKind
;
195 layers::SyncHandle
* mSyncHandle
;
199 class RemoveRenderer
: public RendererEvent
{
201 explicit RemoveRenderer(layers::SynchronousTask
* aTask
) : mTask(aTask
) {
202 MOZ_COUNT_CTOR(RemoveRenderer
);
205 MOZ_COUNTED_DTOR_OVERRIDE(RemoveRenderer
)
207 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
208 aRenderThread
.RemoveRenderer(aWindowId
);
209 layers::AutoCompleteTask
complete(mTask
);
213 layers::SynchronousTask
* mTask
;
216 TransactionBuilder::TransactionBuilder(WebRenderAPI
* aApi
,
217 bool aUseSceneBuilderThread
)
218 : mUseSceneBuilderThread(aUseSceneBuilderThread
),
219 mApiBackend(aApi
->GetBackendType()),
221 mTxn
= wr_transaction_new(mUseSceneBuilderThread
);
224 TransactionBuilder::TransactionBuilder(WebRenderAPI
* aApi
, Transaction
* aTxn
,
225 bool aUseSceneBuilderThread
,
228 mUseSceneBuilderThread(aUseSceneBuilderThread
),
229 mApiBackend(aApi
->GetBackendType()),
230 mOwnsData(aOwnsData
) {}
232 TransactionBuilder::~TransactionBuilder() {
234 wr_transaction_delete(mTxn
);
238 void TransactionBuilder::SetLowPriority(bool aIsLowPriority
) {
239 wr_transaction_set_low_priority(mTxn
, aIsLowPriority
);
242 void TransactionBuilder::UpdateEpoch(PipelineId aPipelineId
, Epoch aEpoch
) {
243 wr_transaction_update_epoch(mTxn
, aPipelineId
, aEpoch
);
246 void TransactionBuilder::SetRootPipeline(PipelineId aPipelineId
) {
247 wr_transaction_set_root_pipeline(mTxn
, aPipelineId
);
250 void TransactionBuilder::RemovePipeline(PipelineId aPipelineId
) {
251 wr_transaction_remove_pipeline(mTxn
, aPipelineId
);
254 void TransactionBuilder::SetDisplayList(
255 Epoch aEpoch
, wr::WrPipelineId pipeline_id
,
256 wr::BuiltDisplayListDescriptor dl_descriptor
,
257 wr::Vec
<uint8_t>& dl_items_data
, wr::Vec
<uint8_t>& dl_cache_data
,
258 wr::Vec
<uint8_t>& dl_spatial_tree
) {
259 wr_transaction_set_display_list(mTxn
, aEpoch
, pipeline_id
, dl_descriptor
,
260 &dl_items_data
.inner
, &dl_cache_data
.inner
,
261 &dl_spatial_tree
.inner
);
264 void TransactionBuilder::ClearDisplayList(Epoch aEpoch
,
265 wr::WrPipelineId aPipelineId
) {
266 wr_transaction_clear_display_list(mTxn
, aEpoch
, aPipelineId
);
269 void TransactionBuilder::GenerateFrame(const VsyncId
& aVsyncId
,
270 wr::RenderReasons aReasons
) {
271 wr_transaction_generate_frame(mTxn
, aVsyncId
.mId
, aReasons
);
274 void TransactionBuilder::InvalidateRenderedFrame(wr::RenderReasons aReasons
) {
275 wr_transaction_invalidate_rendered_frame(mTxn
, aReasons
);
278 bool TransactionBuilder::IsEmpty() const {
279 return wr_transaction_is_empty(mTxn
);
282 bool TransactionBuilder::IsResourceUpdatesEmpty() const {
283 return wr_transaction_resource_updates_is_empty(mTxn
);
286 bool TransactionBuilder::IsRenderedFrameInvalidated() const {
287 return wr_transaction_is_rendered_frame_invalidated(mTxn
);
290 void TransactionBuilder::SetDocumentView(
291 const LayoutDeviceIntRect
& aDocumentRect
) {
292 wr::DeviceIntRect wrDocRect
;
293 wrDocRect
.min
.x
= aDocumentRect
.x
;
294 wrDocRect
.min
.y
= aDocumentRect
.y
;
295 wrDocRect
.max
.x
= aDocumentRect
.x
+ aDocumentRect
.width
;
296 wrDocRect
.max
.y
= aDocumentRect
.y
+ aDocumentRect
.height
;
297 wr_transaction_set_document_view(mTxn
, &wrDocRect
);
300 TransactionWrapper::TransactionWrapper(Transaction
* aTxn
) : mTxn(aTxn
) {}
302 void TransactionWrapper::AppendDynamicProperties(
303 const nsTArray
<wr::WrOpacityProperty
>& aOpacityArray
,
304 const nsTArray
<wr::WrTransformProperty
>& aTransformArray
,
305 const nsTArray
<wr::WrColorProperty
>& aColorArray
) {
306 wr_transaction_append_dynamic_properties(
307 mTxn
, aOpacityArray
.IsEmpty() ? nullptr : aOpacityArray
.Elements(),
308 aOpacityArray
.Length(),
309 aTransformArray
.IsEmpty() ? nullptr : aTransformArray
.Elements(),
310 aTransformArray
.Length(),
311 aColorArray
.IsEmpty() ? nullptr : aColorArray
.Elements(),
312 aColorArray
.Length());
315 void TransactionWrapper::AppendTransformProperties(
316 const nsTArray
<wr::WrTransformProperty
>& aTransformArray
) {
317 wr_transaction_append_transform_properties(
318 mTxn
, aTransformArray
.IsEmpty() ? nullptr : aTransformArray
.Elements(),
319 aTransformArray
.Length());
322 void TransactionWrapper::UpdateScrollPosition(
323 const wr::ExternalScrollId
& aScrollId
,
324 const nsTArray
<wr::SampledScrollOffset
>& aSampledOffsets
) {
325 wr_transaction_scroll_layer(mTxn
, aScrollId
, &aSampledOffsets
);
328 void TransactionWrapper::UpdateIsTransformAsyncZooming(uint64_t aAnimationId
,
330 wr_transaction_set_is_transform_async_zooming(mTxn
, aAnimationId
, aIsZooming
);
333 void TransactionWrapper::AddMinimapData(const wr::ExternalScrollId
& aScrollId
,
334 const MinimapData
& aMinimapData
) {
335 wr_transaction_add_minimap_data(mTxn
, aScrollId
, aMinimapData
);
339 already_AddRefed
<WebRenderAPI
> WebRenderAPI::Create(
340 layers::CompositorBridgeParent
* aBridge
,
341 RefPtr
<widget::CompositorWidget
>&& aWidget
, const wr::WrWindowId
& aWindowId
,
342 LayoutDeviceIntSize aSize
, layers::WindowKind aWindowKind
,
343 nsACString
& aError
) {
347 sizeof(size_t) == sizeof(uintptr_t),
348 "The FFI bindings assume size_t is the same size as uintptr_t!");
350 wr::DocumentHandle
* docHandle
= nullptr;
351 WebRenderBackend backend
= WebRenderBackend::HARDWARE
;
352 WebRenderCompositor compositor
= WebRenderCompositor::DRAW
;
353 int32_t maxTextureSize
= 0;
354 bool useANGLE
= false;
355 bool useDComp
= false;
356 bool useTripleBuffering
= false;
357 bool supportsExternalBufferTextures
= false;
358 layers::SyncHandle syncHandle
= {};
360 // Dispatch a synchronous task because the DocumentHandle object needs to be
361 // created on the render thread. If need be we could delay waiting on this
362 // task until the next time we need to access the DocumentHandle object.
363 layers::SynchronousTask
task("Create Renderer");
364 auto event
= MakeUnique
<NewRenderer
>(
365 &docHandle
, aBridge
, &backend
, &compositor
, &maxTextureSize
, &useANGLE
,
366 &useDComp
, &useTripleBuffering
, &supportsExternalBufferTextures
,
367 std::move(aWidget
), &task
, aSize
, aWindowKind
, &syncHandle
, &aError
);
368 RenderThread::Get()->PostEvent(aWindowId
, std::move(event
));
376 return RefPtr
<WebRenderAPI
>(
377 new WebRenderAPI(docHandle
, aWindowId
, backend
, compositor
,
378 maxTextureSize
, useANGLE
, useDComp
,
380 supportsExternalBufferTextures
, syncHandle
))
384 already_AddRefed
<WebRenderAPI
> WebRenderAPI::Clone() {
385 wr::DocumentHandle
* docHandle
= nullptr;
386 wr_api_clone(mDocHandle
, &docHandle
);
388 RefPtr
<WebRenderAPI
> renderApi
= new WebRenderAPI(
389 docHandle
, mId
, mBackend
, mCompositor
, mMaxTextureSize
, mUseANGLE
,
390 mUseDComp
, mUseTripleBuffering
, mSupportsExternalBufferTextures
,
391 mSyncHandle
, this, this);
393 return renderApi
.forget();
396 wr::WrIdNamespace
WebRenderAPI::GetNamespace() {
397 return wr_api_get_namespace(mDocHandle
);
400 WebRenderAPI::WebRenderAPI(
401 wr::DocumentHandle
* aHandle
, wr::WindowId aId
, WebRenderBackend aBackend
,
402 WebRenderCompositor aCompositor
, uint32_t aMaxTextureSize
, bool aUseANGLE
,
403 bool aUseDComp
, bool aUseTripleBuffering
,
404 bool aSupportsExternalBufferTextures
, layers::SyncHandle aSyncHandle
,
405 wr::WebRenderAPI
* aRootApi
, wr::WebRenderAPI
* aRootDocumentApi
)
406 : mDocHandle(aHandle
),
409 mCompositor(aCompositor
),
410 mMaxTextureSize(aMaxTextureSize
),
411 mUseANGLE(aUseANGLE
),
412 mUseDComp(aUseDComp
),
413 mUseTripleBuffering(aUseTripleBuffering
),
414 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures
),
415 mCaptureSequence(false),
416 mSyncHandle(aSyncHandle
),
417 mRendererDestroyed(false),
419 mRootDocumentApi(aRootDocumentApi
) {}
421 WebRenderAPI::~WebRenderAPI() {
422 if (!mRootDocumentApi
) {
423 wr_api_delete_document(mDocHandle
);
427 MOZ_RELEASE_ASSERT(mRendererDestroyed
);
428 wr_api_shut_down(mDocHandle
);
431 wr_api_delete(mDocHandle
);
434 void WebRenderAPI::DestroyRenderer() {
435 MOZ_RELEASE_ASSERT(!mRootApi
);
437 RenderThread::Get()->SetDestroyed(GetId());
438 // Call wr_api_stop_render_backend() before RemoveRenderer.
439 wr_api_stop_render_backend(mDocHandle
);
441 layers::SynchronousTask
task("Destroy WebRenderAPI");
442 auto event
= MakeUnique
<RemoveRenderer
>(&task
);
443 RunOnRenderThread(std::move(event
));
446 mRendererDestroyed
= true;
449 wr::WebRenderAPI
* WebRenderAPI::GetRootAPI() {
456 void WebRenderAPI::UpdateDebugFlags(uint32_t aFlags
) {
457 wr_api_set_debug_flags(mDocHandle
, wr::DebugFlags
{aFlags
});
460 void WebRenderAPI::SendTransaction(TransactionBuilder
& aTxn
) {
461 if (mRootApi
&& mRootApi
->mRendererDestroyed
) {
465 if (mPendingRemoteTextureInfoList
&&
466 !mPendingRemoteTextureInfoList
->mList
.empty()) {
467 mPendingWrTransactionEvents
.emplace(
468 WrTransactionEvent::PendingRemoteTextures(
469 std::move(mPendingRemoteTextureInfoList
)));
472 if (mPendingAsyncImagePipelineOps
&&
473 !mPendingAsyncImagePipelineOps
->mList
.empty()) {
474 mPendingWrTransactionEvents
.emplace(
475 WrTransactionEvent::PendingAsyncImagePipelineOps(
476 std::move(mPendingAsyncImagePipelineOps
), this, aTxn
.Raw(),
477 aTxn
.UseSceneBuilderThread()));
480 if (!mPendingWrTransactionEvents
.empty()) {
481 mPendingWrTransactionEvents
.emplace(WrTransactionEvent::Transaction(
482 this, aTxn
.Take(), aTxn
.UseSceneBuilderThread()));
483 HandleWrTransactionEvents(RemoteTextureWaitType::AsyncWait
);
485 wr_api_send_transaction(mDocHandle
, aTxn
.Raw(),
486 aTxn
.UseSceneBuilderThread());
490 layers::RemoteTextureInfoList
* WebRenderAPI::GetPendingRemoteTextureInfoList() {
492 // root api does not support async wait RemoteTexture.
496 if (!mPendingRemoteTextureInfoList
) {
497 mPendingRemoteTextureInfoList
= MakeUnique
<layers::RemoteTextureInfoList
>();
499 return mPendingRemoteTextureInfoList
.get();
502 layers::AsyncImagePipelineOps
* WebRenderAPI::GetPendingAsyncImagePipelineOps(
503 TransactionBuilder
& aTxn
) {
505 // root api does not support async wait RemoteTexture.
509 if (!mPendingAsyncImagePipelineOps
||
510 mPendingAsyncImagePipelineOps
->mTransaction
!= aTxn
.Raw()) {
511 if (mPendingAsyncImagePipelineOps
&&
512 !mPendingAsyncImagePipelineOps
->mList
.empty()) {
513 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
514 gfxCriticalNoteOnce
<< "Invalid AsyncImagePipelineOps";
516 mPendingAsyncImagePipelineOps
=
517 MakeUnique
<layers::AsyncImagePipelineOps
>(aTxn
.Raw());
519 MOZ_RELEASE_ASSERT(mPendingAsyncImagePipelineOps
->mTransaction
==
523 return mPendingAsyncImagePipelineOps
.get();
526 bool WebRenderAPI::CheckIsRemoteTextureReady(
527 layers::RemoteTextureInfoList
* aList
, const TimeStamp
& aTimeStamp
) {
528 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
531 RefPtr
<WebRenderAPI
> self
= this;
532 auto callback
= [self
](const layers::RemoteTextureInfo
&) {
533 RefPtr
<nsIRunnable
> runnable
= NewRunnableMethod
<RemoteTextureWaitType
>(
534 "WebRenderAPI::HandleWrTransactionEvents", self
,
535 &WebRenderAPI::HandleWrTransactionEvents
,
536 RemoteTextureWaitType::AsyncWait
);
537 layers::CompositorThread()->Dispatch(runnable
.forget());
541 while (!aList
->mList
.empty() && isReady
) {
542 auto& front
= aList
->mList
.front();
543 isReady
&= layers::RemoteTextureMap::Get()->CheckRemoteTextureReady(
554 const auto maxWaitDurationMs
= 10000;
555 const auto now
= TimeStamp::Now();
556 const auto waitDurationMs
=
557 static_cast<uint32_t>((now
- aTimeStamp
).ToMilliseconds());
559 const auto isTimeout
= waitDurationMs
> maxWaitDurationMs
;
561 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
562 gfxCriticalNote
<< "RemoteTexture ready timeout";
568 void WebRenderAPI::WaitRemoteTextureReady(
569 layers::RemoteTextureInfoList
* aList
) {
570 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
573 while (!aList
->mList
.empty()) {
574 auto& front
= aList
->mList
.front();
575 layers::RemoteTextureMap::Get()->WaitRemoteTextureReady(front
);
580 void WebRenderAPI::FlushPendingWrTransactionEventsWithoutWait() {
581 HandleWrTransactionEvents(RemoteTextureWaitType::FlushWithoutWait
);
584 void WebRenderAPI::FlushPendingWrTransactionEventsWithWait() {
585 HandleWrTransactionEvents(RemoteTextureWaitType::FlushWithWait
);
588 void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType
) {
589 auto& events
= mPendingWrTransactionEvents
;
591 while (!events
.empty()) {
592 auto& front
= events
.front();
593 switch (front
.mTag
) {
594 case WrTransactionEvent::Tag::Transaction
:
595 wr_api_send_transaction(mDocHandle
, front
.RawTransaction(),
596 front
.UseSceneBuilderThread());
598 case WrTransactionEvent::Tag::PendingRemoteTextures
: {
600 if (aType
== RemoteTextureWaitType::AsyncWait
) {
601 isReady
= CheckIsRemoteTextureReady(front
.RemoteTextureInfoList(),
603 } else if (aType
== RemoteTextureWaitType::FlushWithWait
) {
604 WaitRemoteTextureReady(front
.RemoteTextureInfoList());
606 MOZ_ASSERT(aType
== RemoteTextureWaitType::FlushWithoutWait
);
607 auto* list
= front
.RemoteTextureInfoList();
608 while (!list
->mList
.empty()) {
609 auto& front
= list
->mList
.front();
610 layers::RemoteTextureMap::Get()->SuppressRemoteTextureReadyCheck(
611 front
.mTextureId
, front
.mForPid
);
615 if (!isReady
&& (aType
!= RemoteTextureWaitType::FlushWithoutWait
)) {
620 case WrTransactionEvent::Tag::PendingAsyncImagePipelineOps
: {
621 auto* list
= front
.AsyncImagePipelineOps();
622 TransactionBuilder
& txn
= *front
.GetTransactionBuilder();
624 list
->HandleOps(txn
);
632 std::vector
<WrHitResult
> WebRenderAPI::HitTest(const wr::WorldPoint
& aPoint
) {
633 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits
<12>(),
634 "CompositorHitTestFlags MAX value has to be less than number "
635 "of bits in uint16_t minus 4 for SideBitsPacked");
637 nsTArray
<wr::HitResult
> wrResults
;
638 wr_api_hit_test(mDocHandle
, aPoint
, &wrResults
);
640 std::vector
<WrHitResult
> geckoResults
;
641 for (wr::HitResult wrResult
: wrResults
) {
642 WrHitResult geckoResult
;
643 geckoResult
.mLayersId
= wr::AsLayersId(wrResult
.pipeline_id
);
644 geckoResult
.mScrollId
=
645 static_cast<layers::ScrollableLayerGuid::ViewID
>(wrResult
.scroll_id
);
646 geckoResult
.mHitInfo
.deserialize(wrResult
.hit_info
& 0x0fff);
647 geckoResult
.mSideBits
= static_cast<SideBits
>(wrResult
.hit_info
>> 12);
649 if (wrResult
.animation_id
!= 0) {
650 geckoResult
.mAnimationId
= Some(wrResult
.animation_id
);
652 geckoResult
.mAnimationId
= Nothing();
654 geckoResults
.push_back(geckoResult
);
659 void WebRenderAPI::Readback(const TimeStamp
& aStartTime
, gfx::IntSize size
,
660 const gfx::SurfaceFormat
& aFormat
,
661 const Range
<uint8_t>& buffer
, bool* aNeedsYFlip
) {
662 class Readback
: public RendererEvent
{
664 explicit Readback(layers::SynchronousTask
* aTask
, TimeStamp aStartTime
,
665 gfx::IntSize aSize
, const gfx::SurfaceFormat
& aFormat
,
666 const Range
<uint8_t>& aBuffer
, bool* aNeedsYFlip
)
668 mStartTime(aStartTime
),
672 mNeedsYFlip(aNeedsYFlip
) {
673 MOZ_COUNT_CTOR(Readback
);
676 MOZ_COUNTED_DTOR_OVERRIDE(Readback
)
678 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
679 aRenderThread
.UpdateAndRender(aWindowId
, VsyncId(), mStartTime
,
680 /* aRender */ true, Some(mSize
),
681 wr::SurfaceFormatToImageFormat(mFormat
),
682 Some(mBuffer
), mNeedsYFlip
);
683 layers::AutoCompleteTask
complete(mTask
);
686 layers::SynchronousTask
* mTask
;
687 TimeStamp mStartTime
;
689 gfx::SurfaceFormat mFormat
;
690 const Range
<uint8_t>& mBuffer
;
694 // Disable debug flags during readback. See bug 1436020.
697 layers::SynchronousTask
task("Readback");
698 auto event
= MakeUnique
<Readback
>(&task
, aStartTime
, size
, aFormat
, buffer
,
700 // This event will be passed from wr_backend thread to renderer thread. That
701 // implies that all frame data have been processed when the renderer runs this
702 // read-back event. Then, we could make sure this read-back event gets the
704 RunOnRenderThread(std::move(event
));
708 UpdateDebugFlags(gfx::gfxVars::WebRenderDebugFlags());
711 void WebRenderAPI::ClearAllCaches() { wr_api_clear_all_caches(mDocHandle
); }
713 void WebRenderAPI::EnableNativeCompositor(bool aEnable
) {
714 wr_api_enable_native_compositor(mDocHandle
, aEnable
);
717 void WebRenderAPI::SetBatchingLookback(uint32_t aCount
) {
718 wr_api_set_batching_lookback(mDocHandle
, aCount
);
721 void WebRenderAPI::SetBool(wr::BoolParameter aKey
, bool aValue
) {
722 wr_api_set_bool(mDocHandle
, aKey
, aValue
);
725 void WebRenderAPI::SetInt(wr::IntParameter aKey
, int32_t aValue
) {
726 wr_api_set_int(mDocHandle
, aKey
, aValue
);
729 void WebRenderAPI::SetClearColor(const gfx::DeviceColor
& aColor
) {
730 RenderThread::Get()->SetClearColor(mId
, ToColorF(aColor
));
733 void WebRenderAPI::SetProfilerUI(const nsACString
& aUIString
) {
734 RenderThread::Get()->SetProfilerUI(mId
, aUIString
);
737 void WebRenderAPI::Pause() {
738 class PauseEvent
: public RendererEvent
{
740 explicit PauseEvent(layers::SynchronousTask
* aTask
) : mTask(aTask
) {
741 MOZ_COUNT_CTOR(PauseEvent
);
744 MOZ_COUNTED_DTOR_OVERRIDE(PauseEvent
)
746 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
747 aRenderThread
.Pause(aWindowId
);
748 layers::AutoCompleteTask
complete(mTask
);
751 layers::SynchronousTask
* mTask
;
754 layers::SynchronousTask
task("Pause");
755 auto event
= MakeUnique
<PauseEvent
>(&task
);
756 // This event will be passed from wr_backend thread to renderer thread. That
757 // implies that all frame data have been processed when the renderer runs this
759 RunOnRenderThread(std::move(event
));
764 bool WebRenderAPI::Resume() {
765 class ResumeEvent
: public RendererEvent
{
767 explicit ResumeEvent(layers::SynchronousTask
* aTask
, bool* aResult
)
768 : mTask(aTask
), mResult(aResult
) {
769 MOZ_COUNT_CTOR(ResumeEvent
);
772 MOZ_COUNTED_DTOR_OVERRIDE(ResumeEvent
)
774 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
775 *mResult
= aRenderThread
.Resume(aWindowId
);
776 layers::AutoCompleteTask
complete(mTask
);
779 layers::SynchronousTask
* mTask
;
784 layers::SynchronousTask
task("Resume");
785 auto event
= MakeUnique
<ResumeEvent
>(&task
, &result
);
786 // This event will be passed from wr_backend thread to renderer thread. That
787 // implies that all frame data have been processed when the renderer runs this
789 RunOnRenderThread(std::move(event
));
795 void WebRenderAPI::NotifyMemoryPressure() {
796 wr_api_notify_memory_pressure(mDocHandle
);
799 void WebRenderAPI::AccumulateMemoryReport(MemoryReport
* aReport
) {
800 wr_api_accumulate_memory_report(mDocHandle
, aReport
, &WebRenderMallocSizeOf
,
801 &WebRenderMallocEnclosingSizeOf
);
804 void WebRenderAPI::WakeSceneBuilder() { wr_api_wake_scene_builder(mDocHandle
); }
806 void WebRenderAPI::FlushSceneBuilder() {
807 wr_api_flush_scene_builder(mDocHandle
);
810 void WebRenderAPI::WaitFlushed() {
811 class WaitFlushedEvent
: public RendererEvent
{
813 explicit WaitFlushedEvent(layers::SynchronousTask
* aTask
) : mTask(aTask
) {
814 MOZ_COUNT_CTOR(WaitFlushedEvent
);
817 MOZ_COUNTED_DTOR_OVERRIDE(WaitFlushedEvent
)
819 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
820 layers::AutoCompleteTask
complete(mTask
);
823 layers::SynchronousTask
* mTask
;
826 layers::SynchronousTask
task("WaitFlushed");
827 auto event
= MakeUnique
<WaitFlushedEvent
>(&task
);
828 // This event will be passed from wr_backend thread to renderer thread. That
829 // implies that all frame data have been processed when the renderer runs this
831 RunOnRenderThread(std::move(event
));
836 void WebRenderAPI::Capture() {
838 // SCENE | FRAME | TILE_CACHE
839 uint8_t bits
= 15; // TODO: get from JavaScript
840 const char* path
= "wr-capture"; // TODO: get from JavaScript
841 wr_api_capture(mDocHandle
, path
, bits
);
844 void WebRenderAPI::StartCaptureSequence(const nsACString
& aPath
,
846 if (mCaptureSequence
) {
847 wr_api_stop_capture_sequence(mDocHandle
);
850 wr_api_start_capture_sequence(mDocHandle
, PromiseFlatCString(aPath
).get(),
853 mCaptureSequence
= true;
856 void WebRenderAPI::StopCaptureSequence() {
857 if (mCaptureSequence
) {
858 wr_api_stop_capture_sequence(mDocHandle
);
861 mCaptureSequence
= false;
864 void WebRenderAPI::BeginRecording(const TimeStamp
& aRecordingStart
,
865 wr::PipelineId aRootPipelineId
) {
866 class BeginRecordingEvent final
: public RendererEvent
{
868 explicit BeginRecordingEvent(const TimeStamp
& aRecordingStart
,
869 wr::PipelineId aRootPipelineId
)
870 : mRecordingStart(aRecordingStart
), mRootPipelineId(aRootPipelineId
) {
871 MOZ_COUNT_CTOR(BeginRecordingEvent
);
874 ~BeginRecordingEvent() { MOZ_COUNT_DTOR(BeginRecordingEvent
); }
876 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
877 aRenderThread
.BeginRecordingForWindow(aWindowId
, mRecordingStart
,
882 TimeStamp mRecordingStart
;
883 wr::PipelineId mRootPipelineId
;
887 MakeUnique
<BeginRecordingEvent
>(aRecordingStart
, aRootPipelineId
);
888 RunOnRenderThread(std::move(event
));
891 RefPtr
<WebRenderAPI::EndRecordingPromise
> WebRenderAPI::EndRecording() {
892 class EndRecordingEvent final
: public RendererEvent
{
894 explicit EndRecordingEvent() { MOZ_COUNT_CTOR(EndRecordingEvent
); }
896 MOZ_COUNTED_DTOR(EndRecordingEvent
);
898 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
899 Maybe
<layers::FrameRecording
> recording
=
900 aRenderThread
.EndRecordingForWindow(aWindowId
);
903 mPromise
.Resolve(recording
.extract(), __func__
);
905 mPromise
.Reject(NS_ERROR_UNEXPECTED
, __func__
);
909 RefPtr
<WebRenderAPI::EndRecordingPromise
> GetPromise() {
910 return mPromise
.Ensure(__func__
);
914 MozPromiseHolder
<WebRenderAPI::EndRecordingPromise
> mPromise
;
917 auto event
= MakeUnique
<EndRecordingEvent
>();
918 auto promise
= event
->GetPromise();
920 RunOnRenderThread(std::move(event
));
924 void TransactionBuilder::Clear() { wr_resource_updates_clear(mTxn
); }
926 Transaction
* TransactionBuilder::Take() {
928 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
931 Transaction
* txn
= mTxn
;
932 mTxn
= wr_transaction_new(mUseSceneBuilderThread
);
936 void TransactionBuilder::Notify(wr::Checkpoint aWhen
,
937 UniquePtr
<NotificationHandler
> aEvent
) {
938 wr_transaction_notify(mTxn
, aWhen
,
939 reinterpret_cast<uintptr_t>(aEvent
.release()));
942 void TransactionBuilder::AddImage(ImageKey key
,
943 const ImageDescriptor
& aDescriptor
,
944 wr::Vec
<uint8_t>& aBytes
) {
945 wr_resource_updates_add_image(mTxn
, key
, &aDescriptor
, &aBytes
.inner
);
948 void TransactionBuilder::AddBlobImage(BlobImageKey key
,
949 const ImageDescriptor
& aDescriptor
,
951 wr::Vec
<uint8_t>& aBytes
,
952 const wr::DeviceIntRect
& aVisibleRect
) {
953 wr_resource_updates_add_blob_image(mTxn
, key
, &aDescriptor
, aTileSize
,
954 &aBytes
.inner
, aVisibleRect
);
957 void TransactionBuilder::AddExternalImage(ImageKey key
,
958 const ImageDescriptor
& aDescriptor
,
959 ExternalImageId aExtID
,
960 wr::ExternalImageType aImageType
,
961 uint8_t aChannelIndex
) {
962 wr_resource_updates_add_external_image(mTxn
, key
, &aDescriptor
, aExtID
,
963 &aImageType
, aChannelIndex
);
966 void TransactionBuilder::AddExternalImageBuffer(
967 ImageKey aKey
, const ImageDescriptor
& aDescriptor
,
968 ExternalImageId aHandle
) {
969 auto channelIndex
= 0;
970 AddExternalImage(aKey
, aDescriptor
, aHandle
, wr::ExternalImageType::Buffer(),
974 void TransactionBuilder::UpdateImageBuffer(ImageKey aKey
,
975 const ImageDescriptor
& aDescriptor
,
976 wr::Vec
<uint8_t>& aBytes
) {
977 wr_resource_updates_update_image(mTxn
, aKey
, &aDescriptor
, &aBytes
.inner
);
980 void TransactionBuilder::UpdateBlobImage(BlobImageKey aKey
,
981 const ImageDescriptor
& aDescriptor
,
982 wr::Vec
<uint8_t>& aBytes
,
983 const wr::DeviceIntRect
& aVisibleRect
,
984 const wr::LayoutIntRect
& aDirtyRect
) {
985 wr_resource_updates_update_blob_image(mTxn
, aKey
, &aDescriptor
, &aBytes
.inner
,
986 aVisibleRect
, aDirtyRect
);
989 void TransactionBuilder::UpdateExternalImage(ImageKey aKey
,
990 const ImageDescriptor
& aDescriptor
,
991 ExternalImageId aExtID
,
992 wr::ExternalImageType aImageType
,
993 uint8_t aChannelIndex
) {
994 wr_resource_updates_update_external_image(mTxn
, aKey
, &aDescriptor
, aExtID
,
995 &aImageType
, aChannelIndex
);
998 void TransactionBuilder::UpdateExternalImageWithDirtyRect(
999 ImageKey aKey
, const ImageDescriptor
& aDescriptor
, ExternalImageId aExtID
,
1000 wr::ExternalImageType aImageType
, const wr::DeviceIntRect
& aDirtyRect
,
1001 uint8_t aChannelIndex
) {
1002 wr_resource_updates_update_external_image_with_dirty_rect(
1003 mTxn
, aKey
, &aDescriptor
, aExtID
, &aImageType
, aChannelIndex
, aDirtyRect
);
1006 void TransactionBuilder::SetBlobImageVisibleArea(
1007 BlobImageKey aKey
, const wr::DeviceIntRect
& aArea
) {
1008 wr_resource_updates_set_blob_image_visible_area(mTxn
, aKey
, &aArea
);
1011 void TransactionBuilder::DeleteImage(ImageKey aKey
) {
1012 wr_resource_updates_delete_image(mTxn
, aKey
);
1015 void TransactionBuilder::DeleteBlobImage(BlobImageKey aKey
) {
1016 wr_resource_updates_delete_blob_image(mTxn
, aKey
);
1019 void TransactionBuilder::AddRawFont(wr::FontKey aKey
, wr::Vec
<uint8_t>& aBytes
,
1021 wr_resource_updates_add_raw_font(mTxn
, aKey
, &aBytes
.inner
, aIndex
);
1024 void TransactionBuilder::AddFontDescriptor(wr::FontKey aKey
,
1025 wr::Vec
<uint8_t>& aBytes
,
1027 wr_resource_updates_add_font_descriptor(mTxn
, aKey
, &aBytes
.inner
, aIndex
);
1030 void TransactionBuilder::DeleteFont(wr::FontKey aKey
) {
1031 wr_resource_updates_delete_font(mTxn
, aKey
);
1034 void TransactionBuilder::AddFontInstance(
1035 wr::FontInstanceKey aKey
, wr::FontKey aFontKey
, float aGlyphSize
,
1036 const wr::FontInstanceOptions
* aOptions
,
1037 const wr::FontInstancePlatformOptions
* aPlatformOptions
,
1038 wr::Vec
<uint8_t>& aVariations
) {
1039 wr_resource_updates_add_font_instance(mTxn
, aKey
, aFontKey
, aGlyphSize
,
1040 aOptions
, aPlatformOptions
,
1041 &aVariations
.inner
);
1044 void TransactionBuilder::DeleteFontInstance(wr::FontInstanceKey aKey
) {
1045 wr_resource_updates_delete_font_instance(mTxn
, aKey
);
1048 void TransactionBuilder::UpdateQualitySettings(
1049 bool aForceSubpixelAAWherePossible
) {
1050 wr_transaction_set_quality_settings(mTxn
, aForceSubpixelAAWherePossible
);
1053 class FrameStartTime
: public RendererEvent
{
1055 explicit FrameStartTime(const TimeStamp
& aTime
) : mTime(aTime
) {
1056 MOZ_COUNT_CTOR(FrameStartTime
);
1059 MOZ_COUNTED_DTOR_OVERRIDE(FrameStartTime
)
1061 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
1062 auto renderer
= aRenderThread
.GetRenderer(aWindowId
);
1064 renderer
->SetFrameStartTime(mTime
);
1072 void WebRenderAPI::SetFrameStartTime(const TimeStamp
& aTime
) {
1073 auto event
= MakeUnique
<FrameStartTime
>(aTime
);
1074 RunOnRenderThread(std::move(event
));
1077 void WebRenderAPI::RunOnRenderThread(UniquePtr
<RendererEvent
> aEvent
) {
1078 auto event
= reinterpret_cast<uintptr_t>(aEvent
.release());
1079 wr_api_send_external_event(mDocHandle
, event
);
1082 DisplayListBuilder::DisplayListBuilder(PipelineId aId
,
1083 WebRenderBackend aBackend
)
1084 : mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
1085 mActiveFixedPosTracker(nullptr),
1088 mDisplayItemCache(nullptr) {
1089 MOZ_COUNT_CTOR(DisplayListBuilder
);
1090 mWrState
= wr_state_new(aId
);
1092 if (mDisplayItemCache
&& mDisplayItemCache
->IsEnabled()) {
1093 mDisplayItemCache
->SetPipelineId(aId
);
1097 DisplayListBuilder::~DisplayListBuilder() {
1098 MOZ_COUNT_DTOR(DisplayListBuilder
);
1099 wr_state_delete(mWrState
);
1102 void DisplayListBuilder::Save() { wr_dp_save(mWrState
); }
1103 void DisplayListBuilder::Restore() { wr_dp_restore(mWrState
); }
1104 void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState
); }
1106 usize
DisplayListBuilder::Dump(usize aIndent
, const Maybe
<usize
>& aStart
,
1107 const Maybe
<usize
>& aEnd
) {
1108 return wr_dump_display_list(mWrState
, aIndent
, aStart
.ptrOr(nullptr),
1109 aEnd
.ptrOr(nullptr));
1112 void DisplayListBuilder::DumpSerializedDisplayList() {
1113 wr_dump_serialized_display_list(mWrState
);
1116 void DisplayListBuilder::Begin(layers::DisplayItemCache
* aCache
) {
1117 wr_api_begin_builder(mWrState
);
1120 mCurrentSpaceAndClipChain
= wr::RootScrollNodeWithChain();
1121 mClipChainLeaf
= Nothing();
1122 mSuspendedSpaceAndClipChain
= Nothing();
1123 mSuspendedClipChainLeaf
= Nothing();
1124 mCachedTextDT
= nullptr;
1125 mCachedContext
= nullptr;
1126 mActiveFixedPosTracker
= nullptr;
1127 mDisplayItemCache
= aCache
;
1128 mCurrentCacheSlot
= Nothing();
1131 void DisplayListBuilder::End(BuiltDisplayList
& aOutDisplayList
) {
1133 mWrState
, &aOutDisplayList
.dl_desc
, &aOutDisplayList
.dl_items
.inner
,
1134 &aOutDisplayList
.dl_cache
.inner
, &aOutDisplayList
.dl_spatial_tree
.inner
);
1136 mDisplayItemCache
= nullptr;
1139 void DisplayListBuilder::End(layers::DisplayListData
& aOutTransaction
) {
1140 if (mDisplayItemCache
&& mDisplayItemCache
->IsEnabled()) {
1141 wr_dp_set_cache_size(mWrState
, mDisplayItemCache
->CurrentSize());
1144 wr::VecU8 dlItems
, dlCache
, dlSpatialTree
;
1145 wr_api_end_builder(mWrState
, &aOutTransaction
.mDLDesc
, &dlItems
.inner
,
1146 &dlCache
.inner
, &dlSpatialTree
.inner
);
1147 aOutTransaction
.mDLItems
.emplace(dlItems
.inner
.data
, dlItems
.inner
.length
,
1148 dlItems
.inner
.capacity
);
1149 aOutTransaction
.mDLCache
.emplace(dlCache
.inner
.data
, dlCache
.inner
.length
,
1150 dlCache
.inner
.capacity
);
1151 aOutTransaction
.mDLSpatialTree
.emplace(dlSpatialTree
.inner
.data
,
1152 dlSpatialTree
.inner
.length
,
1153 dlSpatialTree
.inner
.capacity
);
1154 dlItems
.inner
.capacity
= 0;
1155 dlItems
.inner
.data
= nullptr;
1156 dlCache
.inner
.capacity
= 0;
1157 dlCache
.inner
.data
= nullptr;
1158 dlSpatialTree
.inner
.capacity
= 0;
1159 dlSpatialTree
.inner
.data
= nullptr;
1162 Maybe
<wr::WrSpatialId
> DisplayListBuilder::PushStackingContext(
1163 const wr::StackingContextParams
& aParams
, const wr::LayoutRect
& aBounds
,
1164 const wr::RasterSpace
& aRasterSpace
) {
1165 MOZ_ASSERT(mClipChainLeaf
.isNothing(),
1166 "Non-empty leaf from clip chain given, but not used with SC!");
1169 "PushStackingContext b=%s t=%s id=0x%" PRIx64
"\n", mWrState
,
1170 ToString(aBounds
).c_str(),
1171 aParams
.mTransformPtr
? ToString(*aParams
.mTransformPtr
).c_str() : "none",
1172 aParams
.animation
? aParams
.animation
->id
: 0);
1174 auto spatialId
= wr_dp_push_stacking_context(
1175 mWrState
, aBounds
, mCurrentSpaceAndClipChain
.space
, &aParams
,
1176 aParams
.mTransformPtr
, aParams
.mFilters
.Elements(),
1177 aParams
.mFilters
.Length(), aParams
.mFilterDatas
.Elements(),
1178 aParams
.mFilterDatas
.Length(), aRasterSpace
);
1180 return spatialId
.id
!= 0 ? Some(spatialId
) : Nothing();
1183 void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame
) {
1184 WRDL_LOG("PopStackingContext\n", mWrState
);
1185 wr_dp_pop_stacking_context(mWrState
, aIsReferenceFrame
);
1188 wr::WrClipChainId
DisplayListBuilder::DefineClipChain(
1189 const nsTArray
<wr::WrClipId
>& aClips
, bool aParentWithCurrentChain
) {
1192 const uint64_t* parent
= nullptr;
1193 if (aParentWithCurrentChain
&&
1194 mCurrentSpaceAndClipChain
.clip_chain
!= wr::ROOT_CLIP_CHAIN
) {
1195 parent
= &mCurrentSpaceAndClipChain
.clip_chain
;
1197 uint64_t clipchainId
= wr_dp_define_clipchain(
1198 mWrState
, parent
, aClips
.Elements(), aClips
.Length());
1199 if (MOZ_LOG_TEST(sWrDLLog
, LogLevel::Debug
)) {
1201 message
.AppendPrintf("DefineClipChain id=%" PRIu64
1202 " clipCount=%zu clipIds=[",
1203 clipchainId
, aClips
.Length());
1204 for (const auto& clip
: aClips
) {
1205 message
.AppendPrintf("%" PRIuPTR
",", clip
.id
);
1207 message
.Append("]");
1208 WRDL_LOG("%s", mWrState
, message
.get());
1210 return wr::WrClipChainId
{clipchainId
};
1213 wr::WrClipId
DisplayListBuilder::DefineImageMaskClip(
1214 const wr::ImageMask
& aMask
, const nsTArray
<wr::LayoutPoint
>& aPoints
,
1215 wr::FillRule aFillRule
) {
1218 WrClipId clipId
= wr_dp_define_image_mask_clip_with_parent_clip_chain(
1219 mWrState
, mCurrentSpaceAndClipChain
.space
, aMask
, aPoints
.Elements(),
1220 aPoints
.Length(), aFillRule
);
1225 wr::WrClipId
DisplayListBuilder::DefineRoundedRectClip(
1226 Maybe
<wr::WrSpatialId
> aSpace
, const wr::ComplexClipRegion
& aComplex
) {
1231 clipId
= wr_dp_define_rounded_rect_clip(mWrState
, *aSpace
, aComplex
);
1233 clipId
= wr_dp_define_rounded_rect_clip(
1234 mWrState
, mCurrentSpaceAndClipChain
.space
, aComplex
);
1240 wr::WrClipId
DisplayListBuilder::DefineRectClip(Maybe
<wr::WrSpatialId
> aSpace
,
1241 wr::LayoutRect aClipRect
) {
1246 clipId
= wr_dp_define_rect_clip(mWrState
, *aSpace
, aClipRect
);
1248 clipId
= wr_dp_define_rect_clip(mWrState
, mCurrentSpaceAndClipChain
.space
,
1255 wr::WrSpatialId
DisplayListBuilder::DefineStickyFrame(
1256 const wr::LayoutRect
& aContentRect
, const float* aTopMargin
,
1257 const float* aRightMargin
, const float* aBottomMargin
,
1258 const float* aLeftMargin
, const StickyOffsetBounds
& aVerticalBounds
,
1259 const StickyOffsetBounds
& aHorizontalBounds
,
1260 const wr::LayoutVector2D
& aAppliedOffset
, wr::SpatialTreeItemKey aKey
) {
1261 auto spatialId
= wr_dp_define_sticky_frame(
1262 mWrState
, mCurrentSpaceAndClipChain
.space
, aContentRect
, aTopMargin
,
1263 aRightMargin
, aBottomMargin
, aLeftMargin
, aVerticalBounds
,
1264 aHorizontalBounds
, aAppliedOffset
, aKey
);
1266 WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n",
1267 mWrState
, spatialId
.id
, ToString(aContentRect
).c_str(),
1268 aTopMargin
? ToString(*aTopMargin
).c_str() : "none",
1269 aRightMargin
? ToString(*aRightMargin
).c_str() : "none",
1270 aBottomMargin
? ToString(*aBottomMargin
).c_str() : "none",
1271 aLeftMargin
? ToString(*aLeftMargin
).c_str() : "none",
1272 ToString(aVerticalBounds
).c_str(),
1273 ToString(aHorizontalBounds
).c_str(),
1274 ToString(aAppliedOffset
).c_str());
1279 Maybe
<wr::WrSpatialId
> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
1280 layers::ScrollableLayerGuid::ViewID aViewId
) const {
1281 if (aViewId
== layers::ScrollableLayerGuid::NULL_SCROLL_ID
) {
1282 return Some(wr::RootScrollNode());
1285 auto it
= mScrollIds
.find(aViewId
);
1286 if (it
== mScrollIds
.end()) {
1290 return Some(it
->second
);
1293 wr::WrSpatialId
DisplayListBuilder::DefineScrollLayer(
1294 const layers::ScrollableLayerGuid::ViewID
& aViewId
,
1295 const Maybe
<wr::WrSpatialId
>& aParent
, const wr::LayoutRect
& aContentRect
,
1296 const wr::LayoutRect
& aClipRect
, const wr::LayoutVector2D
& aScrollOffset
,
1297 wr::APZScrollGeneration aScrollOffsetGeneration
,
1298 wr::HasScrollLinkedEffect aHasScrollLinkedEffect
,
1299 wr::SpatialTreeItemKey aKey
) {
1300 auto it
= mScrollIds
.find(aViewId
);
1301 if (it
!= mScrollIds
.end()) {
1305 // We haven't defined aViewId before, so let's define it now.
1306 wr::WrSpatialId defaultParent
= mCurrentSpaceAndClipChain
.space
;
1308 auto space
= wr_dp_define_scroll_layer(
1309 mWrState
, aViewId
, aParent
? aParent
.ptr() : &defaultParent
, aContentRect
,
1310 aClipRect
, aScrollOffset
, aScrollOffsetGeneration
, aHasScrollLinkedEffect
,
1313 WRDL_LOG("DefineScrollLayer id=%" PRIu64
1314 "/%zu p=%s co=%s cl=%s generation=%s hasScrollLinkedEffect=%s\n",
1315 mWrState
, aViewId
, space
.id
,
1316 aParent
? ToString(aParent
->id
).c_str() : "(nil)",
1317 ToString(aContentRect
).c_str(), ToString(aClipRect
).c_str(),
1318 ToString(aScrollOffsetGeneration
).c_str(),
1319 ToString(aHasScrollLinkedEffect
).c_str());
1321 mScrollIds
[aViewId
] = space
;
1325 void DisplayListBuilder::PushRect(const wr::LayoutRect
& aBounds
,
1326 const wr::LayoutRect
& aClip
,
1327 bool aIsBackfaceVisible
,
1328 bool aForceAntiAliasing
, bool aIsCheckerboard
,
1329 const wr::ColorF
& aColor
) {
1330 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1331 WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState
, ToString(aBounds
).c_str(),
1332 ToString(clip
).c_str(), ToString(aColor
).c_str());
1333 wr_dp_push_rect(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1334 aForceAntiAliasing
, aIsCheckerboard
,
1335 &mCurrentSpaceAndClipChain
, aColor
);
1338 void DisplayListBuilder::PushRoundedRect(const wr::LayoutRect
& aBounds
,
1339 const wr::LayoutRect
& aClip
,
1340 bool aIsBackfaceVisible
,
1341 const wr::ColorF
& aColor
) {
1342 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1343 WRDL_LOG("PushRoundedRect b=%s cl=%s c=%s\n", mWrState
,
1344 ToString(aBounds
).c_str(), ToString(clip
).c_str(),
1345 ToString(aColor
).c_str());
1347 // Draw the rounded rectangle as a border with rounded corners. We could also
1348 // draw this as a rectangle clipped to a rounded rectangle, but:
1349 // - clips are not cached; borders are
1350 // - a simple border like this will be drawn as an image
1351 // - Processing lots of clips is not WebRender's strong point.
1353 // Made the borders thicker than one half the width/height, to avoid
1354 // little white dots at the center at some magnifications.
1355 wr::BorderSide side
= {aColor
, wr::BorderStyle::Solid
};
1356 float h
= aBounds
.width() * 0.6f
;
1357 float v
= aBounds
.height() * 0.6f
;
1358 wr::LayoutSideOffsets widths
= {v
, h
, v
, h
};
1359 wr::BorderRadius radii
= {{h
, v
}, {h
, v
}, {h
, v
}, {h
, v
}};
1361 // Anti-aliased borders are required for rounded borders.
1362 wr_dp_push_border(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1363 &mCurrentSpaceAndClipChain
, wr::AntialiasBorder::Yes
,
1364 widths
, side
, side
, side
, side
, radii
);
1367 void DisplayListBuilder::PushHitTest(
1368 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1369 bool aIsBackfaceVisible
,
1370 const layers::ScrollableLayerGuid::ViewID
& aScrollId
,
1371 const gfx::CompositorHitTestInfo
& aHitInfo
, SideBits aSideBits
) {
1372 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1373 WRDL_LOG("PushHitTest b=%s cl=%s\n", mWrState
, ToString(aBounds
).c_str(),
1374 ToString(clip
).c_str());
1376 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits
<12>(),
1377 "CompositorHitTestFlags MAX value has to be less than number "
1378 "of bits in uint16_t minus 4 for SideBitsPacked");
1380 uint16_t hitInfoBits
= static_cast<uint16_t>(aHitInfo
.serialize()) |
1381 (static_cast<uint16_t>(aSideBits
) << 12);
1383 wr_dp_push_hit_test(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1384 &mCurrentSpaceAndClipChain
, aScrollId
, hitInfoBits
);
1387 void DisplayListBuilder::PushRectWithAnimation(
1388 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1389 bool aIsBackfaceVisible
, const wr::ColorF
& aColor
,
1390 const WrAnimationProperty
* aAnimation
) {
1391 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1392 WRDL_LOG("PushRectWithAnimation b=%s cl=%s c=%s\n", mWrState
,
1393 ToString(aBounds
).c_str(), ToString(clip
).c_str(),
1394 ToString(aColor
).c_str());
1396 wr_dp_push_rect_with_animation(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1397 &mCurrentSpaceAndClipChain
, aColor
,
1401 void DisplayListBuilder::PushClearRect(const wr::LayoutRect
& aBounds
) {
1402 wr::LayoutRect clip
= MergeClipLeaf(aBounds
);
1403 WRDL_LOG("PushClearRect b=%s c=%s\n", mWrState
, ToString(aBounds
).c_str(),
1404 ToString(clip
).c_str());
1405 wr_dp_push_clear_rect(mWrState
, aBounds
, clip
, &mCurrentSpaceAndClipChain
);
1408 void DisplayListBuilder::PushBackdropFilter(
1409 const wr::LayoutRect
& aBounds
, const wr::ComplexClipRegion
& aRegion
,
1410 const nsTArray
<wr::FilterOp
>& aFilters
,
1411 const nsTArray
<wr::WrFilterData
>& aFilterDatas
, bool aIsBackfaceVisible
) {
1412 wr::LayoutRect clip
= MergeClipLeaf(aBounds
);
1413 WRDL_LOG("PushBackdropFilter b=%s c=%s\n", mWrState
,
1414 ToString(aBounds
).c_str(), ToString(clip
).c_str());
1416 auto clipId
= DefineRoundedRectClip(Nothing(), aRegion
);
1417 auto clipChainId
= DefineClipChain({clipId
}, true);
1419 WrSpaceAndClipChain
{mCurrentSpaceAndClipChain
.space
, clipChainId
.id
};
1421 wr_dp_push_backdrop_filter(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1422 &spaceAndClip
, aFilters
.Elements(),
1423 aFilters
.Length(), aFilterDatas
.Elements(),
1424 aFilterDatas
.Length());
1427 void DisplayListBuilder::PushLinearGradient(
1428 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1429 bool aIsBackfaceVisible
, const wr::LayoutPoint
& aStartPoint
,
1430 const wr::LayoutPoint
& aEndPoint
, const nsTArray
<wr::GradientStop
>& aStops
,
1431 wr::ExtendMode aExtendMode
, const wr::LayoutSize aTileSize
,
1432 const wr::LayoutSize aTileSpacing
) {
1433 wr_dp_push_linear_gradient(
1434 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1435 &mCurrentSpaceAndClipChain
, aStartPoint
, aEndPoint
, aStops
.Elements(),
1436 aStops
.Length(), aExtendMode
, aTileSize
, aTileSpacing
);
1439 void DisplayListBuilder::PushRadialGradient(
1440 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1441 bool aIsBackfaceVisible
, const wr::LayoutPoint
& aCenter
,
1442 const wr::LayoutSize
& aRadius
, const nsTArray
<wr::GradientStop
>& aStops
,
1443 wr::ExtendMode aExtendMode
, const wr::LayoutSize aTileSize
,
1444 const wr::LayoutSize aTileSpacing
) {
1445 wr_dp_push_radial_gradient(
1446 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1447 &mCurrentSpaceAndClipChain
, aCenter
, aRadius
, aStops
.Elements(),
1448 aStops
.Length(), aExtendMode
, aTileSize
, aTileSpacing
);
1451 void DisplayListBuilder::PushConicGradient(
1452 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1453 bool aIsBackfaceVisible
, const wr::LayoutPoint
& aCenter
, const float aAngle
,
1454 const nsTArray
<wr::GradientStop
>& aStops
, wr::ExtendMode aExtendMode
,
1455 const wr::LayoutSize aTileSize
, const wr::LayoutSize aTileSpacing
) {
1456 wr_dp_push_conic_gradient(mWrState
, aBounds
, MergeClipLeaf(aClip
),
1457 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1458 aCenter
, aAngle
, aStops
.Elements(), aStops
.Length(),
1459 aExtendMode
, aTileSize
, aTileSpacing
);
1462 void DisplayListBuilder::PushImage(
1463 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1464 bool aIsBackfaceVisible
, bool aForceAntiAliasing
,
1465 wr::ImageRendering aFilter
, wr::ImageKey aImage
, bool aPremultipliedAlpha
,
1466 const wr::ColorF
& aColor
, bool aPreferCompositorSurface
,
1467 bool aSupportsExternalCompositing
) {
1468 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1469 WRDL_LOG("PushImage b=%s cl=%s\n", mWrState
, ToString(aBounds
).c_str(),
1470 ToString(clip
).c_str());
1471 wr_dp_push_image(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1472 aForceAntiAliasing
, &mCurrentSpaceAndClipChain
, aFilter
,
1473 aImage
, aPremultipliedAlpha
, aColor
,
1474 aPreferCompositorSurface
, aSupportsExternalCompositing
);
1477 void DisplayListBuilder::PushRepeatingImage(
1478 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1479 bool aIsBackfaceVisible
, const wr::LayoutSize
& aStretchSize
,
1480 const wr::LayoutSize
& aTileSpacing
, wr::ImageRendering aFilter
,
1481 wr::ImageKey aImage
, bool aPremultipliedAlpha
, const wr::ColorF
& aColor
) {
1482 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1483 WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState
,
1484 ToString(aBounds
).c_str(), ToString(clip
).c_str(),
1485 ToString(aStretchSize
).c_str(), ToString(aTileSpacing
).c_str());
1486 wr_dp_push_repeating_image(
1487 mWrState
, aBounds
, clip
, aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1488 aStretchSize
, aTileSpacing
, aFilter
, aImage
, aPremultipliedAlpha
, aColor
);
1491 void DisplayListBuilder::PushYCbCrPlanarImage(
1492 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1493 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1494 wr::ImageKey aImageChannel1
, wr::ImageKey aImageChannel2
,
1495 wr::WrColorDepth aColorDepth
, wr::WrYuvColorSpace aColorSpace
,
1496 wr::WrColorRange aColorRange
, wr::ImageRendering aRendering
,
1497 bool aPreferCompositorSurface
, bool aSupportsExternalCompositing
) {
1498 wr_dp_push_yuv_planar_image(
1499 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1500 &mCurrentSpaceAndClipChain
, aImageChannel0
, aImageChannel1
,
1501 aImageChannel2
, aColorDepth
, aColorSpace
, aColorRange
, aRendering
,
1502 aPreferCompositorSurface
, aSupportsExternalCompositing
);
1505 void DisplayListBuilder::PushNV12Image(
1506 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1507 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1508 wr::ImageKey aImageChannel1
, wr::WrColorDepth aColorDepth
,
1509 wr::WrYuvColorSpace aColorSpace
, wr::WrColorRange aColorRange
,
1510 wr::ImageRendering aRendering
, bool aPreferCompositorSurface
,
1511 bool aSupportsExternalCompositing
) {
1512 wr_dp_push_yuv_NV12_image(
1513 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1514 &mCurrentSpaceAndClipChain
, aImageChannel0
, aImageChannel1
, aColorDepth
,
1515 aColorSpace
, aColorRange
, aRendering
, aPreferCompositorSurface
,
1516 aSupportsExternalCompositing
);
1519 void DisplayListBuilder::PushP010Image(
1520 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1521 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1522 wr::ImageKey aImageChannel1
, wr::WrColorDepth aColorDepth
,
1523 wr::WrYuvColorSpace aColorSpace
, wr::WrColorRange aColorRange
,
1524 wr::ImageRendering aRendering
, bool aPreferCompositorSurface
,
1525 bool aSupportsExternalCompositing
) {
1526 wr_dp_push_yuv_P010_image(
1527 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1528 &mCurrentSpaceAndClipChain
, aImageChannel0
, aImageChannel1
, aColorDepth
,
1529 aColorSpace
, aColorRange
, aRendering
, aPreferCompositorSurface
,
1530 aSupportsExternalCompositing
);
1533 void DisplayListBuilder::PushYCbCrInterleavedImage(
1534 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1535 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1536 wr::WrColorDepth aColorDepth
, wr::WrYuvColorSpace aColorSpace
,
1537 wr::WrColorRange aColorRange
, wr::ImageRendering aRendering
,
1538 bool aPreferCompositorSurface
, bool aSupportsExternalCompositing
) {
1539 wr_dp_push_yuv_interleaved_image(
1540 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1541 &mCurrentSpaceAndClipChain
, aImageChannel0
, aColorDepth
, aColorSpace
,
1542 aColorRange
, aRendering
, aPreferCompositorSurface
,
1543 aSupportsExternalCompositing
);
1546 void DisplayListBuilder::PushIFrame(const LayoutDeviceRect
& aDevPxBounds
,
1547 bool aIsBackfaceVisible
,
1548 PipelineId aPipeline
,
1549 bool aIgnoreMissingPipeline
) {
1550 // If the incoming bounds size has decimals (As it could when zoom is
1551 // involved), and is pushed straight through here, the compositor would end up
1552 // calculating the destination rect to paint the rendered iframe into
1553 // with those decimal values, rounding the result, instead of snapping. This
1554 // can cause the rendered iframe rect and its destination rect to be
1555 // mismatched, resulting in interpolation artifacts.
1556 auto snapped
= aDevPxBounds
;
1557 auto tl
= snapped
.TopLeft().Round();
1558 auto br
= snapped
.BottomRight().Round();
1560 snapped
.SizeTo(LayoutDeviceSize(br
.x
- tl
.x
, br
.y
- tl
.y
));
1562 const auto bounds
= wr::ToLayoutRect(snapped
);
1563 wr_dp_push_iframe(mWrState
, bounds
, MergeClipLeaf(bounds
), aIsBackfaceVisible
,
1564 &mCurrentSpaceAndClipChain
, aPipeline
,
1565 aIgnoreMissingPipeline
);
1568 void DisplayListBuilder::PushBorder(const wr::LayoutRect
& aBounds
,
1569 const wr::LayoutRect
& aClip
,
1570 bool aIsBackfaceVisible
,
1571 const wr::LayoutSideOffsets
& aWidths
,
1572 const Range
<const wr::BorderSide
>& aSides
,
1573 const wr::BorderRadius
& aRadius
,
1574 wr::AntialiasBorder aAntialias
) {
1575 MOZ_ASSERT(aSides
.length() == 4);
1576 if (aSides
.length() != 4) {
1579 wr_dp_push_border(mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1580 &mCurrentSpaceAndClipChain
, aAntialias
, aWidths
, aSides
[0],
1581 aSides
[1], aSides
[2], aSides
[3], aRadius
);
1584 void DisplayListBuilder::PushBorderImage(const wr::LayoutRect
& aBounds
,
1585 const wr::LayoutRect
& aClip
,
1586 bool aIsBackfaceVisible
,
1587 const wr::WrBorderImage
& aParams
) {
1588 wr_dp_push_border_image(mWrState
, aBounds
, MergeClipLeaf(aClip
),
1589 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1593 void DisplayListBuilder::PushBorderGradient(
1594 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1595 bool aIsBackfaceVisible
, const wr::LayoutSideOffsets
& aWidths
,
1596 const int32_t aWidth
, const int32_t aHeight
, bool aFill
,
1597 const wr::DeviceIntSideOffsets
& aSlice
, const wr::LayoutPoint
& aStartPoint
,
1598 const wr::LayoutPoint
& aEndPoint
, const nsTArray
<wr::GradientStop
>& aStops
,
1599 wr::ExtendMode aExtendMode
) {
1600 wr_dp_push_border_gradient(
1601 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1602 &mCurrentSpaceAndClipChain
, aWidths
, aWidth
, aHeight
, aFill
, aSlice
,
1603 aStartPoint
, aEndPoint
, aStops
.Elements(), aStops
.Length(), aExtendMode
);
1606 void DisplayListBuilder::PushBorderRadialGradient(
1607 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1608 bool aIsBackfaceVisible
, const wr::LayoutSideOffsets
& aWidths
, bool aFill
,
1609 const wr::LayoutPoint
& aCenter
, const wr::LayoutSize
& aRadius
,
1610 const nsTArray
<wr::GradientStop
>& aStops
, wr::ExtendMode aExtendMode
) {
1611 wr_dp_push_border_radial_gradient(
1612 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1613 &mCurrentSpaceAndClipChain
, aWidths
, aFill
, aCenter
, aRadius
,
1614 aStops
.Elements(), aStops
.Length(), aExtendMode
);
1617 void DisplayListBuilder::PushBorderConicGradient(
1618 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1619 bool aIsBackfaceVisible
, const wr::LayoutSideOffsets
& aWidths
, bool aFill
,
1620 const wr::LayoutPoint
& aCenter
, const float aAngle
,
1621 const nsTArray
<wr::GradientStop
>& aStops
, wr::ExtendMode aExtendMode
) {
1622 wr_dp_push_border_conic_gradient(
1623 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1624 &mCurrentSpaceAndClipChain
, aWidths
, aFill
, aCenter
, aAngle
,
1625 aStops
.Elements(), aStops
.Length(), aExtendMode
);
1628 void DisplayListBuilder::PushText(const wr::LayoutRect
& aBounds
,
1629 const wr::LayoutRect
& aClip
,
1630 bool aIsBackfaceVisible
,
1631 const wr::ColorF
& aColor
,
1632 wr::FontInstanceKey aFontKey
,
1633 Range
<const wr::GlyphInstance
> aGlyphBuffer
,
1634 const wr::GlyphOptions
* aGlyphOptions
) {
1635 wr_dp_push_text(mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1636 &mCurrentSpaceAndClipChain
, aColor
, aFontKey
,
1637 &aGlyphBuffer
[0], aGlyphBuffer
.length(), aGlyphOptions
);
1640 void DisplayListBuilder::PushLine(const wr::LayoutRect
& aClip
,
1641 bool aIsBackfaceVisible
,
1642 const wr::Line
& aLine
) {
1643 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1644 wr_dp_push_line(mWrState
, &clip
, aIsBackfaceVisible
,
1645 &mCurrentSpaceAndClipChain
, &aLine
.bounds
,
1646 aLine
.wavyLineThickness
, aLine
.orientation
, &aLine
.color
,
1650 void DisplayListBuilder::PushShadow(const wr::LayoutRect
& aRect
,
1651 const wr::LayoutRect
& aClip
,
1652 bool aIsBackfaceVisible
,
1653 const wr::Shadow
& aShadow
,
1654 bool aShouldInflate
) {
1655 // Local clip_rects are translated inside of shadows, as they are assumed to
1656 // be part of the element drawing itself, and not a parent frame clipping it.
1657 // As such, it is not sound to apply the MergeClipLeaf optimization inside of
1658 // shadows. So we disable the optimization when we encounter a shadow.
1659 // Shadows don't span frames, so we don't have to worry about MergeClipLeaf
1660 // being re-enabled mid-shadow. The optimization is restored in PopAllShadows.
1661 SuspendClipLeafMerging();
1662 wr_dp_push_shadow(mWrState
, aRect
, aClip
, aIsBackfaceVisible
,
1663 &mCurrentSpaceAndClipChain
, aShadow
, aShouldInflate
);
1666 void DisplayListBuilder::PopAllShadows() {
1667 wr_dp_pop_all_shadows(mWrState
);
1668 ResumeClipLeafMerging();
1671 void DisplayListBuilder::SuspendClipLeafMerging() {
1672 if (mClipChainLeaf
) {
1673 // No one should reinitialize mClipChainLeaf while we're suspended
1674 MOZ_ASSERT(!mSuspendedClipChainLeaf
);
1676 mSuspendedClipChainLeaf
= mClipChainLeaf
;
1677 mSuspendedSpaceAndClipChain
= Some(mCurrentSpaceAndClipChain
);
1679 auto clipId
= DefineRectClip(Nothing(), *mClipChainLeaf
);
1680 auto clipChainId
= DefineClipChain({clipId
}, true);
1682 mCurrentSpaceAndClipChain
.clip_chain
= clipChainId
.id
;
1683 mClipChainLeaf
= Nothing();
1687 void DisplayListBuilder::ResumeClipLeafMerging() {
1688 if (mSuspendedClipChainLeaf
) {
1689 mCurrentSpaceAndClipChain
= *mSuspendedSpaceAndClipChain
;
1690 mClipChainLeaf
= mSuspendedClipChainLeaf
;
1692 mSuspendedClipChainLeaf
= Nothing();
1693 mSuspendedSpaceAndClipChain
= Nothing();
1697 void DisplayListBuilder::PushBoxShadow(
1698 const wr::LayoutRect
& aRect
, const wr::LayoutRect
& aClip
,
1699 bool aIsBackfaceVisible
, const wr::LayoutRect
& aBoxBounds
,
1700 const wr::LayoutVector2D
& aOffset
, const wr::ColorF
& aColor
,
1701 const float& aBlurRadius
, const float& aSpreadRadius
,
1702 const wr::BorderRadius
& aBorderRadius
,
1703 const wr::BoxShadowClipMode
& aClipMode
) {
1704 wr_dp_push_box_shadow(mWrState
, aRect
, MergeClipLeaf(aClip
),
1705 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1706 aBoxBounds
, aOffset
, aColor
, aBlurRadius
, aSpreadRadius
,
1707 aBorderRadius
, aClipMode
);
1710 void DisplayListBuilder::StartGroup(nsPaintedDisplayItem
* aItem
) {
1711 if (!mDisplayItemCache
|| mDisplayItemCache
->IsFull()) {
1715 MOZ_ASSERT(!mCurrentCacheSlot
);
1716 mCurrentCacheSlot
= mDisplayItemCache
->AssignSlot(aItem
);
1718 if (mCurrentCacheSlot
) {
1719 wr_dp_start_item_group(mWrState
);
1723 void DisplayListBuilder::CancelGroup(const bool aDiscard
) {
1724 if (!mDisplayItemCache
|| !mCurrentCacheSlot
) {
1728 wr_dp_cancel_item_group(mWrState
, aDiscard
);
1729 mCurrentCacheSlot
= Nothing();
1732 void DisplayListBuilder::FinishGroup() {
1733 if (!mDisplayItemCache
|| !mCurrentCacheSlot
) {
1737 MOZ_ASSERT(mCurrentCacheSlot
);
1739 if (wr_dp_finish_item_group(mWrState
, mCurrentCacheSlot
.ref())) {
1740 mDisplayItemCache
->MarkSlotOccupied(mCurrentCacheSlot
.ref(),
1741 CurrentSpaceAndClipChain());
1742 mDisplayItemCache
->Stats().AddCached();
1745 mCurrentCacheSlot
= Nothing();
1748 bool DisplayListBuilder::ReuseItem(nsPaintedDisplayItem
* aItem
) {
1749 if (!mDisplayItemCache
) {
1753 mDisplayItemCache
->Stats().AddTotal();
1755 if (mDisplayItemCache
->IsEmpty()) {
1759 Maybe
<uint16_t> slot
=
1760 mDisplayItemCache
->CanReuseItem(aItem
, CurrentSpaceAndClipChain());
1763 mDisplayItemCache
->Stats().AddReused();
1764 wr_dp_push_reuse_items(mWrState
, slot
.ref());
1771 Maybe
<layers::ScrollableLayerGuid::ViewID
>
1772 DisplayListBuilder::GetContainingFixedPosScrollTarget(
1773 const ActiveScrolledRoot
* aAsr
) {
1774 return mActiveFixedPosTracker
1775 ? mActiveFixedPosTracker
->GetScrollTargetForASR(aAsr
)
1779 Maybe
<SideBits
> DisplayListBuilder::GetContainingFixedPosSideBits(
1780 const ActiveScrolledRoot
* aAsr
) {
1781 return mActiveFixedPosTracker
1782 ? mActiveFixedPosTracker
->GetSideBitsForASR(aAsr
)
1786 DisplayListBuilder::FixedPosScrollTargetTracker::FixedPosScrollTargetTracker(
1787 DisplayListBuilder
& aBuilder
, const ActiveScrolledRoot
* aAsr
,
1788 layers::ScrollableLayerGuid::ViewID aScrollId
, SideBits aSideBits
)
1789 : mParentTracker(aBuilder
.mActiveFixedPosTracker
),
1792 mScrollId(aScrollId
),
1793 mSideBits(aSideBits
) {
1794 aBuilder
.mActiveFixedPosTracker
= this;
1797 DisplayListBuilder::FixedPosScrollTargetTracker::
1798 ~FixedPosScrollTargetTracker() {
1799 mBuilder
.mActiveFixedPosTracker
= mParentTracker
;
1802 Maybe
<layers::ScrollableLayerGuid::ViewID
>
1803 DisplayListBuilder::FixedPosScrollTargetTracker::GetScrollTargetForASR(
1804 const ActiveScrolledRoot
* aAsr
) {
1805 return aAsr
== mAsr
? Some(mScrollId
) : Nothing();
1809 DisplayListBuilder::FixedPosScrollTargetTracker::GetSideBitsForASR(
1810 const ActiveScrolledRoot
* aAsr
) {
1811 return aAsr
== mAsr
? Some(mSideBits
) : Nothing();
1814 gfxContext
* DisplayListBuilder::GetTextContext(
1815 wr::IpcResourceUpdateQueue
& aResources
,
1816 const layers::StackingContextHelper
& aSc
,
1817 layers::RenderRootStateManager
* aManager
, nsDisplayItem
* aItem
,
1818 nsRect
& aBounds
, const gfx::Point
& aDeviceOffset
) {
1819 if (!mCachedTextDT
) {
1820 mCachedTextDT
= new layout::TextDrawTarget(*this, aResources
, aSc
, aManager
,
1822 if (mCachedTextDT
->IsValid()) {
1823 mCachedContext
= MakeUnique
<gfxContext
>(mCachedTextDT
, aDeviceOffset
);
1826 mCachedTextDT
->Reinitialize(aResources
, aSc
, aManager
, aItem
, aBounds
);
1827 mCachedContext
->SetDeviceOffset(aDeviceOffset
);
1828 mCachedContext
->SetMatrix(gfx::Matrix());
1831 return mCachedContext
.get();
1834 void DisplayListBuilder::PushInheritedClipChain(
1835 nsDisplayListBuilder
* aBuilder
, const DisplayItemClipChain
* aClipChain
) {
1836 if (!aClipChain
|| mInheritedClipChain
== aClipChain
) {
1839 if (!mInheritedClipChain
) {
1840 mInheritedClipChain
= aClipChain
;
1844 mInheritedClipChain
=
1845 aBuilder
->CreateClipChainIntersection(mInheritedClipChain
, aClipChain
);
1849 } // namespace mozilla
1853 void wr_transaction_notification_notified(uintptr_t aHandler
,
1854 mozilla::wr::Checkpoint aWhen
) {
1855 auto handler
= reinterpret_cast<mozilla::wr::NotificationHandler
*>(aHandler
);
1856 handler
->Notify(aWhen
);
1857 // TODO: it would be better to get a callback when the object is destroyed on
1858 // the rust side and delete then.
1862 void wr_register_thread_local_arena() {
1864 jemalloc_thread_local_arena(true);