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 #include "DisplayItemClipChain.h"
9 #include "LayersLogging.h"
10 #include "mozilla/webrender/RendererOGL.h"
11 #include "mozilla/gfx/gfxVars.h"
12 #include "mozilla/layers/CompositorThread.h"
13 #include "mozilla/webrender/RenderCompositor.h"
14 #include "mozilla/widget/CompositorWidget.h"
15 #include "mozilla/layers/SynchronousTask.h"
16 
17 #define WRDL_LOG(...)
18 /*
19 #define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__)
20 #define WRDL_LOG(...) if (XRE_IsContentProcess()) {              \
21                         printf_stderr("WRDL(%p): " __VA_ARGS__); \
22                       }
23 */
24 
25 namespace mozilla {
26 namespace wr {
27 
28 using layers::Stringify;
29 
30 class NewRenderer : public RendererEvent {
31  public:
NewRenderer(wr::DocumentHandle ** aDocHandle,layers::CompositorBridgeParentBase * aBridge,uint32_t * aMaxTextureSize,bool * aUseANGLE,RefPtr<widget::CompositorWidget> && aWidget,layers::SynchronousTask * aTask,LayoutDeviceIntSize aSize,layers::SyncHandle * aHandle)32   NewRenderer(wr::DocumentHandle** aDocHandle,
33               layers::CompositorBridgeParentBase* aBridge,
34               uint32_t* aMaxTextureSize, bool* aUseANGLE,
35               RefPtr<widget::CompositorWidget>&& aWidget,
36               layers::SynchronousTask* aTask, LayoutDeviceIntSize aSize,
37               layers::SyncHandle* aHandle)
38       : mDocHandle(aDocHandle),
39         mMaxTextureSize(aMaxTextureSize),
40         mUseANGLE(aUseANGLE),
41         mBridge(aBridge),
42         mCompositorWidget(Move(aWidget)),
43         mTask(aTask),
44         mSize(aSize),
45         mSyncHandle(aHandle) {
46     MOZ_COUNT_CTOR(NewRenderer);
47   }
48 
~NewRenderer()49   ~NewRenderer() { MOZ_COUNT_DTOR(NewRenderer); }
50 
Run(RenderThread & aRenderThread,WindowId aWindowId)51   virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
52     layers::AutoCompleteTask complete(mTask);
53 
54     UniquePtr<RenderCompositor> compositor =
55         RenderCompositor::Create(Move(mCompositorWidget));
56     if (!compositor) {
57       // RenderCompositor::Create puts a message into gfxCriticalNote if it is
58       // nullptr
59       return;
60     }
61 
62     *mUseANGLE = compositor->UseANGLE();
63 
64     wr::Renderer* wrRenderer = nullptr;
65     if (!wr_window_new(aWindowId, mSize.width, mSize.height, compositor->gl(),
66                        aRenderThread.ThreadPool().Raw(), mDocHandle,
67                        &wrRenderer, mMaxTextureSize)) {
68       // wr_window_new puts a message into gfxCriticalNote if it returns false
69       return;
70     }
71     MOZ_ASSERT(wrRenderer);
72 
73     RefPtr<RenderThread> thread = &aRenderThread;
74     auto renderer = MakeUnique<RendererOGL>(Move(thread), Move(compositor),
75                                             aWindowId, wrRenderer, mBridge);
76     if (wrRenderer && renderer) {
77       wr::WrExternalImageHandler handler = renderer->GetExternalImageHandler();
78       wr_renderer_set_external_image_handler(wrRenderer, &handler);
79       if (gfx::gfxVars::UseWebRenderProgramBinary()) {
80         wr_renderer_update_program_cache(wrRenderer,
81                                          aRenderThread.ProgramCache()->Raw());
82       }
83     }
84 
85     if (renderer) {
86       layers::SyncObjectHost* syncObj = renderer->GetSyncObject();
87       if (syncObj) {
88         *mSyncHandle = syncObj->GetSyncHandle();
89       }
90     }
91 
92     aRenderThread.AddRenderer(aWindowId, Move(renderer));
93   }
94 
95  private:
96   wr::DocumentHandle** mDocHandle;
97   uint32_t* mMaxTextureSize;
98   bool* mUseANGLE;
99   layers::CompositorBridgeParentBase* mBridge;
100   RefPtr<widget::CompositorWidget> mCompositorWidget;
101   layers::SynchronousTask* mTask;
102   LayoutDeviceIntSize mSize;
103   layers::SyncHandle* mSyncHandle;
104 };
105 
106 class RemoveRenderer : public RendererEvent {
107  public:
RemoveRenderer(layers::SynchronousTask * aTask)108   explicit RemoveRenderer(layers::SynchronousTask* aTask) : mTask(aTask) {
109     MOZ_COUNT_CTOR(RemoveRenderer);
110   }
111 
~RemoveRenderer()112   ~RemoveRenderer() { MOZ_COUNT_DTOR(RemoveRenderer); }
113 
Run(RenderThread & aRenderThread,WindowId aWindowId)114   virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
115     aRenderThread.RemoveRenderer(aWindowId);
116     layers::AutoCompleteTask complete(mTask);
117   }
118 
119  private:
120   layers::SynchronousTask* mTask;
121 };
122 
TransactionBuilder()123 TransactionBuilder::TransactionBuilder() {
124   mTxn = wr_transaction_new();
125   mResourceUpdates = wr_resource_updates_new();
126 }
127 
~TransactionBuilder()128 TransactionBuilder::~TransactionBuilder() {
129   wr_transaction_delete(mTxn);
130   wr_resource_updates_delete(mResourceUpdates);
131 }
132 
UpdateEpoch(PipelineId aPipelineId,Epoch aEpoch)133 void TransactionBuilder::UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch) {
134   wr_transaction_update_epoch(mTxn, aPipelineId, aEpoch);
135 }
136 
SetRootPipeline(PipelineId aPipelineId)137 void TransactionBuilder::SetRootPipeline(PipelineId aPipelineId) {
138   wr_transaction_set_root_pipeline(mTxn, aPipelineId);
139 }
140 
RemovePipeline(PipelineId aPipelineId)141 void TransactionBuilder::RemovePipeline(PipelineId aPipelineId) {
142   wr_transaction_remove_pipeline(mTxn, aPipelineId);
143 }
144 
SetDisplayList(gfx::Color aBgColor,Epoch aEpoch,mozilla::LayerSize aViewportSize,wr::WrPipelineId pipeline_id,const wr::LayoutSize & content_size,wr::BuiltDisplayListDescriptor dl_descriptor,wr::Vec<uint8_t> & dl_data)145 void TransactionBuilder::SetDisplayList(
146     gfx::Color aBgColor, Epoch aEpoch, mozilla::LayerSize aViewportSize,
147     wr::WrPipelineId pipeline_id, const wr::LayoutSize& content_size,
148     wr::BuiltDisplayListDescriptor dl_descriptor, wr::Vec<uint8_t>& dl_data) {
149   wr_transaction_set_display_list(mTxn, aEpoch, ToColorF(aBgColor),
150                                   aViewportSize.width, aViewportSize.height,
151                                   pipeline_id, content_size, dl_descriptor,
152                                   &dl_data.inner);
153 }
154 
ClearDisplayList(Epoch aEpoch,wr::WrPipelineId aPipelineId)155 void TransactionBuilder::ClearDisplayList(Epoch aEpoch,
156                                           wr::WrPipelineId aPipelineId) {
157   wr_transaction_clear_display_list(mTxn, aEpoch, aPipelineId);
158 }
159 
GenerateFrame()160 void TransactionBuilder::GenerateFrame() {
161   wr_transaction_generate_frame(mTxn);
162 }
163 
UpdateDynamicProperties(const nsTArray<wr::WrOpacityProperty> & aOpacityArray,const nsTArray<wr::WrTransformProperty> & aTransformArray)164 void TransactionBuilder::UpdateDynamicProperties(
165     const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
166     const nsTArray<wr::WrTransformProperty>& aTransformArray) {
167   wr_transaction_update_dynamic_properties(
168       mTxn, aOpacityArray.IsEmpty() ? nullptr : aOpacityArray.Elements(),
169       aOpacityArray.Length(),
170       aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(),
171       aTransformArray.Length());
172 }
173 
IsEmpty() const174 bool TransactionBuilder::IsEmpty() const {
175   return wr_transaction_is_empty(mTxn);
176 }
177 
SetWindowParameters(const LayoutDeviceIntSize & aWindowSize,const LayoutDeviceIntRect & aDocumentRect)178 void TransactionBuilder::SetWindowParameters(
179     const LayoutDeviceIntSize& aWindowSize,
180     const LayoutDeviceIntRect& aDocumentRect) {
181   wr::DeviceUintSize wrWindowSize;
182   wrWindowSize.width = aWindowSize.width;
183   wrWindowSize.height = aWindowSize.height;
184   wr::DeviceUintRect wrDocRect;
185   wrDocRect.origin.x = aDocumentRect.x;
186   wrDocRect.origin.y = aDocumentRect.y;
187   wrDocRect.size.width = aDocumentRect.width;
188   wrDocRect.size.height = aDocumentRect.height;
189   wr_transaction_set_window_parameters(mTxn, &wrWindowSize, &wrDocRect);
190 }
191 
UpdateScrollPosition(const wr::WrPipelineId & aPipelineId,const layers::FrameMetrics::ViewID & aScrollId,const wr::LayoutPoint & aScrollPosition)192 void TransactionBuilder::UpdateScrollPosition(
193     const wr::WrPipelineId& aPipelineId,
194     const layers::FrameMetrics::ViewID& aScrollId,
195     const wr::LayoutPoint& aScrollPosition) {
196   wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition);
197 }
198 
InitExternalLogHandler()199 /*static*/ void WebRenderAPI::InitExternalLogHandler() {
200   // Redirect the webrender's log to gecko's log system.
201   // The current log level is "error".
202   mozilla::wr::wr_init_external_log_handler(wr::WrLogLevelFilter::Error);
203 }
204 
ShutdownExternalLogHandler()205 /*static*/ void WebRenderAPI::ShutdownExternalLogHandler() {
206   mozilla::wr::wr_shutdown_external_log_handler();
207 }
208 
Create(layers::CompositorBridgeParentBase * aBridge,RefPtr<widget::CompositorWidget> && aWidget,LayoutDeviceIntSize aSize)209 /*static*/ already_AddRefed<WebRenderAPI> WebRenderAPI::Create(
210     layers::CompositorBridgeParentBase* aBridge,
211     RefPtr<widget::CompositorWidget>&& aWidget, LayoutDeviceIntSize aSize) {
212   MOZ_ASSERT(aBridge);
213   MOZ_ASSERT(aWidget);
214 
215   static uint64_t sNextId = 1;
216   auto id = NewWindowId(sNextId++);
217 
218   wr::DocumentHandle* docHandle = nullptr;
219   uint32_t maxTextureSize = 0;
220   bool useANGLE = false;
221   layers::SyncHandle syncHandle = 0;
222 
223   // Dispatch a synchronous task because the DocumentHandle object needs to be
224   // created on the render thread. If need be we could delay waiting on this
225   // task until the next time we need to access the DocumentHandle object.
226   layers::SynchronousTask task("Create Renderer");
227   auto event =
228       MakeUnique<NewRenderer>(&docHandle, aBridge, &maxTextureSize, &useANGLE,
229                               Move(aWidget), &task, aSize, &syncHandle);
230   RenderThread::Get()->RunEvent(id, Move(event));
231 
232   task.Wait();
233 
234   if (!docHandle) {
235     return nullptr;
236   }
237 
238   return RefPtr<WebRenderAPI>(new WebRenderAPI(docHandle, id, maxTextureSize,
239                                                useANGLE, syncHandle))
240       .forget();
241 }
242 
Clone()243 already_AddRefed<WebRenderAPI> WebRenderAPI::Clone() {
244   wr::DocumentHandle* docHandle = nullptr;
245   wr_api_clone(mDocHandle, &docHandle);
246 
247   RefPtr<WebRenderAPI> renderApi =
248       new WebRenderAPI(docHandle, mId, mMaxTextureSize, mUseANGLE, mSyncHandle);
249   renderApi->mRootApi = this;  // Hold root api
250   renderApi->mRootDocumentApi = this;
251   return renderApi.forget();
252 }
253 
CreateDocument(LayoutDeviceIntSize aSize,int8_t aLayerIndex)254 already_AddRefed<WebRenderAPI> WebRenderAPI::CreateDocument(
255     LayoutDeviceIntSize aSize, int8_t aLayerIndex) {
256   wr::DeviceUintSize wrSize;
257   wrSize.width = aSize.width;
258   wrSize.height = aSize.height;
259   wr::DocumentHandle* newDoc;
260 
261   wr_api_create_document(mDocHandle, &newDoc, wrSize, aLayerIndex);
262 
263   RefPtr<WebRenderAPI> api(
264       new WebRenderAPI(newDoc, mId, mMaxTextureSize, mUseANGLE, mSyncHandle));
265   api->mRootApi = this;
266   return api.forget();
267 }
268 
GetNamespace()269 wr::WrIdNamespace WebRenderAPI::GetNamespace() {
270   return wr_api_get_namespace(mDocHandle);
271 }
272 
273 extern void ClearBlobImageResources(WrIdNamespace aNamespace);
274 
~WebRenderAPI()275 WebRenderAPI::~WebRenderAPI() {
276   if (!mRootDocumentApi) {
277     wr_api_delete_document(mDocHandle);
278   }
279 
280   if (!mRootApi) {
281     RenderThread::Get()->SetDestroyed(GetId());
282 
283     layers::SynchronousTask task("Destroy WebRenderAPI");
284     auto event = MakeUnique<RemoveRenderer>(&task);
285     RunOnRenderThread(Move(event));
286     task.Wait();
287 
288     wr_api_shut_down(mDocHandle);
289   }
290 
291     // wr_api_get_namespace cannot be marked destructor-safe because it has a
292     // return value, and we can't call it if MOZ_BUILD_WEBRENDER is not defined
293     // because it's not destructor-safe. So let's just ifdef around it. This is
294     // basically a hack to get around compile-time warnings, this code never
295     // runs unless MOZ_BUILD_WEBRENDER is defined anyway.
296 #ifdef MOZ_BUILD_WEBRENDER
297   wr::WrIdNamespace ns = GetNamespace();
298 #else
299   wr::WrIdNamespace ns{0};
300 #endif
301 
302   // Clean up any resources the blob image renderer is holding onto that
303   // can no longer be used once this WR API instance goes away.
304   ClearBlobImageResources(ns);
305 
306   wr_api_delete(mDocHandle);
307 }
308 
SendTransaction(TransactionBuilder & aTxn)309 void WebRenderAPI::SendTransaction(TransactionBuilder& aTxn) {
310   wr_transaction_update_resources(aTxn.Raw(), aTxn.RawUpdates());
311   wr_api_send_transaction(mDocHandle, aTxn.Raw());
312 }
313 
HitTest(const wr::WorldPoint & aPoint,wr::WrPipelineId & aOutPipelineId,layers::FrameMetrics::ViewID & aOutScrollId,gfx::CompositorHitTestInfo & aOutHitInfo)314 bool WebRenderAPI::HitTest(const wr::WorldPoint& aPoint,
315                            wr::WrPipelineId& aOutPipelineId,
316                            layers::FrameMetrics::ViewID& aOutScrollId,
317                            gfx::CompositorHitTestInfo& aOutHitInfo) {
318   static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint16_t),
319                 "CompositorHitTestInfo should be u16-sized");
320   return wr_api_hit_test(mDocHandle, aPoint, &aOutPipelineId, &aOutScrollId,
321                          (uint16_t*)&aOutHitInfo);
322 }
323 
Readback(gfx::IntSize size,uint8_t * buffer,uint32_t buffer_size)324 void WebRenderAPI::Readback(gfx::IntSize size, uint8_t* buffer,
325                             uint32_t buffer_size) {
326   class Readback : public RendererEvent {
327    public:
328     explicit Readback(layers::SynchronousTask* aTask, gfx::IntSize aSize,
329                       uint8_t* aBuffer, uint32_t aBufferSize)
330         : mTask(aTask),
331           mSize(aSize),
332           mBuffer(aBuffer),
333           mBufferSize(aBufferSize) {
334       MOZ_COUNT_CTOR(Readback);
335     }
336 
337     ~Readback() { MOZ_COUNT_DTOR(Readback); }
338 
339     virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
340       aRenderThread.UpdateAndRender(aWindowId, /* aReadback */ true);
341       wr_renderer_readback(aRenderThread.GetRenderer(aWindowId)->GetRenderer(),
342                            mSize.width, mSize.height, mBuffer, mBufferSize);
343       layers::AutoCompleteTask complete(mTask);
344     }
345 
346     layers::SynchronousTask* mTask;
347     gfx::IntSize mSize;
348     uint8_t* mBuffer;
349     uint32_t mBufferSize;
350   };
351 
352   layers::SynchronousTask task("Readback");
353   auto event = MakeUnique<Readback>(&task, size, buffer, buffer_size);
354   // This event will be passed from wr_backend thread to renderer thread. That
355   // implies that all frame data have been processed when the renderer runs this
356   // read-back event. Then, we could make sure this read-back event gets the
357   // latest result.
358   RunOnRenderThread(Move(event));
359 
360   task.Wait();
361 }
362 
Pause()363 void WebRenderAPI::Pause() {
364   class PauseEvent : public RendererEvent {
365    public:
366     explicit PauseEvent(layers::SynchronousTask* aTask) : mTask(aTask) {
367       MOZ_COUNT_CTOR(PauseEvent);
368     }
369 
370     ~PauseEvent() { MOZ_COUNT_DTOR(PauseEvent); }
371 
372     virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
373       aRenderThread.Pause(aWindowId);
374       layers::AutoCompleteTask complete(mTask);
375     }
376 
377     layers::SynchronousTask* mTask;
378   };
379 
380   layers::SynchronousTask task("Pause");
381   auto event = MakeUnique<PauseEvent>(&task);
382   // This event will be passed from wr_backend thread to renderer thread. That
383   // implies that all frame data have been processed when the renderer runs this
384   // event.
385   RunOnRenderThread(Move(event));
386 
387   task.Wait();
388 }
389 
Resume()390 bool WebRenderAPI::Resume() {
391   class ResumeEvent : public RendererEvent {
392    public:
393     explicit ResumeEvent(layers::SynchronousTask* aTask, bool* aResult)
394         : mTask(aTask), mResult(aResult) {
395       MOZ_COUNT_CTOR(ResumeEvent);
396     }
397 
398     ~ResumeEvent() { MOZ_COUNT_DTOR(ResumeEvent); }
399 
400     virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
401       *mResult = aRenderThread.Resume(aWindowId);
402       layers::AutoCompleteTask complete(mTask);
403     }
404 
405     layers::SynchronousTask* mTask;
406     bool* mResult;
407   };
408 
409   bool result = false;
410   layers::SynchronousTask task("Resume");
411   auto event = MakeUnique<ResumeEvent>(&task, &result);
412   // This event will be passed from wr_backend thread to renderer thread. That
413   // implies that all frame data have been processed when the renderer runs this
414   // event.
415   RunOnRenderThread(Move(event));
416 
417   task.Wait();
418   return result;
419 }
420 
WaitFlushed()421 void WebRenderAPI::WaitFlushed() {
422   class WaitFlushedEvent : public RendererEvent {
423    public:
424     explicit WaitFlushedEvent(layers::SynchronousTask* aTask) : mTask(aTask) {
425       MOZ_COUNT_CTOR(WaitFlushedEvent);
426     }
427 
428     ~WaitFlushedEvent() { MOZ_COUNT_DTOR(WaitFlushedEvent); }
429 
430     virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
431       layers::AutoCompleteTask complete(mTask);
432     }
433 
434     layers::SynchronousTask* mTask;
435   };
436 
437   layers::SynchronousTask task("WaitFlushed");
438   auto event = MakeUnique<WaitFlushedEvent>(&task);
439   // This event will be passed from wr_backend thread to renderer thread. That
440   // implies that all frame data have been processed when the renderer runs this
441   // event.
442   RunOnRenderThread(Move(event));
443 
444   task.Wait();
445 }
446 
Capture()447 void WebRenderAPI::Capture() {
448   uint8_t bits = 3;                 // TODO: get from JavaScript
449   const char* path = "wr-capture";  // TODO: get from JavaScript
450   const char* border = "--------------------------\n";
451   printf("%s Capturing WR state to: %s\n%s", border, path, border);
452   wr_api_capture(mDocHandle, path, bits);
453 }
454 
Clear()455 void TransactionBuilder::Clear() {
456   wr_resource_updates_clear(mResourceUpdates);
457 }
458 
AddImage(ImageKey key,const ImageDescriptor & aDescriptor,wr::Vec<uint8_t> & aBytes)459 void TransactionBuilder::AddImage(ImageKey key,
460                                   const ImageDescriptor& aDescriptor,
461                                   wr::Vec<uint8_t>& aBytes) {
462   wr_resource_updates_add_image(mResourceUpdates, key, &aDescriptor,
463                                 &aBytes.inner);
464 }
465 
AddBlobImage(ImageKey key,const ImageDescriptor & aDescriptor,wr::Vec<uint8_t> & aBytes)466 void TransactionBuilder::AddBlobImage(ImageKey key,
467                                       const ImageDescriptor& aDescriptor,
468                                       wr::Vec<uint8_t>& aBytes) {
469   wr_resource_updates_add_blob_image(mResourceUpdates, key, &aDescriptor,
470                                      &aBytes.inner);
471 }
472 
AddExternalImage(ImageKey key,const ImageDescriptor & aDescriptor,ExternalImageId aExtID,wr::WrExternalImageBufferType aBufferType,uint8_t aChannelIndex)473 void TransactionBuilder::AddExternalImage(
474     ImageKey key, const ImageDescriptor& aDescriptor, ExternalImageId aExtID,
475     wr::WrExternalImageBufferType aBufferType, uint8_t aChannelIndex) {
476   wr_resource_updates_add_external_image(mResourceUpdates, key, &aDescriptor,
477                                          aExtID, aBufferType, aChannelIndex);
478 }
479 
AddExternalImageBuffer(ImageKey aKey,const ImageDescriptor & aDescriptor,ExternalImageId aHandle)480 void TransactionBuilder::AddExternalImageBuffer(
481     ImageKey aKey, const ImageDescriptor& aDescriptor,
482     ExternalImageId aHandle) {
483   auto channelIndex = 0;
484   AddExternalImage(aKey, aDescriptor, aHandle,
485                    wr::WrExternalImageBufferType::ExternalBuffer, channelIndex);
486 }
487 
UpdateImageBuffer(ImageKey aKey,const ImageDescriptor & aDescriptor,wr::Vec<uint8_t> & aBytes)488 void TransactionBuilder::UpdateImageBuffer(ImageKey aKey,
489                                            const ImageDescriptor& aDescriptor,
490                                            wr::Vec<uint8_t>& aBytes) {
491   wr_resource_updates_update_image(mResourceUpdates, aKey, &aDescriptor,
492                                    &aBytes.inner);
493 }
494 
UpdateBlobImage(ImageKey aKey,const ImageDescriptor & aDescriptor,wr::Vec<uint8_t> & aBytes,const wr::DeviceUintRect & aDirtyRect)495 void TransactionBuilder::UpdateBlobImage(ImageKey aKey,
496                                          const ImageDescriptor& aDescriptor,
497                                          wr::Vec<uint8_t>& aBytes,
498                                          const wr::DeviceUintRect& aDirtyRect) {
499   wr_resource_updates_update_blob_image(mResourceUpdates, aKey, &aDescriptor,
500                                         &aBytes.inner, aDirtyRect);
501 }
502 
UpdateExternalImage(ImageKey aKey,const ImageDescriptor & aDescriptor,ExternalImageId aExtID,wr::WrExternalImageBufferType aBufferType,uint8_t aChannelIndex)503 void TransactionBuilder::UpdateExternalImage(
504     ImageKey aKey, const ImageDescriptor& aDescriptor, ExternalImageId aExtID,
505     wr::WrExternalImageBufferType aBufferType, uint8_t aChannelIndex) {
506   wr_resource_updates_update_external_image(
507       mResourceUpdates, aKey, &aDescriptor, aExtID, aBufferType, aChannelIndex);
508 }
509 
DeleteImage(ImageKey aKey)510 void TransactionBuilder::DeleteImage(ImageKey aKey) {
511   wr_resource_updates_delete_image(mResourceUpdates, aKey);
512 }
513 
AddRawFont(wr::FontKey aKey,wr::Vec<uint8_t> & aBytes,uint32_t aIndex)514 void TransactionBuilder::AddRawFont(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes,
515                                     uint32_t aIndex) {
516   wr_resource_updates_add_raw_font(mResourceUpdates, aKey, &aBytes.inner,
517                                    aIndex);
518 }
519 
AddFontDescriptor(wr::FontKey aKey,wr::Vec<uint8_t> & aBytes,uint32_t aIndex)520 void TransactionBuilder::AddFontDescriptor(wr::FontKey aKey,
521                                            wr::Vec<uint8_t>& aBytes,
522                                            uint32_t aIndex) {
523   wr_resource_updates_add_font_descriptor(mResourceUpdates, aKey, &aBytes.inner,
524                                           aIndex);
525 }
526 
DeleteFont(wr::FontKey aKey)527 void TransactionBuilder::DeleteFont(wr::FontKey aKey) {
528   wr_resource_updates_delete_font(mResourceUpdates, aKey);
529 }
530 
AddFontInstance(wr::FontInstanceKey aKey,wr::FontKey aFontKey,float aGlyphSize,const wr::FontInstanceOptions * aOptions,const wr::FontInstancePlatformOptions * aPlatformOptions,wr::Vec<uint8_t> & aVariations)531 void TransactionBuilder::AddFontInstance(
532     wr::FontInstanceKey aKey, wr::FontKey aFontKey, float aGlyphSize,
533     const wr::FontInstanceOptions* aOptions,
534     const wr::FontInstancePlatformOptions* aPlatformOptions,
535     wr::Vec<uint8_t>& aVariations) {
536   wr_resource_updates_add_font_instance(mResourceUpdates, aKey, aFontKey,
537                                         aGlyphSize, aOptions, aPlatformOptions,
538                                         &aVariations.inner);
539 }
540 
DeleteFontInstance(wr::FontInstanceKey aKey)541 void TransactionBuilder::DeleteFontInstance(wr::FontInstanceKey aKey) {
542   wr_resource_updates_delete_font_instance(mResourceUpdates, aKey);
543 }
544 
545 class FrameStartTime : public RendererEvent {
546  public:
FrameStartTime(const TimeStamp & aTime)547   explicit FrameStartTime(const TimeStamp& aTime) : mTime(aTime) {
548     MOZ_COUNT_CTOR(FrameStartTime);
549   }
550 
~FrameStartTime()551   ~FrameStartTime() { MOZ_COUNT_DTOR(FrameStartTime); }
552 
Run(RenderThread & aRenderThread,WindowId aWindowId)553   virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
554     auto renderer = aRenderThread.GetRenderer(aWindowId);
555     if (renderer) {
556       renderer->SetFrameStartTime(mTime);
557     }
558   }
559 
560  private:
561   TimeStamp mTime;
562 };
563 
SetFrameStartTime(const TimeStamp & aTime)564 void WebRenderAPI::SetFrameStartTime(const TimeStamp& aTime) {
565   auto event = MakeUnique<FrameStartTime>(aTime);
566   RunOnRenderThread(Move(event));
567 }
568 
RunOnRenderThread(UniquePtr<RendererEvent> aEvent)569 void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) {
570   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
571   wr_api_send_external_event(mDocHandle, event);
572 }
573 
DisplayListBuilder(PipelineId aId,const wr::LayoutSize & aContentSize,size_t aCapacity)574 DisplayListBuilder::DisplayListBuilder(PipelineId aId,
575                                        const wr::LayoutSize& aContentSize,
576                                        size_t aCapacity) {
577   MOZ_COUNT_CTOR(DisplayListBuilder);
578   mWrState = wr_state_new(aId, aContentSize, aCapacity);
579 }
580 
~DisplayListBuilder()581 DisplayListBuilder::~DisplayListBuilder() {
582   MOZ_COUNT_DTOR(DisplayListBuilder);
583   wr_state_delete(mWrState);
584 }
585 
Save()586 void DisplayListBuilder::Save() { wr_dp_save(mWrState); }
Restore()587 void DisplayListBuilder::Restore() { wr_dp_restore(mWrState); }
ClearSave()588 void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState); }
Dump()589 void DisplayListBuilder::Dump() { wr_dump_display_list(mWrState); }
590 
Finalize(wr::LayoutSize & aOutContentSize,BuiltDisplayList & aOutDisplayList)591 void DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
592                                   BuiltDisplayList& aOutDisplayList) {
593   wr_api_finalize_builder(mWrState, &aOutContentSize, &aOutDisplayList.dl_desc,
594                           &aOutDisplayList.dl.inner);
595 }
596 
PushStackingContext(const wr::LayoutRect & aBounds,const WrAnimationProperty * aAnimation,const float * aOpacity,const gfx::Matrix4x4 * aTransform,wr::TransformStyle aTransformStyle,const gfx::Matrix4x4 * aPerspective,const wr::MixBlendMode & aMixBlendMode,const nsTArray<wr::WrFilterOp> & aFilters,bool aIsBackfaceVisible)597 void DisplayListBuilder::PushStackingContext(
598     const wr::LayoutRect& aBounds, const WrAnimationProperty* aAnimation,
599     const float* aOpacity, const gfx::Matrix4x4* aTransform,
600     wr::TransformStyle aTransformStyle, const gfx::Matrix4x4* aPerspective,
601     const wr::MixBlendMode& aMixBlendMode,
602     const nsTArray<wr::WrFilterOp>& aFilters, bool aIsBackfaceVisible) {
603   wr::LayoutTransform matrix;
604   if (aTransform) {
605     matrix = ToLayoutTransform(*aTransform);
606   }
607   const wr::LayoutTransform* maybeTransform = aTransform ? &matrix : nullptr;
608   wr::LayoutTransform perspective;
609   if (aPerspective) {
610     perspective = ToLayoutTransform(*aPerspective);
611   }
612   const wr::LayoutTransform* maybePerspective =
613       aPerspective ? &perspective : nullptr;
614   WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState,
615            Stringify(aBounds).c_str(),
616            aTransform ? Stringify(*aTransform).c_str() : "none");
617   wr_dp_push_stacking_context(mWrState, aBounds, aAnimation, aOpacity,
618                               maybeTransform, aTransformStyle, maybePerspective,
619                               aMixBlendMode, aFilters.Elements(),
620                               aFilters.Length(), aIsBackfaceVisible);
621 }
622 
PopStackingContext()623 void DisplayListBuilder::PopStackingContext() {
624   WRDL_LOG("PopStackingContext\n", mWrState);
625   wr_dp_pop_stacking_context(mWrState);
626 }
627 
DefineClip(const Maybe<wr::WrScrollId> & aAncestorScrollId,const Maybe<wr::WrClipId> & aAncestorClipId,const wr::LayoutRect & aClipRect,const nsTArray<wr::ComplexClipRegion> * aComplex,const wr::WrImageMask * aMask)628 wr::WrClipId DisplayListBuilder::DefineClip(
629     const Maybe<wr::WrScrollId>& aAncestorScrollId,
630     const Maybe<wr::WrClipId>& aAncestorClipId, const wr::LayoutRect& aClipRect,
631     const nsTArray<wr::ComplexClipRegion>* aComplex,
632     const wr::WrImageMask* aMask) {
633   const size_t* ancestorScrollId = nullptr;
634   if (aAncestorScrollId) {
635     ancestorScrollId = &(aAncestorScrollId.ref().id);
636   }
637   const size_t* ancestorClipId = nullptr;
638   if (aAncestorClipId) {
639     ancestorClipId = &(aAncestorClipId.ref().id);
640   }
641   size_t clip_id =
642       wr_dp_define_clip(mWrState, ancestorScrollId, ancestorClipId, aClipRect,
643                         aComplex ? aComplex->Elements() : nullptr,
644                         aComplex ? aComplex->Length() : 0, aMask);
645   WRDL_LOG(
646       "DefineClip id=%zu as=%s ac=%s r=%s m=%p b=%s complex=%zu\n", mWrState,
647       clip_id,
648       aAncestorScrollId ? Stringify(aAncestorScrollId.ref().id).c_str()
649                         : "(nil)",
650       aAncestorClipId ? Stringify(aAncestorClipId.ref().id).c_str() : "(nil)",
651       Stringify(aClipRect).c_str(), aMask,
652       aMask ? Stringify(aMask->rect).c_str() : "none",
653       aComplex ? aComplex->Length() : 0);
654   return wr::WrClipId{clip_id};
655 }
656 
PushClip(const wr::WrClipId & aClipId,const DisplayItemClipChain * aParent)657 void DisplayListBuilder::PushClip(const wr::WrClipId& aClipId,
658                                   const DisplayItemClipChain* aParent) {
659   wr_dp_push_clip(mWrState, aClipId.id);
660   WRDL_LOG("PushClip id=%zu\n", mWrState, aClipId.id);
661   if (!aParent) {
662     mClipStack.push_back(wr::ScrollOrClipId(aClipId));
663   } else {
664     PushCacheOverride(aParent, aClipId);
665   }
666 }
667 
PopClip(const DisplayItemClipChain * aParent)668 void DisplayListBuilder::PopClip(const DisplayItemClipChain* aParent) {
669   WRDL_LOG("PopClip\n", mWrState);
670   if (!aParent) {
671     MOZ_ASSERT(mClipStack.back().is<wr::WrClipId>());
672     mClipStack.pop_back();
673   } else {
674     PopCacheOverride(aParent);
675   }
676   wr_dp_pop_clip(mWrState);
677 }
678 
PushCacheOverride(const DisplayItemClipChain * aParent,const wr::WrClipId & aClipId)679 void DisplayListBuilder::PushCacheOverride(const DisplayItemClipChain* aParent,
680                                            const wr::WrClipId& aClipId) {
681   // We need to walk the entire clip chain from aParent up and install aClipId
682   // as an override for all of them. This is so that nested display items end up
683   // with the correct parent clip regardless of which outside clip their clip
684   // chains are attached to. Example:
685   // nsDisplayStickyPosition with clipChain D -> C -> B -> A -> nullptr
686   //   nsDisplayItem with clipChain F -> E -> B -> A -> nullptr
687   // In this case the sticky clip that is generated by the sticky display item
688   // is defined as a child of D, which is a child of C and so on. When we go
689   // to define E for the nested display item, we want to make sure that it
690   // is defined as a child of sticky clip, regardless of which of {D, C, B, A}
691   // it has as a parent. {D, C, B, A} are what I refer to as the "outside clips"
692   // because they are "outside" the sticky clip, and if we define E as a child
693   // of any of those clips directly, then we end up losing the sticky clip from
694   // the WR clip chain of the nested item. This is why we install cache
695   // overrides for all of them so that when we walk the nested item's clip chain
696   // from E to B we discover that really we want to use the sticky clip as E's
697   // parent.
698   for (const DisplayItemClipChain* i = aParent; i; i = i->mParent) {
699     auto it = mCacheOverride.insert({i, std::vector<wr::WrClipId>()});
700     it.first->second.push_back(aClipId);
701     WRDL_LOG("Pushing override %p -> %zu\n", mWrState, i, aClipId.id);
702   }
703 }
704 
PopCacheOverride(const DisplayItemClipChain * aParent)705 void DisplayListBuilder::PopCacheOverride(const DisplayItemClipChain* aParent) {
706   for (const DisplayItemClipChain* i = aParent; i; i = i->mParent) {
707     auto it = mCacheOverride.find(i);
708     MOZ_ASSERT(it != mCacheOverride.end());
709     MOZ_ASSERT(!(it->second.empty()));
710     WRDL_LOG("Popping override %p -> %zu\n", mWrState, i, it->second.back().id);
711     it->second.pop_back();
712     if (it->second.empty()) {
713       mCacheOverride.erase(it);
714     }
715   }
716 }
717 
GetCacheOverride(const DisplayItemClipChain * aParent)718 Maybe<wr::WrClipId> DisplayListBuilder::GetCacheOverride(
719     const DisplayItemClipChain* aParent) {
720   auto it = mCacheOverride.find(aParent);
721   return it == mCacheOverride.end() ? Nothing() : Some(it->second.back());
722 }
723 
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)724 wr::WrStickyId DisplayListBuilder::DefineStickyFrame(
725     const wr::LayoutRect& aContentRect, const float* aTopMargin,
726     const float* aRightMargin, const float* aBottomMargin,
727     const float* aLeftMargin, const StickyOffsetBounds& aVerticalBounds,
728     const StickyOffsetBounds& aHorizontalBounds,
729     const wr::LayoutVector2D& aAppliedOffset) {
730   size_t id = wr_dp_define_sticky_frame(
731       mWrState, aContentRect, aTopMargin, aRightMargin, aBottomMargin,
732       aLeftMargin, aVerticalBounds, aHorizontalBounds, aAppliedOffset);
733   WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n",
734            mWrState, id, Stringify(aContentRect).c_str(),
735            aTopMargin ? Stringify(*aTopMargin).c_str() : "none",
736            aRightMargin ? Stringify(*aRightMargin).c_str() : "none",
737            aBottomMargin ? Stringify(*aBottomMargin).c_str() : "none",
738            aLeftMargin ? Stringify(*aLeftMargin).c_str() : "none",
739            Stringify(aVerticalBounds).c_str(),
740            Stringify(aHorizontalBounds).c_str(),
741            Stringify(aAppliedOffset).c_str());
742   return wr::WrStickyId{id};
743 }
744 
PushStickyFrame(const wr::WrStickyId & aStickyId,const DisplayItemClipChain * aParent)745 void DisplayListBuilder::PushStickyFrame(const wr::WrStickyId& aStickyId,
746                                          const DisplayItemClipChain* aParent) {
747   wr_dp_push_clip(mWrState, aStickyId.id);
748   WRDL_LOG("PushSticky id=%zu\n", mWrState, aStickyId.id);
749   // inside WR, a sticky id is just a regular clip id. so we can do some
750   // handwaving here and turn the WrStickyId into a WrclipId and treat it
751   // like any other out-of-band clip.
752   wr::WrClipId stickyIdAsClipId;
753   stickyIdAsClipId.id = aStickyId.id;
754   PushCacheOverride(aParent, stickyIdAsClipId);
755 }
756 
PopStickyFrame(const DisplayItemClipChain * aParent)757 void DisplayListBuilder::PopStickyFrame(const DisplayItemClipChain* aParent) {
758   WRDL_LOG("PopSticky\n", mWrState);
759   PopCacheOverride(aParent);
760   wr_dp_pop_clip(mWrState);
761 }
762 
GetScrollIdForDefinedScrollLayer(layers::FrameMetrics::ViewID aViewId) const763 Maybe<wr::WrScrollId> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
764     layers::FrameMetrics::ViewID aViewId) const {
765   if (aViewId == layers::FrameMetrics::NULL_SCROLL_ID) {
766     return Some(wr::WrScrollId{0});
767   }
768 
769   auto it = mScrollIds.find(aViewId);
770   if (it == mScrollIds.end()) {
771     return Nothing();
772   }
773 
774   return Some(it->second);
775 }
776 
DefineScrollLayer(const layers::FrameMetrics::ViewID & aViewId,const Maybe<wr::WrScrollId> & aAncestorScrollId,const Maybe<wr::WrClipId> & aAncestorClipId,const wr::LayoutRect & aContentRect,const wr::LayoutRect & aClipRect)777 wr::WrScrollId DisplayListBuilder::DefineScrollLayer(
778     const layers::FrameMetrics::ViewID& aViewId,
779     const Maybe<wr::WrScrollId>& aAncestorScrollId,
780     const Maybe<wr::WrClipId>& aAncestorClipId,
781     const wr::LayoutRect& aContentRect, const wr::LayoutRect& aClipRect) {
782   WRDL_LOG(
783       "DefineScrollLayer id=%" PRIu64 " as=%s ac=%s co=%s cl=%s\n", mWrState,
784       aViewId,
785       aAncestorScrollId ? Stringify(aAncestorScrollId.ref().id).c_str()
786                         : "(nil)",
787       aAncestorClipId ? Stringify(aAncestorClipId.ref().id).c_str() : "(nil)",
788       Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
789 
790   auto it = mScrollIds.find(aViewId);
791   if (it != mScrollIds.end()) {
792     return it->second;
793   }
794 
795   // We haven't defined aViewId before, so let's define it now.
796   size_t numericScrollId = wr_dp_define_scroll_layer(
797       mWrState, aViewId, aAncestorScrollId ? &(aAncestorScrollId->id) : nullptr,
798       aAncestorClipId ? &(aAncestorClipId->id) : nullptr, aContentRect,
799       aClipRect);
800   auto wrScrollId = wr::WrScrollId{numericScrollId};
801   mScrollIds[aViewId] = wrScrollId;
802   return wrScrollId;
803 }
804 
PushScrollLayer(const wr::WrScrollId & aScrollId)805 void DisplayListBuilder::PushScrollLayer(const wr::WrScrollId& aScrollId) {
806   WRDL_LOG("PushScrollLayer id=%zu\n", mWrState, aScrollId.id);
807   wr_dp_push_scroll_layer(mWrState, aScrollId.id);
808   mClipStack.push_back(wr::ScrollOrClipId(aScrollId));
809 }
810 
PopScrollLayer()811 void DisplayListBuilder::PopScrollLayer() {
812   MOZ_ASSERT(mClipStack.back().is<wr::WrScrollId>());
813   WRDL_LOG("PopScrollLayer id=%zu\n", mWrState,
814            mClipStack.back().as<wr::WrScrollId>().id);
815   mClipStack.pop_back();
816   wr_dp_pop_scroll_layer(mWrState);
817 }
818 
PushClipAndScrollInfo(const wr::WrScrollId & aScrollId,const wr::WrClipId * aClipId)819 void DisplayListBuilder::PushClipAndScrollInfo(const wr::WrScrollId& aScrollId,
820                                                const wr::WrClipId* aClipId) {
821   WRDL_LOG("PushClipAndScroll s=%zu c=%s\n", mWrState, aScrollId.id,
822            aClipId ? Stringify(aClipId->id).c_str() : "none");
823   wr_dp_push_clip_and_scroll_info(mWrState, aScrollId.id,
824                                   aClipId ? &(aClipId->id) : nullptr);
825   mClipStack.push_back(wr::ScrollOrClipId(aScrollId));
826 }
827 
PopClipAndScrollInfo()828 void DisplayListBuilder::PopClipAndScrollInfo() {
829   MOZ_ASSERT(mClipStack.back().is<wr::WrScrollId>());
830   WRDL_LOG("PopClipAndScroll\n", mWrState);
831   mClipStack.pop_back();
832   wr_dp_pop_clip_and_scroll_info(mWrState);
833 }
834 
PushRect(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::ColorF & aColor)835 void DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds,
836                                   const wr::LayoutRect& aClip,
837                                   bool aIsBackfaceVisible,
838                                   const wr::ColorF& aColor) {
839   WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState, Stringify(aBounds).c_str(),
840            Stringify(aClip).c_str(), Stringify(aColor).c_str());
841   wr_dp_push_rect(mWrState, aBounds, aClip, aIsBackfaceVisible, aColor);
842 }
843 
PushClearRect(const wr::LayoutRect & aBounds)844 void DisplayListBuilder::PushClearRect(const wr::LayoutRect& aBounds) {
845   WRDL_LOG("PushClearRect b=%s\n", mWrState, Stringify(aBounds).c_str());
846   wr_dp_push_clear_rect(mWrState, aBounds);
847 }
848 
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)849 void DisplayListBuilder::PushLinearGradient(
850     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
851     bool aIsBackfaceVisible, const wr::LayoutPoint& aStartPoint,
852     const wr::LayoutPoint& aEndPoint, const nsTArray<wr::GradientStop>& aStops,
853     wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize,
854     const wr::LayoutSize aTileSpacing) {
855   wr_dp_push_linear_gradient(
856       mWrState, aBounds, aClip, aIsBackfaceVisible, aStartPoint, aEndPoint,
857       aStops.Elements(), aStops.Length(), aExtendMode, aTileSize, aTileSpacing);
858 }
859 
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)860 void DisplayListBuilder::PushRadialGradient(
861     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
862     bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter,
863     const wr::LayoutSize& aRadius, const nsTArray<wr::GradientStop>& aStops,
864     wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize,
865     const wr::LayoutSize aTileSpacing) {
866   wr_dp_push_radial_gradient(
867       mWrState, aBounds, aClip, aIsBackfaceVisible, aCenter, aRadius,
868       aStops.Elements(), aStops.Length(), aExtendMode, aTileSize, aTileSpacing);
869 }
870 
PushImage(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,wr::ImageRendering aFilter,wr::ImageKey aImage,bool aPremultipliedAlpha)871 void DisplayListBuilder::PushImage(const wr::LayoutRect& aBounds,
872                                    const wr::LayoutRect& aClip,
873                                    bool aIsBackfaceVisible,
874                                    wr::ImageRendering aFilter,
875                                    wr::ImageKey aImage,
876                                    bool aPremultipliedAlpha) {
877   wr::LayoutSize size;
878   size.width = aBounds.size.width;
879   size.height = aBounds.size.height;
880   PushImage(aBounds, aClip, aIsBackfaceVisible, size, size, aFilter, aImage,
881             aPremultipliedAlpha);
882 }
883 
PushImage(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)884 void DisplayListBuilder::PushImage(
885     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
886     bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize,
887     const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter,
888     wr::ImageKey aImage, bool aPremultipliedAlpha) {
889   WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState,
890            Stringify(aBounds).c_str(), Stringify(aClip).c_str(),
891            Stringify(aStretchSize).c_str(), Stringify(aTileSpacing).c_str());
892   wr_dp_push_image(mWrState, aBounds, aClip, aIsBackfaceVisible, aStretchSize,
893                    aTileSpacing, aFilter, aImage, aPremultipliedAlpha);
894 }
895 
PushYCbCrPlanarImage(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,wr::ImageKey aImageChannel0,wr::ImageKey aImageChannel1,wr::ImageKey aImageChannel2,wr::WrYuvColorSpace aColorSpace,wr::ImageRendering aRendering)896 void DisplayListBuilder::PushYCbCrPlanarImage(
897     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
898     bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
899     wr::ImageKey aImageChannel1, wr::ImageKey aImageChannel2,
900     wr::WrYuvColorSpace aColorSpace, wr::ImageRendering aRendering) {
901   wr_dp_push_yuv_planar_image(mWrState, aBounds, aClip, aIsBackfaceVisible,
902                               aImageChannel0, aImageChannel1, aImageChannel2,
903                               aColorSpace, aRendering);
904 }
905 
PushNV12Image(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,wr::ImageKey aImageChannel0,wr::ImageKey aImageChannel1,wr::WrYuvColorSpace aColorSpace,wr::ImageRendering aRendering)906 void DisplayListBuilder::PushNV12Image(const wr::LayoutRect& aBounds,
907                                        const wr::LayoutRect& aClip,
908                                        bool aIsBackfaceVisible,
909                                        wr::ImageKey aImageChannel0,
910                                        wr::ImageKey aImageChannel1,
911                                        wr::WrYuvColorSpace aColorSpace,
912                                        wr::ImageRendering aRendering) {
913   wr_dp_push_yuv_NV12_image(mWrState, aBounds, aClip, aIsBackfaceVisible,
914                             aImageChannel0, aImageChannel1, aColorSpace,
915                             aRendering);
916 }
917 
PushYCbCrInterleavedImage(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,wr::ImageKey aImageChannel0,wr::WrYuvColorSpace aColorSpace,wr::ImageRendering aRendering)918 void DisplayListBuilder::PushYCbCrInterleavedImage(
919     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
920     bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
921     wr::WrYuvColorSpace aColorSpace, wr::ImageRendering aRendering) {
922   wr_dp_push_yuv_interleaved_image(mWrState, aBounds, aClip, aIsBackfaceVisible,
923                                    aImageChannel0, aColorSpace, aRendering);
924 }
925 
PushIFrame(const wr::LayoutRect & aBounds,bool aIsBackfaceVisible,PipelineId aPipeline)926 void DisplayListBuilder::PushIFrame(const wr::LayoutRect& aBounds,
927                                     bool aIsBackfaceVisible,
928                                     PipelineId aPipeline) {
929   wr_dp_push_iframe(mWrState, aBounds, aIsBackfaceVisible, aPipeline);
930 }
931 
PushBorder(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::BorderWidths & aWidths,const Range<const wr::BorderSide> & aSides,const wr::BorderRadius & aRadius)932 void DisplayListBuilder::PushBorder(const wr::LayoutRect& aBounds,
933                                     const wr::LayoutRect& aClip,
934                                     bool aIsBackfaceVisible,
935                                     const wr::BorderWidths& aWidths,
936                                     const Range<const wr::BorderSide>& aSides,
937                                     const wr::BorderRadius& aRadius) {
938   MOZ_ASSERT(aSides.length() == 4);
939   if (aSides.length() != 4) {
940     return;
941   }
942   wr_dp_push_border(mWrState, aBounds, aClip, aIsBackfaceVisible, aWidths,
943                     aSides[0], aSides[1], aSides[2], aSides[3], aRadius);
944 }
945 
PushBorderImage(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::BorderWidths & aWidths,wr::ImageKey aImage,const wr::NinePatchDescriptor & aPatch,const wr::SideOffsets2D<float> & aOutset,const wr::RepeatMode & aRepeatHorizontal,const wr::RepeatMode & aRepeatVertical)946 void DisplayListBuilder::PushBorderImage(
947     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
948     bool aIsBackfaceVisible, const wr::BorderWidths& aWidths,
949     wr::ImageKey aImage, const wr::NinePatchDescriptor& aPatch,
950     const wr::SideOffsets2D<float>& aOutset,
951     const wr::RepeatMode& aRepeatHorizontal,
952     const wr::RepeatMode& aRepeatVertical) {
953   wr_dp_push_border_image(mWrState, aBounds, aClip, aIsBackfaceVisible, aWidths,
954                           aImage, aPatch, aOutset, aRepeatHorizontal,
955                           aRepeatVertical);
956 }
957 
PushBorderGradient(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::BorderWidths & aWidths,const wr::LayoutPoint & aStartPoint,const wr::LayoutPoint & aEndPoint,const nsTArray<wr::GradientStop> & aStops,wr::ExtendMode aExtendMode,const wr::SideOffsets2D<float> & aOutset)958 void DisplayListBuilder::PushBorderGradient(
959     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
960     bool aIsBackfaceVisible, const wr::BorderWidths& aWidths,
961     const wr::LayoutPoint& aStartPoint, const wr::LayoutPoint& aEndPoint,
962     const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
963     const wr::SideOffsets2D<float>& aOutset) {
964   wr_dp_push_border_gradient(mWrState, aBounds, aClip, aIsBackfaceVisible,
965                              aWidths, aStartPoint, aEndPoint, aStops.Elements(),
966                              aStops.Length(), aExtendMode, aOutset);
967 }
968 
PushBorderRadialGradient(const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::BorderWidths & aWidths,const wr::LayoutPoint & aCenter,const wr::LayoutSize & aRadius,const nsTArray<wr::GradientStop> & aStops,wr::ExtendMode aExtendMode,const wr::SideOffsets2D<float> & aOutset)969 void DisplayListBuilder::PushBorderRadialGradient(
970     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
971     bool aIsBackfaceVisible, const wr::BorderWidths& aWidths,
972     const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
973     const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
974     const wr::SideOffsets2D<float>& aOutset) {
975   wr_dp_push_border_radial_gradient(
976       mWrState, aBounds, aClip, aIsBackfaceVisible, aWidths, aCenter, aRadius,
977       aStops.Elements(), aStops.Length(), aExtendMode, aOutset);
978 }
979 
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)980 void DisplayListBuilder::PushText(const wr::LayoutRect& aBounds,
981                                   const wr::LayoutRect& aClip,
982                                   bool aIsBackfaceVisible,
983                                   const wr::ColorF& aColor,
984                                   wr::FontInstanceKey aFontKey,
985                                   Range<const wr::GlyphInstance> aGlyphBuffer,
986                                   const wr::GlyphOptions* aGlyphOptions) {
987   wr_dp_push_text(mWrState, aBounds, aClip, aIsBackfaceVisible, aColor,
988                   aFontKey, &aGlyphBuffer[0], aGlyphBuffer.length(),
989                   aGlyphOptions);
990 }
991 
PushLine(const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::Line & aLine)992 void DisplayListBuilder::PushLine(const wr::LayoutRect& aClip,
993                                   bool aIsBackfaceVisible,
994                                   const wr::Line& aLine) {
995   wr_dp_push_line(mWrState, &aClip, aIsBackfaceVisible, &aLine.bounds,
996                   aLine.wavyLineThickness, aLine.orientation, &aLine.color,
997                   aLine.style);
998 }
999 
PushShadow(const wr::LayoutRect & aRect,const wr::LayoutRect & aClip,bool aIsBackfaceVisible,const wr::Shadow & aShadow)1000 void DisplayListBuilder::PushShadow(const wr::LayoutRect& aRect,
1001                                     const wr::LayoutRect& aClip,
1002                                     bool aIsBackfaceVisible,
1003                                     const wr::Shadow& aShadow) {
1004   wr_dp_push_shadow(mWrState, aRect, aClip, aIsBackfaceVisible, aShadow);
1005 }
1006 
PopAllShadows()1007 void DisplayListBuilder::PopAllShadows() { wr_dp_pop_all_shadows(mWrState); }
1008 
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)1009 void DisplayListBuilder::PushBoxShadow(
1010     const wr::LayoutRect& aRect, const wr::LayoutRect& aClip,
1011     bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds,
1012     const wr::LayoutVector2D& aOffset, const wr::ColorF& aColor,
1013     const float& aBlurRadius, const float& aSpreadRadius,
1014     const wr::BorderRadius& aBorderRadius,
1015     const wr::BoxShadowClipMode& aClipMode) {
1016   wr_dp_push_box_shadow(mWrState, aRect, aClip, aIsBackfaceVisible, aBoxBounds,
1017                         aOffset, aColor, aBlurRadius, aSpreadRadius,
1018                         aBorderRadius, aClipMode);
1019 }
1020 
TopmostClipId()1021 Maybe<wr::WrClipId> DisplayListBuilder::TopmostClipId() {
1022   for (auto it = mClipStack.crbegin(); it != mClipStack.crend(); it++) {
1023     if (it->is<wr::WrClipId>()) {
1024       return Some(it->as<wr::WrClipId>());
1025     }
1026   }
1027   return Nothing();
1028 }
1029 
TopmostScrollId()1030 wr::WrScrollId DisplayListBuilder::TopmostScrollId() {
1031   for (auto it = mClipStack.crbegin(); it != mClipStack.crend(); it++) {
1032     if (it->is<wr::WrScrollId>()) {
1033       return it->as<wr::WrScrollId>();
1034     }
1035   }
1036   return wr::WrScrollId{0};
1037 }
1038 
TopmostIsClip()1039 bool DisplayListBuilder::TopmostIsClip() {
1040   if (mClipStack.empty()) {
1041     return false;
1042   }
1043   return mClipStack.back().is<wr::WrClipId>();
1044 }
1045 
SetHitTestInfo(const layers::FrameMetrics::ViewID & aScrollId,gfx::CompositorHitTestInfo aHitInfo)1046 void DisplayListBuilder::SetHitTestInfo(
1047     const layers::FrameMetrics::ViewID& aScrollId,
1048     gfx::CompositorHitTestInfo aHitInfo) {
1049   static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint16_t),
1050                 "CompositorHitTestInfo should be u16-sized");
1051   wr_set_item_tag(mWrState, aScrollId, static_cast<uint16_t>(aHitInfo));
1052 }
1053 
ClearHitTestInfo()1054 void DisplayListBuilder::ClearHitTestInfo() { wr_clear_item_tag(mWrState); }
1055 
1056 }  // namespace wr
1057 }  // namespace mozilla
1058