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