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/StaticPrefs_gfx.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/ToString.h"
15 #include "mozilla/webrender/RenderCompositor.h"
16 #include "mozilla/widget/CompositorWidget.h"
17 #include "mozilla/layers/SynchronousTask.h"
18 #include "TextDrawTarget.h"
19 #include "malloc_decls.h"
23 //#define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__)
24 //#define WRDL_LOG(...) if (XRE_IsContentProcess()) printf_stderr("WRDL(%p): " __VA_ARGS__)
28 using namespace layers
;
32 MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf
)
33 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(WebRenderMallocEnclosingSizeOf
)
36 eSideBitsPackedTop
= 0x1000,
37 eSideBitsPackedRight
= 0x2000,
38 eSideBitsPackedBottom
= 0x4000,
39 eSideBitsPackedLeft
= 0x8000
42 static uint16_t SideBitsToHitInfoBits(SideBits aSideBits
) {
44 if (aSideBits
& SideBits::eTop
) {
45 ret
|= eSideBitsPackedTop
;
47 if (aSideBits
& SideBits::eRight
) {
48 ret
|= eSideBitsPackedRight
;
50 if (aSideBits
& SideBits::eBottom
) {
51 ret
|= eSideBitsPackedBottom
;
53 if (aSideBits
& SideBits::eLeft
) {
54 ret
|= eSideBitsPackedLeft
;
59 class NewRenderer
: public RendererEvent
{
61 NewRenderer(wr::DocumentHandle
** aDocHandle
,
62 layers::CompositorBridgeParent
* aBridge
,
63 WebRenderBackend
* aBackend
, WebRenderCompositor
* aCompositor
,
64 int32_t* aMaxTextureSize
, bool* aUseANGLE
, bool* aUseDComp
,
65 bool* aUseTripleBuffering
, bool* aSupportsExternalBufferTextures
,
66 RefPtr
<widget::CompositorWidget
>&& aWidget
,
67 layers::SynchronousTask
* aTask
, LayoutDeviceIntSize aSize
,
68 layers::WindowKind aWindowKind
, layers::SyncHandle
* aHandle
,
70 : mDocHandle(aDocHandle
),
72 mCompositor(aCompositor
),
73 mMaxTextureSize(aMaxTextureSize
),
76 mUseTripleBuffering(aUseTripleBuffering
),
77 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures
),
79 mCompositorWidget(std::move(aWidget
)),
82 mWindowKind(aWindowKind
),
85 MOZ_COUNT_CTOR(NewRenderer
);
88 MOZ_COUNTED_DTOR(NewRenderer
)
90 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
91 layers::AutoCompleteTask
complete(mTask
);
93 UniquePtr
<RenderCompositor
> compositor
=
94 RenderCompositor::Create(std::move(mCompositorWidget
), *mError
);
96 if (!mError
->IsEmpty()) {
97 gfxCriticalNote
<< mError
->BeginReading();
102 *mBackend
= compositor
->BackendType();
103 *mCompositor
= compositor
->CompositorType();
104 *mUseANGLE
= compositor
->UseANGLE();
105 *mUseDComp
= compositor
->UseDComp();
106 *mUseTripleBuffering
= compositor
->UseTripleBuffering();
107 *mSupportsExternalBufferTextures
=
108 compositor
->SupportsExternalBufferTextures();
110 // Only allow the panic on GL error functionality in nightly builds,
111 // since it (deliberately) crashes the GPU process if any GL call
112 // returns an error code.
113 bool panic_on_gl_error
= false;
116 StaticPrefs::gfx_webrender_panic_on_gl_error_AtStartup();
119 bool isMainWindow
= true; // TODO!
120 bool supportLowPriorityTransactions
= isMainWindow
;
121 bool supportLowPriorityThreadpool
=
122 supportLowPriorityTransactions
&&
123 StaticPrefs::gfx_webrender_enable_low_priority_pool();
124 wr::Renderer
* wrRenderer
= nullptr;
125 char* errorMessage
= nullptr;
126 int picTileWidth
= StaticPrefs::gfx_webrender_picture_tile_width();
127 int picTileHeight
= StaticPrefs::gfx_webrender_picture_tile_height();
128 auto* swgl
= compositor
->swgl();
129 auto* gl
= (compositor
->gl() && !swgl
) ? compositor
->gl() : nullptr;
130 auto* progCache
= (aRenderThread
.GetProgramCache() && !swgl
)
131 ? aRenderThread
.GetProgramCache()->Raw()
133 auto* shaders
= (aRenderThread
.GetShaders() && !swgl
)
134 ? aRenderThread
.GetShaders()->RawShaders()
138 aWindowId
, mSize
.width
, mSize
.height
,
139 mWindowKind
== WindowKind::MAIN
, supportLowPriorityTransactions
,
140 supportLowPriorityThreadpool
, gfx::gfxVars::UseGLSwizzle(),
141 gfx::gfxVars::UseWebRenderScissoredCacheClears(),
143 StaticPrefs::gfx_webrender_start_debug_server(),
147 swgl
, gl
, compositor
->SurfaceOriginIsTopLeft(), progCache
, shaders
,
148 aRenderThread
.ThreadPool().Raw(),
149 aRenderThread
.ThreadPoolLP().Raw(), &WebRenderMallocSizeOf
,
150 &WebRenderMallocEnclosingSizeOf
, 0, compositor
.get(),
151 compositor
->ShouldUseNativeCompositor(),
152 compositor
->GetMaxUpdateRects(), compositor
->UsePartialPresent(),
153 compositor
->GetMaxPartialPresentRects(),
154 compositor
->ShouldDrawPreviousPartialPresentRegions(), mDocHandle
,
155 &wrRenderer
, mMaxTextureSize
, &errorMessage
,
156 StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(),
157 panic_on_gl_error
, picTileWidth
, picTileHeight
)) {
158 // wr_window_new puts a message into gfxCriticalNote if it returns false
159 MOZ_ASSERT(errorMessage
);
160 mError
->AssignASCII(errorMessage
);
161 wr_api_free_error_msg(errorMessage
);
164 MOZ_ASSERT(wrRenderer
);
166 RefPtr
<RenderThread
> thread
= &aRenderThread
;
168 MakeUnique
<RendererOGL
>(std::move(thread
), std::move(compositor
),
169 aWindowId
, wrRenderer
, mBridge
);
170 if (wrRenderer
&& renderer
) {
171 wr::WrExternalImageHandler handler
= renderer
->GetExternalImageHandler();
172 wr_renderer_set_external_image_handler(wrRenderer
, &handler
);
176 layers::SyncObjectHost
* syncObj
= renderer
->GetSyncObject();
178 *mSyncHandle
= syncObj
->GetSyncHandle();
182 aRenderThread
.AddRenderer(aWindowId
, std::move(renderer
));
186 wr::DocumentHandle
** mDocHandle
;
187 WebRenderBackend
* mBackend
;
188 WebRenderCompositor
* mCompositor
;
189 int32_t* mMaxTextureSize
;
192 bool* mUseTripleBuffering
;
193 bool* mSupportsExternalBufferTextures
;
194 layers::CompositorBridgeParent
* mBridge
;
195 RefPtr
<widget::CompositorWidget
> mCompositorWidget
;
196 layers::SynchronousTask
* mTask
;
197 LayoutDeviceIntSize mSize
;
198 layers::WindowKind mWindowKind
;
199 layers::SyncHandle
* mSyncHandle
;
203 class RemoveRenderer
: public RendererEvent
{
205 explicit RemoveRenderer(layers::SynchronousTask
* aTask
) : mTask(aTask
) {
206 MOZ_COUNT_CTOR(RemoveRenderer
);
209 MOZ_COUNTED_DTOR_OVERRIDE(RemoveRenderer
)
211 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
212 aRenderThread
.RemoveRenderer(aWindowId
);
213 layers::AutoCompleteTask
complete(mTask
);
217 layers::SynchronousTask
* mTask
;
220 TransactionBuilder::TransactionBuilder(WebRenderAPI
* aApi
,
221 bool aUseSceneBuilderThread
)
222 : mUseSceneBuilderThread(aUseSceneBuilderThread
),
223 mApiBackend(aApi
->GetBackendType()) {
224 mTxn
= wr_transaction_new(mUseSceneBuilderThread
);
227 TransactionBuilder::~TransactionBuilder() { wr_transaction_delete(mTxn
); }
229 void TransactionBuilder::SetLowPriority(bool aIsLowPriority
) {
230 wr_transaction_set_low_priority(mTxn
, aIsLowPriority
);
233 void TransactionBuilder::UpdateEpoch(PipelineId aPipelineId
, Epoch aEpoch
) {
234 wr_transaction_update_epoch(mTxn
, aPipelineId
, aEpoch
);
237 void TransactionBuilder::SetRootPipeline(PipelineId aPipelineId
) {
238 wr_transaction_set_root_pipeline(mTxn
, aPipelineId
);
241 void TransactionBuilder::RemovePipeline(PipelineId aPipelineId
) {
242 wr_transaction_remove_pipeline(mTxn
, aPipelineId
);
245 void TransactionBuilder::SetDisplayList(
246 const gfx::DeviceColor
& aBgColor
, Epoch aEpoch
,
247 const wr::LayoutSize
& aViewportSize
, wr::WrPipelineId pipeline_id
,
248 wr::BuiltDisplayListDescriptor dl_descriptor
, wr::Vec
<uint8_t>& dl_data
) {
249 wr_transaction_set_display_list(mTxn
, aEpoch
, ToColorF(aBgColor
),
250 aViewportSize
, pipeline_id
, dl_descriptor
,
254 void TransactionBuilder::ClearDisplayList(Epoch aEpoch
,
255 wr::WrPipelineId aPipelineId
) {
256 wr_transaction_clear_display_list(mTxn
, aEpoch
, aPipelineId
);
259 void TransactionBuilder::GenerateFrame(const VsyncId
& aVsyncId
) {
260 wr_transaction_generate_frame(mTxn
, aVsyncId
.mId
);
263 void TransactionBuilder::InvalidateRenderedFrame() {
264 wr_transaction_invalidate_rendered_frame(mTxn
);
267 void TransactionBuilder::UpdateDynamicProperties(
268 const nsTArray
<wr::WrOpacityProperty
>& aOpacityArray
,
269 const nsTArray
<wr::WrTransformProperty
>& aTransformArray
,
270 const nsTArray
<wr::WrColorProperty
>& aColorArray
) {
271 wr_transaction_update_dynamic_properties(
272 mTxn
, aOpacityArray
.IsEmpty() ? nullptr : aOpacityArray
.Elements(),
273 aOpacityArray
.Length(),
274 aTransformArray
.IsEmpty() ? nullptr : aTransformArray
.Elements(),
275 aTransformArray
.Length(),
276 aColorArray
.IsEmpty() ? nullptr : aColorArray
.Elements(),
277 aColorArray
.Length());
280 bool TransactionBuilder::IsEmpty() const {
281 return wr_transaction_is_empty(mTxn
);
284 bool TransactionBuilder::IsResourceUpdatesEmpty() const {
285 return wr_transaction_resource_updates_is_empty(mTxn
);
288 bool TransactionBuilder::IsRenderedFrameInvalidated() const {
289 return wr_transaction_is_rendered_frame_invalidated(mTxn
);
292 void TransactionBuilder::SetDocumentView(
293 const LayoutDeviceIntRect
& aDocumentRect
) {
294 wr::DeviceIntRect wrDocRect
;
295 wrDocRect
.origin
.x
= aDocumentRect
.x
;
296 wrDocRect
.origin
.y
= aDocumentRect
.y
;
297 wrDocRect
.size
.width
= aDocumentRect
.width
;
298 wrDocRect
.size
.height
= aDocumentRect
.height
;
299 wr_transaction_set_document_view(mTxn
, &wrDocRect
);
302 void TransactionBuilder::UpdateScrollPosition(
303 const wr::WrPipelineId
& aPipelineId
,
304 const layers::ScrollableLayerGuid::ViewID
& aScrollId
,
305 const wr::LayoutPoint
& aScrollPosition
) {
306 wr_transaction_scroll_layer(mTxn
, aPipelineId
, aScrollId
, aScrollPosition
);
309 TransactionWrapper::TransactionWrapper(Transaction
* aTxn
) : mTxn(aTxn
) {}
311 void TransactionWrapper::UpdateDynamicProperties(
312 const nsTArray
<wr::WrOpacityProperty
>& aOpacityArray
,
313 const nsTArray
<wr::WrTransformProperty
>& aTransformArray
,
314 const nsTArray
<wr::WrColorProperty
>& aColorArray
) {
315 wr_transaction_update_dynamic_properties(
316 mTxn
, aOpacityArray
.IsEmpty() ? nullptr : aOpacityArray
.Elements(),
317 aOpacityArray
.Length(),
318 aTransformArray
.IsEmpty() ? nullptr : aTransformArray
.Elements(),
319 aTransformArray
.Length(),
320 aColorArray
.IsEmpty() ? nullptr : aColorArray
.Elements(),
321 aColorArray
.Length());
324 void TransactionWrapper::AppendTransformProperties(
325 const nsTArray
<wr::WrTransformProperty
>& aTransformArray
) {
326 wr_transaction_append_transform_properties(
327 mTxn
, aTransformArray
.IsEmpty() ? nullptr : aTransformArray
.Elements(),
328 aTransformArray
.Length());
331 void TransactionWrapper::UpdateScrollPosition(
332 const wr::WrPipelineId
& aPipelineId
,
333 const layers::ScrollableLayerGuid::ViewID
& aScrollId
,
334 const wr::LayoutPoint
& aScrollPosition
) {
335 wr_transaction_scroll_layer(mTxn
, aPipelineId
, aScrollId
, aScrollPosition
);
338 void TransactionWrapper::UpdatePinchZoom(float aZoom
) {
339 wr_transaction_pinch_zoom(mTxn
, aZoom
);
342 void TransactionWrapper::UpdateIsTransformAsyncZooming(uint64_t aAnimationId
,
344 wr_transaction_set_is_transform_async_zooming(mTxn
, aAnimationId
, aIsZooming
);
348 already_AddRefed
<WebRenderAPI
> WebRenderAPI::Create(
349 layers::CompositorBridgeParent
* aBridge
,
350 RefPtr
<widget::CompositorWidget
>&& aWidget
, const wr::WrWindowId
& aWindowId
,
351 LayoutDeviceIntSize aSize
, layers::WindowKind aWindowKind
,
352 nsACString
& aError
) {
356 sizeof(size_t) == sizeof(uintptr_t),
357 "The FFI bindings assume size_t is the same size as uintptr_t!");
359 wr::DocumentHandle
* docHandle
= nullptr;
360 WebRenderBackend backend
= WebRenderBackend::HARDWARE
;
361 WebRenderCompositor compositor
= WebRenderCompositor::DRAW
;
362 int32_t maxTextureSize
= 0;
363 bool useANGLE
= false;
364 bool useDComp
= false;
365 bool useTripleBuffering
= false;
366 bool supportsExternalBufferTextures
= false;
367 layers::SyncHandle syncHandle
= 0;
369 // Dispatch a synchronous task because the DocumentHandle object needs to be
370 // created on the render thread. If need be we could delay waiting on this
371 // task until the next time we need to access the DocumentHandle object.
372 layers::SynchronousTask
task("Create Renderer");
373 auto event
= MakeUnique
<NewRenderer
>(
374 &docHandle
, aBridge
, &backend
, &compositor
, &maxTextureSize
, &useANGLE
,
375 &useDComp
, &useTripleBuffering
, &supportsExternalBufferTextures
,
376 std::move(aWidget
), &task
, aSize
, aWindowKind
, &syncHandle
, &aError
);
377 RenderThread::Get()->RunEvent(aWindowId
, std::move(event
));
385 return RefPtr
<WebRenderAPI
>(
386 new WebRenderAPI(docHandle
, aWindowId
, backend
, compositor
,
387 maxTextureSize
, useANGLE
, useDComp
,
389 supportsExternalBufferTextures
, syncHandle
))
393 already_AddRefed
<WebRenderAPI
> WebRenderAPI::Clone() {
394 wr::DocumentHandle
* docHandle
= nullptr;
395 wr_api_clone(mDocHandle
, &docHandle
);
397 RefPtr
<WebRenderAPI
> renderApi
=
398 new WebRenderAPI(docHandle
, mId
, mBackend
, mCompositor
, mMaxTextureSize
,
399 mUseANGLE
, mUseDComp
, mUseTripleBuffering
,
400 mSupportsExternalBufferTextures
, mSyncHandle
);
401 renderApi
->mRootApi
= this; // Hold root api
402 renderApi
->mRootDocumentApi
= this;
404 return renderApi
.forget();
407 wr::WrIdNamespace
WebRenderAPI::GetNamespace() {
408 return wr_api_get_namespace(mDocHandle
);
411 WebRenderAPI::WebRenderAPI(wr::DocumentHandle
* aHandle
, wr::WindowId aId
,
412 WebRenderBackend aBackend
,
413 WebRenderCompositor aCompositor
,
414 uint32_t aMaxTextureSize
, bool aUseANGLE
,
415 bool aUseDComp
, bool aUseTripleBuffering
,
416 bool aSupportsExternalBufferTextures
,
417 layers::SyncHandle aSyncHandle
)
418 : mDocHandle(aHandle
),
421 mCompositor(aCompositor
),
422 mMaxTextureSize(aMaxTextureSize
),
423 mUseANGLE(aUseANGLE
),
424 mUseDComp(aUseDComp
),
425 mUseTripleBuffering(aUseTripleBuffering
),
426 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures
),
427 mCaptureSequence(false),
428 mSyncHandle(aSyncHandle
),
429 mRendererDestroyed(false) {}
431 WebRenderAPI::~WebRenderAPI() {
432 if (!mRootDocumentApi
) {
433 wr_api_delete_document(mDocHandle
);
437 MOZ_RELEASE_ASSERT(mRendererDestroyed
);
438 wr_api_shut_down(mDocHandle
);
441 wr_api_delete(mDocHandle
);
444 void WebRenderAPI::DestroyRenderer() {
445 MOZ_RELEASE_ASSERT(!mRootApi
);
447 RenderThread::Get()->SetDestroyed(GetId());
448 // Call wr_api_stop_render_backend() before RemoveRenderer.
449 wr_api_stop_render_backend(mDocHandle
);
451 layers::SynchronousTask
task("Destroy WebRenderAPI");
452 auto event
= MakeUnique
<RemoveRenderer
>(&task
);
453 RunOnRenderThread(std::move(event
));
456 mRendererDestroyed
= true;
459 void WebRenderAPI::UpdateDebugFlags(uint32_t aFlags
) {
460 wr_api_set_debug_flags(mDocHandle
, wr::DebugFlags
{aFlags
});
463 void WebRenderAPI::SendTransaction(TransactionBuilder
& aTxn
) {
464 wr_api_send_transaction(mDocHandle
, aTxn
.Raw(), aTxn
.UseSceneBuilderThread());
467 SideBits
ExtractSideBitsFromHitInfoBits(uint16_t& aHitInfoBits
) {
468 SideBits sideBits
= SideBits::eNone
;
469 if (aHitInfoBits
& eSideBitsPackedTop
) {
470 sideBits
|= SideBits::eTop
;
472 if (aHitInfoBits
& eSideBitsPackedRight
) {
473 sideBits
|= SideBits::eRight
;
475 if (aHitInfoBits
& eSideBitsPackedBottom
) {
476 sideBits
|= SideBits::eBottom
;
478 if (aHitInfoBits
& eSideBitsPackedLeft
) {
479 sideBits
|= SideBits::eLeft
;
482 aHitInfoBits
&= 0x0fff;
486 std::vector
<WrHitResult
> WebRenderAPI::HitTest(const wr::WorldPoint
& aPoint
) {
487 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits
<12>(),
488 "CompositorHitTestFlags MAX value has to be less than number "
489 "of bits in uint16_t minus 4 for SideBitsPacked");
491 nsTArray
<wr::HitResult
> wrResults
;
492 wr_api_hit_test(mDocHandle
, aPoint
, &wrResults
);
494 std::vector
<WrHitResult
> geckoResults
;
495 for (wr::HitResult wrResult
: wrResults
) {
496 WrHitResult geckoResult
;
497 geckoResult
.mLayersId
= wr::AsLayersId(wrResult
.pipeline_id
);
498 geckoResult
.mScrollId
=
499 static_cast<layers::ScrollableLayerGuid::ViewID
>(wrResult
.scroll_id
);
500 geckoResult
.mSideBits
= ExtractSideBitsFromHitInfoBits(wrResult
.hit_info
);
501 geckoResult
.mHitInfo
.deserialize(wrResult
.hit_info
);
502 geckoResults
.push_back(geckoResult
);
507 void WebRenderAPI::Readback(const TimeStamp
& aStartTime
, gfx::IntSize size
,
508 const gfx::SurfaceFormat
& aFormat
,
509 const Range
<uint8_t>& buffer
, bool* aNeedsYFlip
) {
510 class Readback
: public RendererEvent
{
512 explicit Readback(layers::SynchronousTask
* aTask
, TimeStamp aStartTime
,
513 gfx::IntSize aSize
, const gfx::SurfaceFormat
& aFormat
,
514 const Range
<uint8_t>& aBuffer
, bool* aNeedsYFlip
)
516 mStartTime(aStartTime
),
520 mNeedsYFlip(aNeedsYFlip
) {
521 MOZ_COUNT_CTOR(Readback
);
524 MOZ_COUNTED_DTOR_OVERRIDE(Readback
)
526 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
527 aRenderThread
.UpdateAndRender(aWindowId
, VsyncId(), mStartTime
,
528 /* aRender */ true, Some(mSize
),
529 wr::SurfaceFormatToImageFormat(mFormat
),
530 Some(mBuffer
), mNeedsYFlip
);
531 layers::AutoCompleteTask
complete(mTask
);
534 layers::SynchronousTask
* mTask
;
535 TimeStamp mStartTime
;
537 gfx::SurfaceFormat mFormat
;
538 const Range
<uint8_t>& mBuffer
;
542 // Disable debug flags during readback. See bug 1436020.
545 layers::SynchronousTask
task("Readback");
546 auto event
= MakeUnique
<Readback
>(&task
, aStartTime
, size
, aFormat
, buffer
,
548 // This event will be passed from wr_backend thread to renderer thread. That
549 // implies that all frame data have been processed when the renderer runs this
550 // read-back event. Then, we could make sure this read-back event gets the
552 RunOnRenderThread(std::move(event
));
556 UpdateDebugFlags(gfx::gfxVars::WebRenderDebugFlags());
559 void WebRenderAPI::ClearAllCaches() { wr_api_clear_all_caches(mDocHandle
); }
561 void WebRenderAPI::EnableNativeCompositor(bool aEnable
) {
562 wr_api_enable_native_compositor(mDocHandle
, aEnable
);
565 void WebRenderAPI::EnableMultithreading(bool aEnable
) {
566 wr_api_enable_multithreading(mDocHandle
, aEnable
);
569 void WebRenderAPI::SetBatchingLookback(uint32_t aCount
) {
570 wr_api_set_batching_lookback(mDocHandle
, aCount
);
573 void WebRenderAPI::SetClearColor(const gfx::DeviceColor
& aColor
) {
574 RenderThread::Get()->SetClearColor(mId
, ToColorF(aColor
));
577 void WebRenderAPI::SetProfilerUI(const nsCString
& aUIString
) {
578 RenderThread::Get()->SetProfilerUI(mId
, aUIString
);
581 void WebRenderAPI::Pause() {
582 class PauseEvent
: public RendererEvent
{
584 explicit PauseEvent(layers::SynchronousTask
* aTask
) : mTask(aTask
) {
585 MOZ_COUNT_CTOR(PauseEvent
);
588 MOZ_COUNTED_DTOR_OVERRIDE(PauseEvent
)
590 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
591 aRenderThread
.Pause(aWindowId
);
592 layers::AutoCompleteTask
complete(mTask
);
595 layers::SynchronousTask
* mTask
;
598 layers::SynchronousTask
task("Pause");
599 auto event
= MakeUnique
<PauseEvent
>(&task
);
600 // This event will be passed from wr_backend thread to renderer thread. That
601 // implies that all frame data have been processed when the renderer runs this
603 RunOnRenderThread(std::move(event
));
608 bool WebRenderAPI::Resume() {
609 class ResumeEvent
: public RendererEvent
{
611 explicit ResumeEvent(layers::SynchronousTask
* aTask
, bool* aResult
)
612 : mTask(aTask
), mResult(aResult
) {
613 MOZ_COUNT_CTOR(ResumeEvent
);
616 MOZ_COUNTED_DTOR_OVERRIDE(ResumeEvent
)
618 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
619 *mResult
= aRenderThread
.Resume(aWindowId
);
620 layers::AutoCompleteTask
complete(mTask
);
623 layers::SynchronousTask
* mTask
;
628 layers::SynchronousTask
task("Resume");
629 auto event
= MakeUnique
<ResumeEvent
>(&task
, &result
);
630 // This event will be passed from wr_backend thread to renderer thread. That
631 // implies that all frame data have been processed when the renderer runs this
633 RunOnRenderThread(std::move(event
));
639 void WebRenderAPI::NotifyMemoryPressure() {
640 wr_api_notify_memory_pressure(mDocHandle
);
643 void WebRenderAPI::AccumulateMemoryReport(MemoryReport
* aReport
) {
644 wr_api_accumulate_memory_report(mDocHandle
, aReport
, &WebRenderMallocSizeOf
,
645 &WebRenderMallocEnclosingSizeOf
);
648 void WebRenderAPI::WakeSceneBuilder() { wr_api_wake_scene_builder(mDocHandle
); }
650 void WebRenderAPI::FlushSceneBuilder() {
651 wr_api_flush_scene_builder(mDocHandle
);
654 void WebRenderAPI::WaitFlushed() {
655 class WaitFlushedEvent
: public RendererEvent
{
657 explicit WaitFlushedEvent(layers::SynchronousTask
* aTask
) : mTask(aTask
) {
658 MOZ_COUNT_CTOR(WaitFlushedEvent
);
661 MOZ_COUNTED_DTOR_OVERRIDE(WaitFlushedEvent
)
663 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
664 layers::AutoCompleteTask
complete(mTask
);
667 layers::SynchronousTask
* mTask
;
670 layers::SynchronousTask
task("WaitFlushed");
671 auto event
= MakeUnique
<WaitFlushedEvent
>(&task
);
672 // This event will be passed from wr_backend thread to renderer thread. That
673 // implies that all frame data have been processed when the renderer runs this
675 RunOnRenderThread(std::move(event
));
680 void WebRenderAPI::Capture() {
682 // SCENE | FRAME | TILE_CACHE
683 uint8_t bits
= 15; // TODO: get from JavaScript
684 const char* path
= "wr-capture"; // TODO: get from JavaScript
685 wr_api_capture(mDocHandle
, path
, bits
);
688 void WebRenderAPI::StartCaptureSequence(const nsCString
& aPath
,
690 if (mCaptureSequence
) {
691 wr_api_stop_capture_sequence(mDocHandle
);
694 wr_api_start_capture_sequence(mDocHandle
, PromiseFlatCString(aPath
).get(),
697 mCaptureSequence
= true;
700 void WebRenderAPI::StopCaptureSequence() {
701 if (mCaptureSequence
) {
702 wr_api_stop_capture_sequence(mDocHandle
);
705 mCaptureSequence
= false;
708 void WebRenderAPI::BeginRecording(const TimeStamp
& aRecordingStart
,
709 wr::PipelineId aRootPipelineId
) {
710 class BeginRecordingEvent final
: public RendererEvent
{
712 explicit BeginRecordingEvent(const TimeStamp
& aRecordingStart
,
713 wr::PipelineId aRootPipelineId
)
714 : mRecordingStart(aRecordingStart
), mRootPipelineId(aRootPipelineId
) {
715 MOZ_COUNT_CTOR(BeginRecordingEvent
);
718 ~BeginRecordingEvent() { MOZ_COUNT_DTOR(BeginRecordingEvent
); }
720 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
721 aRenderThread
.BeginRecordingForWindow(aWindowId
, mRecordingStart
,
726 TimeStamp mRecordingStart
;
727 wr::PipelineId mRootPipelineId
;
731 MakeUnique
<BeginRecordingEvent
>(aRecordingStart
, aRootPipelineId
);
732 RunOnRenderThread(std::move(event
));
735 RefPtr
<WebRenderAPI::WriteCollectedFramesPromise
>
736 WebRenderAPI::WriteCollectedFrames() {
737 class WriteCollectedFramesEvent final
: public RendererEvent
{
739 explicit WriteCollectedFramesEvent() {
740 MOZ_COUNT_CTOR(WriteCollectedFramesEvent
);
743 MOZ_COUNTED_DTOR(WriteCollectedFramesEvent
)
745 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
746 aRenderThread
.WriteCollectedFramesForWindow(aWindowId
);
747 mPromise
.Resolve(true, __func__
);
750 RefPtr
<WebRenderAPI::WriteCollectedFramesPromise
> GetPromise() {
751 return mPromise
.Ensure(__func__
);
755 MozPromiseHolder
<WebRenderAPI::WriteCollectedFramesPromise
> mPromise
;
758 auto event
= MakeUnique
<WriteCollectedFramesEvent
>();
759 auto promise
= event
->GetPromise();
761 RunOnRenderThread(std::move(event
));
765 RefPtr
<WebRenderAPI::GetCollectedFramesPromise
>
766 WebRenderAPI::GetCollectedFrames() {
767 class GetCollectedFramesEvent final
: public RendererEvent
{
769 explicit GetCollectedFramesEvent() {
770 MOZ_COUNT_CTOR(GetCollectedFramesEvent
);
773 MOZ_COUNTED_DTOR(GetCollectedFramesEvent
);
775 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
776 Maybe
<layers::CollectedFrames
> frames
=
777 aRenderThread
.GetCollectedFramesForWindow(aWindowId
);
780 mPromise
.Resolve(std::move(*frames
), __func__
);
782 mPromise
.Reject(NS_ERROR_UNEXPECTED
, __func__
);
786 RefPtr
<WebRenderAPI::GetCollectedFramesPromise
> GetPromise() {
787 return mPromise
.Ensure(__func__
);
791 MozPromiseHolder
<WebRenderAPI::GetCollectedFramesPromise
> mPromise
;
794 auto event
= MakeUnique
<GetCollectedFramesEvent
>();
795 auto promise
= event
->GetPromise();
797 RunOnRenderThread(std::move(event
));
801 void TransactionBuilder::Clear() { wr_resource_updates_clear(mTxn
); }
803 void TransactionBuilder::Notify(wr::Checkpoint aWhen
,
804 UniquePtr
<NotificationHandler
> aEvent
) {
805 wr_transaction_notify(mTxn
, aWhen
,
806 reinterpret_cast<uintptr_t>(aEvent
.release()));
809 void TransactionBuilder::AddImage(ImageKey key
,
810 const ImageDescriptor
& aDescriptor
,
811 wr::Vec
<uint8_t>& aBytes
) {
812 wr_resource_updates_add_image(mTxn
, key
, &aDescriptor
, &aBytes
.inner
);
815 void TransactionBuilder::AddBlobImage(BlobImageKey key
,
816 const ImageDescriptor
& aDescriptor
,
817 wr::Vec
<uint8_t>& aBytes
,
818 const wr::DeviceIntRect
& aVisibleRect
) {
819 wr_resource_updates_add_blob_image(mTxn
, key
, &aDescriptor
, &aBytes
.inner
,
823 void TransactionBuilder::AddExternalImage(ImageKey key
,
824 const ImageDescriptor
& aDescriptor
,
825 ExternalImageId aExtID
,
826 wr::ExternalImageType aImageType
,
827 uint8_t aChannelIndex
) {
828 wr_resource_updates_add_external_image(mTxn
, key
, &aDescriptor
, aExtID
,
829 &aImageType
, aChannelIndex
);
832 void TransactionBuilder::AddExternalImageBuffer(
833 ImageKey aKey
, const ImageDescriptor
& aDescriptor
,
834 ExternalImageId aHandle
) {
835 auto channelIndex
= 0;
836 AddExternalImage(aKey
, aDescriptor
, aHandle
, wr::ExternalImageType::Buffer(),
840 void TransactionBuilder::UpdateImageBuffer(ImageKey aKey
,
841 const ImageDescriptor
& aDescriptor
,
842 wr::Vec
<uint8_t>& aBytes
) {
843 wr_resource_updates_update_image(mTxn
, aKey
, &aDescriptor
, &aBytes
.inner
);
846 void TransactionBuilder::UpdateBlobImage(BlobImageKey aKey
,
847 const ImageDescriptor
& aDescriptor
,
848 wr::Vec
<uint8_t>& aBytes
,
849 const wr::DeviceIntRect
& aVisibleRect
,
850 const wr::LayoutIntRect
& aDirtyRect
) {
851 wr_resource_updates_update_blob_image(mTxn
, aKey
, &aDescriptor
, &aBytes
.inner
,
852 aVisibleRect
, aDirtyRect
);
855 void TransactionBuilder::UpdateExternalImage(ImageKey aKey
,
856 const ImageDescriptor
& aDescriptor
,
857 ExternalImageId aExtID
,
858 wr::ExternalImageType aImageType
,
859 uint8_t aChannelIndex
) {
860 wr_resource_updates_update_external_image(mTxn
, aKey
, &aDescriptor
, aExtID
,
861 &aImageType
, aChannelIndex
);
864 void TransactionBuilder::UpdateExternalImageWithDirtyRect(
865 ImageKey aKey
, const ImageDescriptor
& aDescriptor
, ExternalImageId aExtID
,
866 wr::ExternalImageType aImageType
, const wr::DeviceIntRect
& aDirtyRect
,
867 uint8_t aChannelIndex
) {
868 wr_resource_updates_update_external_image_with_dirty_rect(
869 mTxn
, aKey
, &aDescriptor
, aExtID
, &aImageType
, aChannelIndex
, aDirtyRect
);
872 void TransactionBuilder::SetBlobImageVisibleArea(
873 BlobImageKey aKey
, const wr::DeviceIntRect
& aArea
) {
874 wr_resource_updates_set_blob_image_visible_area(mTxn
, aKey
, &aArea
);
877 void TransactionBuilder::DeleteImage(ImageKey aKey
) {
878 wr_resource_updates_delete_image(mTxn
, aKey
);
881 void TransactionBuilder::DeleteBlobImage(BlobImageKey aKey
) {
882 wr_resource_updates_delete_blob_image(mTxn
, aKey
);
885 void TransactionBuilder::AddRawFont(wr::FontKey aKey
, wr::Vec
<uint8_t>& aBytes
,
887 wr_resource_updates_add_raw_font(mTxn
, aKey
, &aBytes
.inner
, aIndex
);
890 void TransactionBuilder::AddFontDescriptor(wr::FontKey aKey
,
891 wr::Vec
<uint8_t>& aBytes
,
893 wr_resource_updates_add_font_descriptor(mTxn
, aKey
, &aBytes
.inner
, aIndex
);
896 void TransactionBuilder::DeleteFont(wr::FontKey aKey
) {
897 wr_resource_updates_delete_font(mTxn
, aKey
);
900 void TransactionBuilder::AddFontInstance(
901 wr::FontInstanceKey aKey
, wr::FontKey aFontKey
, float aGlyphSize
,
902 const wr::FontInstanceOptions
* aOptions
,
903 const wr::FontInstancePlatformOptions
* aPlatformOptions
,
904 wr::Vec
<uint8_t>& aVariations
) {
905 wr_resource_updates_add_font_instance(mTxn
, aKey
, aFontKey
, aGlyphSize
,
906 aOptions
, aPlatformOptions
,
910 void TransactionBuilder::DeleteFontInstance(wr::FontInstanceKey aKey
) {
911 wr_resource_updates_delete_font_instance(mTxn
, aKey
);
914 void TransactionBuilder::UpdateQualitySettings(
915 bool aForceSubpixelAAWherePossible
) {
916 wr_transaction_set_quality_settings(mTxn
, aForceSubpixelAAWherePossible
);
919 class FrameStartTime
: public RendererEvent
{
921 explicit FrameStartTime(const TimeStamp
& aTime
) : mTime(aTime
) {
922 MOZ_COUNT_CTOR(FrameStartTime
);
925 MOZ_COUNTED_DTOR_OVERRIDE(FrameStartTime
)
927 void Run(RenderThread
& aRenderThread
, WindowId aWindowId
) override
{
928 auto renderer
= aRenderThread
.GetRenderer(aWindowId
);
930 renderer
->SetFrameStartTime(mTime
);
938 void WebRenderAPI::SetFrameStartTime(const TimeStamp
& aTime
) {
939 auto event
= MakeUnique
<FrameStartTime
>(aTime
);
940 RunOnRenderThread(std::move(event
));
943 void WebRenderAPI::RunOnRenderThread(UniquePtr
<RendererEvent
> aEvent
) {
944 auto event
= reinterpret_cast<uintptr_t>(aEvent
.release());
945 wr_api_send_external_event(mDocHandle
, event
);
948 DisplayListBuilder::DisplayListBuilder(PipelineId aId
,
949 WebRenderBackend aBackend
,
951 layers::DisplayItemCache
* aCache
)
952 : mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
953 mActiveFixedPosTracker(nullptr),
956 mDisplayItemCache(aCache
) {
957 MOZ_COUNT_CTOR(DisplayListBuilder
);
958 mWrState
= wr_state_new(aId
, aCapacity
);
960 if (mDisplayItemCache
&& mDisplayItemCache
->IsEnabled()) {
961 mDisplayItemCache
->SetPipelineId(aId
);
965 DisplayListBuilder::~DisplayListBuilder() {
966 MOZ_COUNT_DTOR(DisplayListBuilder
);
967 wr_state_delete(mWrState
);
970 void DisplayListBuilder::Save() { wr_dp_save(mWrState
); }
971 void DisplayListBuilder::Restore() { wr_dp_restore(mWrState
); }
972 void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState
); }
974 usize
DisplayListBuilder::Dump(usize aIndent
, const Maybe
<usize
>& aStart
,
975 const Maybe
<usize
>& aEnd
) {
976 return wr_dump_display_list(mWrState
, aIndent
, aStart
.ptrOr(nullptr),
977 aEnd
.ptrOr(nullptr));
980 void DisplayListBuilder::DumpSerializedDisplayList() {
981 wr_dump_serialized_display_list(mWrState
);
984 void DisplayListBuilder::Finalize(BuiltDisplayList
& aOutDisplayList
) {
985 wr_api_finalize_builder(mWrState
, &aOutDisplayList
.dl_desc
,
986 &aOutDisplayList
.dl
.inner
);
989 void DisplayListBuilder::Finalize(layers::DisplayListData
& aOutTransaction
) {
990 if (mDisplayItemCache
&& mDisplayItemCache
->IsEnabled()) {
991 wr_dp_set_cache_size(mWrState
, mDisplayItemCache
->CurrentSize());
995 wr_api_finalize_builder(mWrState
, &aOutTransaction
.mDLDesc
, &dl
.inner
);
996 aOutTransaction
.mDL
.emplace(dl
.inner
.data
, dl
.inner
.length
,
998 aOutTransaction
.mRemotePipelineIds
= std::move(mRemotePipelineIds
);
999 dl
.inner
.capacity
= 0;
1000 dl
.inner
.data
= nullptr;
1003 Maybe
<wr::WrSpatialId
> DisplayListBuilder::PushStackingContext(
1004 const wr::StackingContextParams
& aParams
, const wr::LayoutRect
& aBounds
,
1005 const wr::RasterSpace
& aRasterSpace
) {
1006 MOZ_ASSERT(mClipChainLeaf
.isNothing(),
1007 "Non-empty leaf from clip chain given, but not used with SC!");
1009 wr::LayoutTransform matrix
;
1010 const gfx::Matrix4x4
* transform
= aParams
.mTransformPtr
;
1012 matrix
= ToLayoutTransform(*transform
);
1014 const wr::LayoutTransform
* maybeTransform
= transform
? &matrix
: nullptr;
1015 WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState
,
1016 ToString(aBounds
).c_str(),
1017 transform
? ToString(*transform
).c_str() : "none");
1019 auto spatialId
= wr_dp_push_stacking_context(
1020 mWrState
, aBounds
, mCurrentSpaceAndClipChain
.space
, &aParams
,
1021 maybeTransform
, aParams
.mFilters
.Elements(), aParams
.mFilters
.Length(),
1022 aParams
.mFilterDatas
.Elements(), aParams
.mFilterDatas
.Length(),
1025 return spatialId
.id
!= 0 ? Some(spatialId
) : Nothing();
1028 void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame
) {
1029 WRDL_LOG("PopStackingContext\n", mWrState
);
1030 wr_dp_pop_stacking_context(mWrState
, aIsReferenceFrame
);
1033 wr::WrClipChainId
DisplayListBuilder::DefineClipChain(
1034 const nsTArray
<wr::WrClipId
>& aClips
, bool aParentWithCurrentChain
) {
1037 const uint64_t* parent
= nullptr;
1038 if (aParentWithCurrentChain
&&
1039 mCurrentSpaceAndClipChain
.clip_chain
!= wr::ROOT_CLIP_CHAIN
) {
1040 parent
= &mCurrentSpaceAndClipChain
.clip_chain
;
1042 uint64_t clipchainId
= wr_dp_define_clipchain(
1043 mWrState
, parent
, aClips
.Elements(), aClips
.Length());
1044 WRDL_LOG("DefineClipChain id=%" PRIu64
" clips=%zu\n", mWrState
, clipchainId
,
1046 return wr::WrClipChainId
{clipchainId
};
1049 wr::WrClipId
DisplayListBuilder::DefineClip(
1050 const Maybe
<wr::WrSpaceAndClip
>& aParent
, const wr::LayoutRect
& aClipRect
,
1051 const nsTArray
<wr::ComplexClipRegion
>* aComplex
) {
1056 clipId
= wr_dp_define_clip_with_parent_clip(
1057 mWrState
, aParent
.ptr(), aClipRect
,
1058 aComplex
? aComplex
->Elements() : nullptr,
1059 aComplex
? aComplex
->Length() : 0);
1061 clipId
= wr_dp_define_clip_with_parent_clip_chain(
1062 mWrState
, &mCurrentSpaceAndClipChain
, aClipRect
,
1063 aComplex
? aComplex
->Elements() : nullptr,
1064 aComplex
? aComplex
->Length() : 0);
1067 WRDL_LOG("DefineClip id=%zu p=%s r=%s complex=%zu\n", mWrState
, clipId
.id
,
1068 aParent
? ToString(aParent
->clip
.id
).c_str() : "(nil)",
1069 ToString(aClipRect
).c_str(), aComplex
? aComplex
->Length() : 0);
1074 wr::WrClipId
DisplayListBuilder::DefineImageMaskClip(
1075 const wr::ImageMask
& aMask
, const nsTArray
<wr::LayoutPoint
>& aPoints
,
1076 wr::FillRule aFillRule
) {
1079 WrClipId clipId
= wr_dp_define_image_mask_clip_with_parent_clip_chain(
1080 mWrState
, &mCurrentSpaceAndClipChain
, aMask
, aPoints
.Elements(),
1081 aPoints
.Length(), aFillRule
);
1086 wr::WrClipId
DisplayListBuilder::DefineRoundedRectClip(
1087 const wr::ComplexClipRegion
& aComplex
) {
1090 WrClipId clipId
= wr_dp_define_rounded_rect_clip_with_parent_clip_chain(
1091 mWrState
, &mCurrentSpaceAndClipChain
, aComplex
);
1096 wr::WrClipId
DisplayListBuilder::DefineRectClip(wr::LayoutRect aClipRect
) {
1099 WrClipId clipId
= wr_dp_define_rect_clip_with_parent_clip_chain(
1100 mWrState
, &mCurrentSpaceAndClipChain
, aClipRect
);
1105 wr::WrSpatialId
DisplayListBuilder::DefineStickyFrame(
1106 const wr::LayoutRect
& aContentRect
, const float* aTopMargin
,
1107 const float* aRightMargin
, const float* aBottomMargin
,
1108 const float* aLeftMargin
, const StickyOffsetBounds
& aVerticalBounds
,
1109 const StickyOffsetBounds
& aHorizontalBounds
,
1110 const wr::LayoutVector2D
& aAppliedOffset
) {
1111 auto spatialId
= wr_dp_define_sticky_frame(
1112 mWrState
, mCurrentSpaceAndClipChain
.space
, aContentRect
, aTopMargin
,
1113 aRightMargin
, aBottomMargin
, aLeftMargin
, aVerticalBounds
,
1114 aHorizontalBounds
, aAppliedOffset
);
1116 WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n",
1117 mWrState
, spatialId
.id
, ToString(aContentRect
).c_str(),
1118 aTopMargin
? ToString(*aTopMargin
).c_str() : "none",
1119 aRightMargin
? ToString(*aRightMargin
).c_str() : "none",
1120 aBottomMargin
? ToString(*aBottomMargin
).c_str() : "none",
1121 aLeftMargin
? ToString(*aLeftMargin
).c_str() : "none",
1122 ToString(aVerticalBounds
).c_str(),
1123 ToString(aHorizontalBounds
).c_str(),
1124 ToString(aAppliedOffset
).c_str());
1129 Maybe
<wr::WrSpaceAndClip
> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
1130 layers::ScrollableLayerGuid::ViewID aViewId
) const {
1131 if (aViewId
== layers::ScrollableLayerGuid::NULL_SCROLL_ID
) {
1132 return Some(wr::RootScrollNode());
1135 auto it
= mScrollIds
.find(aViewId
);
1136 if (it
== mScrollIds
.end()) {
1140 return Some(it
->second
);
1143 wr::WrSpaceAndClip
DisplayListBuilder::DefineScrollLayer(
1144 const layers::ScrollableLayerGuid::ViewID
& aViewId
,
1145 const Maybe
<wr::WrSpaceAndClip
>& aParent
,
1146 const wr::LayoutRect
& aContentRect
, const wr::LayoutRect
& aClipRect
,
1147 const wr::LayoutPoint
& aScrollOffset
) {
1148 auto it
= mScrollIds
.find(aViewId
);
1149 if (it
!= mScrollIds
.end()) {
1153 // We haven't defined aViewId before, so let's define it now.
1154 wr::WrSpaceAndClip defaultParent
= wr::RootScrollNode();
1155 // Note: we are currently ignoring the clipId on the stack here
1156 defaultParent
.space
= mCurrentSpaceAndClipChain
.space
;
1158 auto spaceAndClip
= wr_dp_define_scroll_layer(
1159 mWrState
, aViewId
, aParent
? aParent
.ptr() : &defaultParent
, aContentRect
,
1160 aClipRect
, aScrollOffset
);
1162 WRDL_LOG("DefineScrollLayer id=%" PRIu64
"/%zu p=%s co=%s cl=%s\n", mWrState
,
1163 aViewId
, spaceAndClip
.space
.id
,
1164 aParent
? ToString(aParent
->space
.id
).c_str() : "(nil)",
1165 ToString(aContentRect
).c_str(), ToString(aClipRect
).c_str());
1167 mScrollIds
[aViewId
] = spaceAndClip
;
1168 return spaceAndClip
;
1171 void DisplayListBuilder::PushRect(const wr::LayoutRect
& aBounds
,
1172 const wr::LayoutRect
& aClip
,
1173 bool aIsBackfaceVisible
,
1174 const wr::ColorF
& aColor
) {
1175 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1176 WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState
, ToString(aBounds
).c_str(),
1177 ToString(clip
).c_str(), ToString(aColor
).c_str());
1178 wr_dp_push_rect(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1179 &mCurrentSpaceAndClipChain
, aColor
);
1182 void DisplayListBuilder::PushRoundedRect(const wr::LayoutRect
& aBounds
,
1183 const wr::LayoutRect
& aClip
,
1184 bool aIsBackfaceVisible
,
1185 const wr::ColorF
& aColor
) {
1186 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1187 WRDL_LOG("PushRoundedRect b=%s cl=%s c=%s\n", mWrState
,
1188 ToString(aBounds
).c_str(), ToString(clip
).c_str(),
1189 ToString(aColor
).c_str());
1191 // Draw the rounded rectangle as a border with rounded corners. We could also
1192 // draw this as a rectangle clipped to a rounded rectangle, but:
1193 // - clips are not cached; borders are
1194 // - a simple border like this will be drawn as an image
1195 // - Processing lots of clips is not WebRender's strong point.
1197 // Made the borders thicker than one half the width/height, to avoid
1198 // little white dots at the center at some magnifications.
1199 wr::BorderSide side
= {aColor
, wr::BorderStyle::Solid
};
1200 float h
= aBounds
.size
.width
* 0.6f
;
1201 float v
= aBounds
.size
.height
* 0.6f
;
1202 wr::LayoutSideOffsets widths
= {v
, h
, v
, h
};
1203 wr::BorderRadius radii
= {{h
, v
}, {h
, v
}, {h
, v
}, {h
, v
}};
1205 // Anti-aliased borders are required for rounded borders.
1206 wr_dp_push_border(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1207 &mCurrentSpaceAndClipChain
, wr::AntialiasBorder::Yes
,
1208 widths
, side
, side
, side
, side
, radii
);
1211 void DisplayListBuilder::PushHitTest(
1212 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1213 bool aIsBackfaceVisible
,
1214 const layers::ScrollableLayerGuid::ViewID
& aScrollId
,
1215 gfx::CompositorHitTestInfo aHitInfo
, SideBits aSideBits
) {
1216 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1217 WRDL_LOG("PushHitTest b=%s cl=%s\n", mWrState
, ToString(aBounds
).c_str(),
1218 ToString(clip
).c_str());
1220 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits
<12>(),
1221 "CompositorHitTestFlags MAX value has to be less than number "
1222 "of bits in uint16_t minus 4 for SideBitsPacked");
1224 uint16_t hitInfoBits
= static_cast<uint16_t>(aHitInfo
.serialize()) |
1225 SideBitsToHitInfoBits(aSideBits
);
1227 wr_dp_push_hit_test(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1228 &mCurrentSpaceAndClipChain
, aScrollId
, hitInfoBits
);
1231 void DisplayListBuilder::PushRectWithAnimation(
1232 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1233 bool aIsBackfaceVisible
, const wr::ColorF
& aColor
,
1234 const WrAnimationProperty
* aAnimation
) {
1235 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1236 WRDL_LOG("PushRectWithAnimation b=%s cl=%s c=%s\n", mWrState
,
1237 ToString(aBounds
).c_str(), ToString(clip
).c_str(),
1238 ToString(aColor
).c_str());
1240 wr_dp_push_rect_with_animation(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1241 &mCurrentSpaceAndClipChain
, aColor
,
1245 void DisplayListBuilder::PushClearRect(const wr::LayoutRect
& aBounds
) {
1246 wr::LayoutRect clip
= MergeClipLeaf(aBounds
);
1247 WRDL_LOG("PushClearRect b=%s c=%s\n", mWrState
, ToString(aBounds
).c_str(),
1248 ToString(clip
).c_str());
1249 wr_dp_push_clear_rect(mWrState
, aBounds
, clip
, &mCurrentSpaceAndClipChain
);
1252 void DisplayListBuilder::PushClearRectWithComplexRegion(
1253 const wr::LayoutRect
& aBounds
, const wr::ComplexClipRegion
& aRegion
) {
1254 wr::LayoutRect clip
= MergeClipLeaf(aBounds
);
1255 WRDL_LOG("PushClearRectWithComplexRegion b=%s c=%s\n", mWrState
,
1256 ToString(aBounds
).c_str(), ToString(clip
).c_str());
1258 // TODO(gw): This doesn't pass the complex region through to WR, as clear
1259 // rects with complex clips are currently broken. This is the
1260 // only place they are used, and they are used only for a single
1261 // case (close buttons on Win7 machines). We might be able to
1262 // get away with not supporting this at all in WR, using the
1263 // non-clipped clear rect is an improvement for now, at least.
1264 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1636683 for
1265 // more information.
1266 AutoTArray
<wr::ComplexClipRegion
, 1> clips
;
1267 auto clipId
= DefineClip(Nothing(), aBounds
, &clips
);
1268 auto spaceAndClip
= WrSpaceAndClip
{mCurrentSpaceAndClipChain
.space
, clipId
};
1270 wr_dp_push_clear_rect_with_parent_clip(mWrState
, aBounds
, clip
,
1274 void DisplayListBuilder::PushBackdropFilter(
1275 const wr::LayoutRect
& aBounds
, const wr::ComplexClipRegion
& aRegion
,
1276 const nsTArray
<wr::FilterOp
>& aFilters
,
1277 const nsTArray
<wr::WrFilterData
>& aFilterDatas
, bool aIsBackfaceVisible
) {
1278 wr::LayoutRect clip
= MergeClipLeaf(aBounds
);
1279 WRDL_LOG("PushBackdropFilter b=%s c=%s\n", mWrState
,
1280 ToString(aBounds
).c_str(), ToString(clip
).c_str());
1282 AutoTArray
<wr::ComplexClipRegion
, 1> clips
;
1283 clips
.AppendElement(aRegion
);
1284 auto clipId
= DefineClip(Nothing(), aBounds
, &clips
);
1285 auto spaceAndClip
= WrSpaceAndClip
{mCurrentSpaceAndClipChain
.space
, clipId
};
1287 wr_dp_push_backdrop_filter_with_parent_clip(
1288 mWrState
, aBounds
, clip
, aIsBackfaceVisible
, &spaceAndClip
,
1289 aFilters
.Elements(), aFilters
.Length(), aFilterDatas
.Elements(),
1290 aFilterDatas
.Length());
1293 void DisplayListBuilder::PushLinearGradient(
1294 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1295 bool aIsBackfaceVisible
, const wr::LayoutPoint
& aStartPoint
,
1296 const wr::LayoutPoint
& aEndPoint
, const nsTArray
<wr::GradientStop
>& aStops
,
1297 wr::ExtendMode aExtendMode
, const wr::LayoutSize aTileSize
,
1298 const wr::LayoutSize aTileSpacing
) {
1299 wr_dp_push_linear_gradient(
1300 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1301 &mCurrentSpaceAndClipChain
, aStartPoint
, aEndPoint
, aStops
.Elements(),
1302 aStops
.Length(), aExtendMode
, aTileSize
, aTileSpacing
);
1305 void DisplayListBuilder::PushRadialGradient(
1306 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1307 bool aIsBackfaceVisible
, const wr::LayoutPoint
& aCenter
,
1308 const wr::LayoutSize
& aRadius
, const nsTArray
<wr::GradientStop
>& aStops
,
1309 wr::ExtendMode aExtendMode
, const wr::LayoutSize aTileSize
,
1310 const wr::LayoutSize aTileSpacing
) {
1311 wr_dp_push_radial_gradient(
1312 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1313 &mCurrentSpaceAndClipChain
, aCenter
, aRadius
, aStops
.Elements(),
1314 aStops
.Length(), aExtendMode
, aTileSize
, aTileSpacing
);
1317 void DisplayListBuilder::PushConicGradient(
1318 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1319 bool aIsBackfaceVisible
, const wr::LayoutPoint
& aCenter
, const float aAngle
,
1320 const nsTArray
<wr::GradientStop
>& aStops
, wr::ExtendMode aExtendMode
,
1321 const wr::LayoutSize aTileSize
, const wr::LayoutSize aTileSpacing
) {
1322 wr_dp_push_conic_gradient(mWrState
, aBounds
, MergeClipLeaf(aClip
),
1323 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1324 aCenter
, aAngle
, aStops
.Elements(), aStops
.Length(),
1325 aExtendMode
, aTileSize
, aTileSpacing
);
1328 void DisplayListBuilder::PushImage(
1329 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1330 bool aIsBackfaceVisible
, wr::ImageRendering aFilter
, wr::ImageKey aImage
,
1331 bool aPremultipliedAlpha
, const wr::ColorF
& aColor
,
1332 bool aPreferCompositorSurface
, bool aSupportsExternalCompositing
) {
1333 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1334 WRDL_LOG("PushImage b=%s cl=%s\n", mWrState
, ToString(aBounds
).c_str(),
1335 ToString(clip
).c_str());
1336 wr_dp_push_image(mWrState
, aBounds
, clip
, aIsBackfaceVisible
,
1337 &mCurrentSpaceAndClipChain
, aFilter
, aImage
,
1338 aPremultipliedAlpha
, aColor
, aPreferCompositorSurface
,
1339 aSupportsExternalCompositing
);
1342 void DisplayListBuilder::PushRepeatingImage(
1343 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1344 bool aIsBackfaceVisible
, const wr::LayoutSize
& aStretchSize
,
1345 const wr::LayoutSize
& aTileSpacing
, wr::ImageRendering aFilter
,
1346 wr::ImageKey aImage
, bool aPremultipliedAlpha
, const wr::ColorF
& aColor
) {
1347 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1348 WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState
,
1349 ToString(aBounds
).c_str(), ToString(clip
).c_str(),
1350 ToString(aStretchSize
).c_str(), ToString(aTileSpacing
).c_str());
1351 wr_dp_push_repeating_image(
1352 mWrState
, aBounds
, clip
, aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1353 aStretchSize
, aTileSpacing
, aFilter
, aImage
, aPremultipliedAlpha
, aColor
);
1356 void DisplayListBuilder::PushYCbCrPlanarImage(
1357 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1358 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1359 wr::ImageKey aImageChannel1
, wr::ImageKey aImageChannel2
,
1360 wr::WrColorDepth aColorDepth
, wr::WrYuvColorSpace aColorSpace
,
1361 wr::WrColorRange aColorRange
, wr::ImageRendering aRendering
,
1362 bool aPreferCompositorSurface
, bool aSupportsExternalCompositing
) {
1363 wr_dp_push_yuv_planar_image(
1364 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1365 &mCurrentSpaceAndClipChain
, aImageChannel0
, aImageChannel1
,
1366 aImageChannel2
, aColorDepth
, aColorSpace
, aColorRange
, aRendering
,
1367 aPreferCompositorSurface
, aSupportsExternalCompositing
);
1370 void DisplayListBuilder::PushNV12Image(
1371 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1372 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1373 wr::ImageKey aImageChannel1
, wr::WrColorDepth aColorDepth
,
1374 wr::WrYuvColorSpace aColorSpace
, wr::WrColorRange aColorRange
,
1375 wr::ImageRendering aRendering
, bool aPreferCompositorSurface
,
1376 bool aSupportsExternalCompositing
) {
1377 wr_dp_push_yuv_NV12_image(
1378 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1379 &mCurrentSpaceAndClipChain
, aImageChannel0
, aImageChannel1
, aColorDepth
,
1380 aColorSpace
, aColorRange
, aRendering
, aPreferCompositorSurface
,
1381 aSupportsExternalCompositing
);
1384 void DisplayListBuilder::PushYCbCrInterleavedImage(
1385 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1386 bool aIsBackfaceVisible
, wr::ImageKey aImageChannel0
,
1387 wr::WrColorDepth aColorDepth
, wr::WrYuvColorSpace aColorSpace
,
1388 wr::WrColorRange aColorRange
, wr::ImageRendering aRendering
,
1389 bool aPreferCompositorSurface
, bool aSupportsExternalCompositing
) {
1390 wr_dp_push_yuv_interleaved_image(
1391 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1392 &mCurrentSpaceAndClipChain
, aImageChannel0
, aColorDepth
, aColorSpace
,
1393 aColorRange
, aRendering
, aPreferCompositorSurface
,
1394 aSupportsExternalCompositing
);
1397 void DisplayListBuilder::PushIFrame(const wr::LayoutRect
& aBounds
,
1398 bool aIsBackfaceVisible
,
1399 PipelineId aPipeline
,
1400 bool aIgnoreMissingPipeline
) {
1401 mRemotePipelineIds
.AppendElement(aPipeline
);
1402 wr_dp_push_iframe(mWrState
, aBounds
, MergeClipLeaf(aBounds
),
1403 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
, aPipeline
,
1404 aIgnoreMissingPipeline
);
1407 void DisplayListBuilder::PushBorder(const wr::LayoutRect
& aBounds
,
1408 const wr::LayoutRect
& aClip
,
1409 bool aIsBackfaceVisible
,
1410 const wr::LayoutSideOffsets
& aWidths
,
1411 const Range
<const wr::BorderSide
>& aSides
,
1412 const wr::BorderRadius
& aRadius
,
1413 wr::AntialiasBorder aAntialias
) {
1414 MOZ_ASSERT(aSides
.length() == 4);
1415 if (aSides
.length() != 4) {
1418 wr_dp_push_border(mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1419 &mCurrentSpaceAndClipChain
, aAntialias
, aWidths
, aSides
[0],
1420 aSides
[1], aSides
[2], aSides
[3], aRadius
);
1423 void DisplayListBuilder::PushBorderImage(const wr::LayoutRect
& aBounds
,
1424 const wr::LayoutRect
& aClip
,
1425 bool aIsBackfaceVisible
,
1426 const wr::WrBorderImage
& aParams
) {
1427 wr_dp_push_border_image(mWrState
, aBounds
, MergeClipLeaf(aClip
),
1428 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1432 void DisplayListBuilder::PushBorderGradient(
1433 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1434 bool aIsBackfaceVisible
, const wr::LayoutSideOffsets
& aWidths
,
1435 const int32_t aWidth
, const int32_t aHeight
, bool aFill
,
1436 const wr::DeviceIntSideOffsets
& aSlice
, const wr::LayoutPoint
& aStartPoint
,
1437 const wr::LayoutPoint
& aEndPoint
, const nsTArray
<wr::GradientStop
>& aStops
,
1438 wr::ExtendMode aExtendMode
, const wr::LayoutSideOffsets
& aOutset
) {
1439 wr_dp_push_border_gradient(mWrState
, aBounds
, MergeClipLeaf(aClip
),
1440 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1441 aWidths
, aWidth
, aHeight
, aFill
, aSlice
,
1442 aStartPoint
, aEndPoint
, aStops
.Elements(),
1443 aStops
.Length(), aExtendMode
, aOutset
);
1446 void DisplayListBuilder::PushBorderRadialGradient(
1447 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1448 bool aIsBackfaceVisible
, const wr::LayoutSideOffsets
& aWidths
, bool aFill
,
1449 const wr::LayoutPoint
& aCenter
, const wr::LayoutSize
& aRadius
,
1450 const nsTArray
<wr::GradientStop
>& aStops
, wr::ExtendMode aExtendMode
,
1451 const wr::LayoutSideOffsets
& aOutset
) {
1452 wr_dp_push_border_radial_gradient(
1453 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1454 &mCurrentSpaceAndClipChain
, aWidths
, aFill
, aCenter
, aRadius
,
1455 aStops
.Elements(), aStops
.Length(), aExtendMode
, aOutset
);
1458 void DisplayListBuilder::PushBorderConicGradient(
1459 const wr::LayoutRect
& aBounds
, const wr::LayoutRect
& aClip
,
1460 bool aIsBackfaceVisible
, const wr::LayoutSideOffsets
& aWidths
, bool aFill
,
1461 const wr::LayoutPoint
& aCenter
, const float aAngle
,
1462 const nsTArray
<wr::GradientStop
>& aStops
, wr::ExtendMode aExtendMode
,
1463 const wr::LayoutSideOffsets
& aOutset
) {
1464 wr_dp_push_border_conic_gradient(
1465 mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1466 &mCurrentSpaceAndClipChain
, aWidths
, aFill
, aCenter
, aAngle
,
1467 aStops
.Elements(), aStops
.Length(), aExtendMode
, aOutset
);
1470 void DisplayListBuilder::PushText(const wr::LayoutRect
& aBounds
,
1471 const wr::LayoutRect
& aClip
,
1472 bool aIsBackfaceVisible
,
1473 const wr::ColorF
& aColor
,
1474 wr::FontInstanceKey aFontKey
,
1475 Range
<const wr::GlyphInstance
> aGlyphBuffer
,
1476 const wr::GlyphOptions
* aGlyphOptions
) {
1477 wr_dp_push_text(mWrState
, aBounds
, MergeClipLeaf(aClip
), aIsBackfaceVisible
,
1478 &mCurrentSpaceAndClipChain
, aColor
, aFontKey
,
1479 &aGlyphBuffer
[0], aGlyphBuffer
.length(), aGlyphOptions
);
1482 void DisplayListBuilder::PushLine(const wr::LayoutRect
& aClip
,
1483 bool aIsBackfaceVisible
,
1484 const wr::Line
& aLine
) {
1485 wr::LayoutRect clip
= MergeClipLeaf(aClip
);
1486 wr_dp_push_line(mWrState
, &clip
, aIsBackfaceVisible
,
1487 &mCurrentSpaceAndClipChain
, &aLine
.bounds
,
1488 aLine
.wavyLineThickness
, aLine
.orientation
, &aLine
.color
,
1492 void DisplayListBuilder::PushShadow(const wr::LayoutRect
& aRect
,
1493 const wr::LayoutRect
& aClip
,
1494 bool aIsBackfaceVisible
,
1495 const wr::Shadow
& aShadow
,
1496 bool aShouldInflate
) {
1497 // Local clip_rects are translated inside of shadows, as they are assumed to
1498 // be part of the element drawing itself, and not a parent frame clipping it.
1499 // As such, it is not sound to apply the MergeClipLeaf optimization inside of
1500 // shadows. So we disable the optimization when we encounter a shadow.
1501 // Shadows don't span frames, so we don't have to worry about MergeClipLeaf
1502 // being re-enabled mid-shadow. The optimization is restored in PopAllShadows.
1503 SuspendClipLeafMerging();
1504 wr_dp_push_shadow(mWrState
, aRect
, aClip
, aIsBackfaceVisible
,
1505 &mCurrentSpaceAndClipChain
, aShadow
, aShouldInflate
);
1508 void DisplayListBuilder::PopAllShadows() {
1509 wr_dp_pop_all_shadows(mWrState
);
1510 ResumeClipLeafMerging();
1513 void DisplayListBuilder::SuspendClipLeafMerging() {
1514 if (mClipChainLeaf
) {
1515 // No one should reinitialize mClipChainLeaf while we're suspended
1516 MOZ_ASSERT(!mSuspendedClipChainLeaf
);
1518 mSuspendedClipChainLeaf
= mClipChainLeaf
;
1519 mSuspendedSpaceAndClipChain
= Some(mCurrentSpaceAndClipChain
);
1521 auto clipId
= DefineRectClip(*mClipChainLeaf
);
1522 auto clipChainId
= DefineClipChain({clipId
}, true);
1524 mCurrentSpaceAndClipChain
.clip_chain
= clipChainId
.id
;
1525 mClipChainLeaf
= Nothing();
1529 void DisplayListBuilder::ResumeClipLeafMerging() {
1530 if (mSuspendedClipChainLeaf
) {
1531 mCurrentSpaceAndClipChain
= *mSuspendedSpaceAndClipChain
;
1532 mClipChainLeaf
= mSuspendedClipChainLeaf
;
1534 mSuspendedClipChainLeaf
= Nothing();
1535 mSuspendedSpaceAndClipChain
= Nothing();
1539 void DisplayListBuilder::PushBoxShadow(
1540 const wr::LayoutRect
& aRect
, const wr::LayoutRect
& aClip
,
1541 bool aIsBackfaceVisible
, const wr::LayoutRect
& aBoxBounds
,
1542 const wr::LayoutVector2D
& aOffset
, const wr::ColorF
& aColor
,
1543 const float& aBlurRadius
, const float& aSpreadRadius
,
1544 const wr::BorderRadius
& aBorderRadius
,
1545 const wr::BoxShadowClipMode
& aClipMode
) {
1546 wr_dp_push_box_shadow(mWrState
, aRect
, MergeClipLeaf(aClip
),
1547 aIsBackfaceVisible
, &mCurrentSpaceAndClipChain
,
1548 aBoxBounds
, aOffset
, aColor
, aBlurRadius
, aSpreadRadius
,
1549 aBorderRadius
, aClipMode
);
1552 void DisplayListBuilder::StartGroup(nsPaintedDisplayItem
* aItem
) {
1553 if (!mDisplayItemCache
|| mDisplayItemCache
->IsFull()) {
1557 MOZ_ASSERT(!mCurrentCacheSlot
);
1558 mCurrentCacheSlot
= mDisplayItemCache
->AssignSlot(aItem
);
1560 if (mCurrentCacheSlot
) {
1561 wr_dp_start_item_group(mWrState
);
1565 void DisplayListBuilder::CancelGroup(const bool aDiscard
) {
1566 if (!mDisplayItemCache
|| !mCurrentCacheSlot
) {
1570 wr_dp_cancel_item_group(mWrState
, aDiscard
);
1571 mCurrentCacheSlot
= Nothing();
1574 void DisplayListBuilder::FinishGroup() {
1575 if (!mDisplayItemCache
|| !mCurrentCacheSlot
) {
1579 MOZ_ASSERT(mCurrentCacheSlot
);
1581 if (wr_dp_finish_item_group(mWrState
, mCurrentCacheSlot
.ref())) {
1582 mDisplayItemCache
->MarkSlotOccupied(mCurrentCacheSlot
.ref(),
1583 CurrentSpaceAndClipChain());
1584 mDisplayItemCache
->Stats().AddCached();
1587 mCurrentCacheSlot
= Nothing();
1590 bool DisplayListBuilder::ReuseItem(nsPaintedDisplayItem
* aItem
) {
1591 if (!mDisplayItemCache
) {
1595 mDisplayItemCache
->Stats().AddTotal();
1597 if (mDisplayItemCache
->IsEmpty()) {
1601 Maybe
<uint16_t> slot
=
1602 mDisplayItemCache
->CanReuseItem(aItem
, CurrentSpaceAndClipChain());
1605 mDisplayItemCache
->Stats().AddReused();
1606 wr_dp_push_reuse_items(mWrState
, slot
.ref());
1613 Maybe
<layers::ScrollableLayerGuid::ViewID
>
1614 DisplayListBuilder::GetContainingFixedPosScrollTarget(
1615 const ActiveScrolledRoot
* aAsr
) {
1616 return mActiveFixedPosTracker
1617 ? mActiveFixedPosTracker
->GetScrollTargetForASR(aAsr
)
1621 Maybe
<SideBits
> DisplayListBuilder::GetContainingFixedPosSideBits(
1622 const ActiveScrolledRoot
* aAsr
) {
1623 return mActiveFixedPosTracker
1624 ? mActiveFixedPosTracker
->GetSideBitsForASR(aAsr
)
1628 DisplayListBuilder::FixedPosScrollTargetTracker::FixedPosScrollTargetTracker(
1629 DisplayListBuilder
& aBuilder
, const ActiveScrolledRoot
* aAsr
,
1630 layers::ScrollableLayerGuid::ViewID aScrollId
, SideBits aSideBits
)
1631 : mParentTracker(aBuilder
.mActiveFixedPosTracker
),
1634 mScrollId(aScrollId
),
1635 mSideBits(aSideBits
) {
1636 aBuilder
.mActiveFixedPosTracker
= this;
1639 DisplayListBuilder::FixedPosScrollTargetTracker::
1640 ~FixedPosScrollTargetTracker() {
1641 mBuilder
.mActiveFixedPosTracker
= mParentTracker
;
1644 Maybe
<layers::ScrollableLayerGuid::ViewID
>
1645 DisplayListBuilder::FixedPosScrollTargetTracker::GetScrollTargetForASR(
1646 const ActiveScrolledRoot
* aAsr
) {
1647 return aAsr
== mAsr
? Some(mScrollId
) : Nothing();
1651 DisplayListBuilder::FixedPosScrollTargetTracker::GetSideBitsForASR(
1652 const ActiveScrolledRoot
* aAsr
) {
1653 return aAsr
== mAsr
? Some(mSideBits
) : Nothing();
1656 already_AddRefed
<gfxContext
> DisplayListBuilder::GetTextContext(
1657 wr::IpcResourceUpdateQueue
& aResources
,
1658 const layers::StackingContextHelper
& aSc
,
1659 layers::RenderRootStateManager
* aManager
, nsDisplayItem
* aItem
,
1660 nsRect
& aBounds
, const gfx::Point
& aDeviceOffset
) {
1661 if (!mCachedTextDT
) {
1662 mCachedTextDT
= new layout::TextDrawTarget(*this, aResources
, aSc
, aManager
,
1664 mCachedContext
= gfxContext::CreateOrNull(mCachedTextDT
, aDeviceOffset
);
1666 mCachedTextDT
->Reinitialize(aResources
, aSc
, aManager
, aItem
, aBounds
);
1667 mCachedContext
->SetDeviceOffset(aDeviceOffset
);
1668 mCachedContext
->SetMatrix(gfx::Matrix());
1671 RefPtr
<gfxContext
> tmp
= mCachedContext
;
1672 return tmp
.forget();
1676 } // namespace mozilla
1680 void wr_transaction_notification_notified(uintptr_t aHandler
,
1681 mozilla::wr::Checkpoint aWhen
) {
1682 auto handler
= reinterpret_cast<mozilla::wr::NotificationHandler
*>(aHandler
);
1683 handler
->Notify(aWhen
);
1684 // TODO: it would be better to get a callback when the object is destroyed on
1685 // the rust side and delete then.
1689 void wr_register_thread_local_arena() {
1691 jemalloc_thread_local_arena(true);