Bug 1675375 Part 2: Add a polygon clips to image masks. r=gw
[gecko.git] / gfx / webrender_bindings / WebRenderAPI.cpp
blob920effe698a313f21d58477911a7ad8c35426b7f
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"
21 // clang-format off
22 #define WRDL_LOG(...)
23 //#define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__)
24 //#define WRDL_LOG(...) if (XRE_IsContentProcess()) printf_stderr("WRDL(%p): " __VA_ARGS__)
25 // clang-format on
27 namespace mozilla {
28 using namespace layers;
30 namespace wr {
32 MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf)
33 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(WebRenderMallocEnclosingSizeOf)
35 enum SideBitsPacked {
36 eSideBitsPackedTop = 0x1000,
37 eSideBitsPackedRight = 0x2000,
38 eSideBitsPackedBottom = 0x4000,
39 eSideBitsPackedLeft = 0x8000
42 static uint16_t SideBitsToHitInfoBits(SideBits aSideBits) {
43 uint16_t ret = 0;
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;
56 return ret;
59 class NewRenderer : public RendererEvent {
60 public:
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,
69 nsACString* aError)
70 : mDocHandle(aDocHandle),
71 mBackend(aBackend),
72 mCompositor(aCompositor),
73 mMaxTextureSize(aMaxTextureSize),
74 mUseANGLE(aUseANGLE),
75 mUseDComp(aUseDComp),
76 mUseTripleBuffering(aUseTripleBuffering),
77 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures),
78 mBridge(aBridge),
79 mCompositorWidget(std::move(aWidget)),
80 mTask(aTask),
81 mSize(aSize),
82 mWindowKind(aWindowKind),
83 mSyncHandle(aHandle),
84 mError(aError) {
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);
95 if (!compositor) {
96 if (!mError->IsEmpty()) {
97 gfxCriticalNote << mError->BeginReading();
99 return;
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;
114 #ifdef NIGHTLY_BUILD
115 panic_on_gl_error =
116 StaticPrefs::gfx_webrender_panic_on_gl_error_AtStartup();
117 #endif
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()
132 : nullptr;
133 auto* shaders = (aRenderThread.GetShaders() && !swgl)
134 ? aRenderThread.GetShaders()->RawShaders()
135 : nullptr;
137 if (!wr_window_new(
138 aWindowId, mSize.width, mSize.height,
139 mWindowKind == WindowKind::MAIN, supportLowPriorityTransactions,
140 supportLowPriorityThreadpool, gfx::gfxVars::UseGLSwizzle(),
141 gfx::gfxVars::UseWebRenderScissoredCacheClears(),
142 #ifdef NIGHTLY_BUILD
143 StaticPrefs::gfx_webrender_start_debug_server(),
144 #else
145 false,
146 #endif
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);
162 return;
164 MOZ_ASSERT(wrRenderer);
166 RefPtr<RenderThread> thread = &aRenderThread;
167 auto renderer =
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);
175 if (renderer) {
176 layers::SyncObjectHost* syncObj = renderer->GetSyncObject();
177 if (syncObj) {
178 *mSyncHandle = syncObj->GetSyncHandle();
182 aRenderThread.AddRenderer(aWindowId, std::move(renderer));
185 private:
186 wr::DocumentHandle** mDocHandle;
187 WebRenderBackend* mBackend;
188 WebRenderCompositor* mCompositor;
189 int32_t* mMaxTextureSize;
190 bool* mUseANGLE;
191 bool* mUseDComp;
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;
200 nsACString* mError;
203 class RemoveRenderer : public RendererEvent {
204 public:
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);
216 private:
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,
251 &dl_data.inner);
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,
343 bool aIsZooming) {
344 wr_transaction_set_is_transform_async_zooming(mTxn, aAnimationId, aIsZooming);
347 /*static*/
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) {
353 MOZ_ASSERT(aBridge);
354 MOZ_ASSERT(aWidget);
355 static_assert(
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));
379 task.Wait();
381 if (!docHandle) {
382 return nullptr;
385 return RefPtr<WebRenderAPI>(
386 new WebRenderAPI(docHandle, aWindowId, backend, compositor,
387 maxTextureSize, useANGLE, useDComp,
388 useTripleBuffering,
389 supportsExternalBufferTextures, syncHandle))
390 .forget();
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),
419 mId(aId),
420 mBackend(aBackend),
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);
436 if (!mRootApi) {
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));
454 task.Wait();
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;
483 return sideBits;
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);
504 return geckoResults;
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 {
511 public:
512 explicit Readback(layers::SynchronousTask* aTask, TimeStamp aStartTime,
513 gfx::IntSize aSize, const gfx::SurfaceFormat& aFormat,
514 const Range<uint8_t>& aBuffer, bool* aNeedsYFlip)
515 : mTask(aTask),
516 mStartTime(aStartTime),
517 mSize(aSize),
518 mFormat(aFormat),
519 mBuffer(aBuffer),
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;
536 gfx::IntSize mSize;
537 gfx::SurfaceFormat mFormat;
538 const Range<uint8_t>& mBuffer;
539 bool* mNeedsYFlip;
542 // Disable debug flags during readback. See bug 1436020.
543 UpdateDebugFlags(0);
545 layers::SynchronousTask task("Readback");
546 auto event = MakeUnique<Readback>(&task, aStartTime, size, aFormat, buffer,
547 aNeedsYFlip);
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
551 // latest result.
552 RunOnRenderThread(std::move(event));
554 task.Wait();
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 {
583 public:
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
602 // event.
603 RunOnRenderThread(std::move(event));
605 task.Wait();
608 bool WebRenderAPI::Resume() {
609 class ResumeEvent : public RendererEvent {
610 public:
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;
624 bool* mResult;
627 bool result = false;
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
632 // event.
633 RunOnRenderThread(std::move(event));
635 task.Wait();
636 return result;
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 {
656 public:
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
674 // event.
675 RunOnRenderThread(std::move(event));
677 task.Wait();
680 void WebRenderAPI::Capture() {
681 // see CaptureBits
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,
689 uint32_t aFlags) {
690 if (mCaptureSequence) {
691 wr_api_stop_capture_sequence(mDocHandle);
694 wr_api_start_capture_sequence(mDocHandle, PromiseFlatCString(aPath).get(),
695 aFlags);
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 {
711 public:
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,
722 mRootPipelineId);
725 private:
726 TimeStamp mRecordingStart;
727 wr::PipelineId mRootPipelineId;
730 auto event =
731 MakeUnique<BeginRecordingEvent>(aRecordingStart, aRootPipelineId);
732 RunOnRenderThread(std::move(event));
735 RefPtr<WebRenderAPI::WriteCollectedFramesPromise>
736 WebRenderAPI::WriteCollectedFrames() {
737 class WriteCollectedFramesEvent final : public RendererEvent {
738 public:
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__);
754 private:
755 MozPromiseHolder<WebRenderAPI::WriteCollectedFramesPromise> mPromise;
758 auto event = MakeUnique<WriteCollectedFramesEvent>();
759 auto promise = event->GetPromise();
761 RunOnRenderThread(std::move(event));
762 return promise;
765 RefPtr<WebRenderAPI::GetCollectedFramesPromise>
766 WebRenderAPI::GetCollectedFrames() {
767 class GetCollectedFramesEvent final : public RendererEvent {
768 public:
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);
779 if (frames) {
780 mPromise.Resolve(std::move(*frames), __func__);
781 } else {
782 mPromise.Reject(NS_ERROR_UNEXPECTED, __func__);
786 RefPtr<WebRenderAPI::GetCollectedFramesPromise> GetPromise() {
787 return mPromise.Ensure(__func__);
790 private:
791 MozPromiseHolder<WebRenderAPI::GetCollectedFramesPromise> mPromise;
794 auto event = MakeUnique<GetCollectedFramesEvent>();
795 auto promise = event->GetPromise();
797 RunOnRenderThread(std::move(event));
798 return promise;
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,
820 aVisibleRect);
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(),
837 channelIndex);
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,
886 uint32_t aIndex) {
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,
892 uint32_t aIndex) {
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,
907 &aVariations.inner);
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 {
920 public:
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);
929 if (renderer) {
930 renderer->SetFrameStartTime(mTime);
934 private:
935 TimeStamp 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,
950 size_t aCapacity,
951 layers::DisplayItemCache* aCache)
952 : mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
953 mActiveFixedPosTracker(nullptr),
954 mPipelineId(aId),
955 mBackend(aBackend),
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());
994 wr::VecU8 dl;
995 wr_api_finalize_builder(mWrState, &aOutTransaction.mDLDesc, &dl.inner);
996 aOutTransaction.mDL.emplace(dl.inner.data, dl.inner.length,
997 dl.inner.capacity);
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;
1011 if (transform) {
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(),
1023 aRasterSpace);
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) {
1035 CancelGroup();
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,
1045 aClips.Length());
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) {
1052 CancelGroup();
1054 WrClipId clipId;
1055 if (aParent) {
1056 clipId = wr_dp_define_clip_with_parent_clip(
1057 mWrState, aParent.ptr(), aClipRect,
1058 aComplex ? aComplex->Elements() : nullptr,
1059 aComplex ? aComplex->Length() : 0);
1060 } else {
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);
1071 return clipId;
1074 wr::WrClipId DisplayListBuilder::DefineImageMaskClip(
1075 const wr::ImageMask& aMask, const nsTArray<wr::LayoutPoint>& aPoints,
1076 wr::FillRule aFillRule) {
1077 CancelGroup();
1079 WrClipId clipId = wr_dp_define_image_mask_clip_with_parent_clip_chain(
1080 mWrState, &mCurrentSpaceAndClipChain, aMask, aPoints.Elements(),
1081 aPoints.Length(), aFillRule);
1083 return clipId;
1086 wr::WrClipId DisplayListBuilder::DefineRoundedRectClip(
1087 const wr::ComplexClipRegion& aComplex) {
1088 CancelGroup();
1090 WrClipId clipId = wr_dp_define_rounded_rect_clip_with_parent_clip_chain(
1091 mWrState, &mCurrentSpaceAndClipChain, aComplex);
1093 return clipId;
1096 wr::WrClipId DisplayListBuilder::DefineRectClip(wr::LayoutRect aClipRect) {
1097 CancelGroup();
1099 WrClipId clipId = wr_dp_define_rect_clip_with_parent_clip_chain(
1100 mWrState, &mCurrentSpaceAndClipChain, aClipRect);
1102 return clipId;
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());
1126 return spatialId;
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()) {
1137 return Nothing();
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()) {
1150 return it->second;
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,
1242 aAnimation);
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,
1271 &spaceAndClip);
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) {
1416 return;
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,
1429 &aParams);
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,
1489 aLine.style);
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()) {
1554 return;
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) {
1567 return;
1570 wr_dp_cancel_item_group(mWrState, aDiscard);
1571 mCurrentCacheSlot = Nothing();
1574 void DisplayListBuilder::FinishGroup() {
1575 if (!mDisplayItemCache || !mCurrentCacheSlot) {
1576 return;
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) {
1592 return false;
1595 mDisplayItemCache->Stats().AddTotal();
1597 if (mDisplayItemCache->IsEmpty()) {
1598 return false;
1601 Maybe<uint16_t> slot =
1602 mDisplayItemCache->CanReuseItem(aItem, CurrentSpaceAndClipChain());
1604 if (slot) {
1605 mDisplayItemCache->Stats().AddReused();
1606 wr_dp_push_reuse_items(mWrState, slot.ref());
1607 return true;
1610 return false;
1613 Maybe<layers::ScrollableLayerGuid::ViewID>
1614 DisplayListBuilder::GetContainingFixedPosScrollTarget(
1615 const ActiveScrolledRoot* aAsr) {
1616 return mActiveFixedPosTracker
1617 ? mActiveFixedPosTracker->GetScrollTargetForASR(aAsr)
1618 : Nothing();
1621 Maybe<SideBits> DisplayListBuilder::GetContainingFixedPosSideBits(
1622 const ActiveScrolledRoot* aAsr) {
1623 return mActiveFixedPosTracker
1624 ? mActiveFixedPosTracker->GetSideBitsForASR(aAsr)
1625 : Nothing();
1628 DisplayListBuilder::FixedPosScrollTargetTracker::FixedPosScrollTargetTracker(
1629 DisplayListBuilder& aBuilder, const ActiveScrolledRoot* aAsr,
1630 layers::ScrollableLayerGuid::ViewID aScrollId, SideBits aSideBits)
1631 : mParentTracker(aBuilder.mActiveFixedPosTracker),
1632 mBuilder(aBuilder),
1633 mAsr(aAsr),
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();
1650 Maybe<SideBits>
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,
1663 aItem, aBounds);
1664 mCachedContext = gfxContext::CreateOrNull(mCachedTextDT, aDeviceOffset);
1665 } else {
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();
1675 } // namespace wr
1676 } // namespace mozilla
1678 extern "C" {
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.
1686 delete handler;
1689 void wr_register_thread_local_arena() {
1690 #ifdef MOZ_MEMORY
1691 jemalloc_thread_local_arena(true);
1692 #endif
1695 } // extern C