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