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