Backed out 4 changesets (bug 1879154) for causing bustage on nsUserCharacteristics...
[gecko.git] / gfx / webrender_bindings / WebRenderAPI.cpp
blob09a024a8979eae69fc9aa5f6b696f3af0f1cd3cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WebRenderAPI.h"
9 #include "mozilla/Logging.h"
10 #include "mozilla/ipc/ByteBuf.h"
11 #include "mozilla/webrender/RendererOGL.h"
12 #include "mozilla/gfx/gfxVars.h"
13 #include "mozilla/layers/CompositorThread.h"
14 #include "mozilla/StaticPrefs_gfx.h"
15 #include "mozilla/StaticPrefs_webgl.h"
16 #include "mozilla/ToString.h"
17 #include "mozilla/webrender/RenderCompositor.h"
18 #include "mozilla/widget/CompositorWidget.h"
19 #include "mozilla/layers/SynchronousTask.h"
20 #include "nsThreadUtils.h"
21 #include "TextDrawTarget.h"
22 #include "malloc_decls.h"
23 #include "GLContext.h"
25 static mozilla::LazyLogModule sWrDLLog("wr.dl");
26 #define WRDL_LOG(...) \
27 MOZ_LOG(sWrDLLog, LogLevel::Debug, ("WRDL(%p): " __VA_ARGS__))
29 namespace mozilla {
30 using namespace layers;
32 namespace wr {
34 MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf)
35 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(WebRenderMallocEnclosingSizeOf)
37 class NewRenderer : public RendererEvent {
38 public:
39 NewRenderer(wr::DocumentHandle** aDocHandle,
40 layers::CompositorBridgeParent* aBridge,
41 WebRenderBackend* aBackend, WebRenderCompositor* aCompositor,
42 int32_t* aMaxTextureSize, bool* aUseANGLE, bool* aUseDComp,
43 bool* aUseTripleBuffering, bool* aSupportsExternalBufferTextures,
44 RefPtr<widget::CompositorWidget>&& aWidget,
45 layers::SynchronousTask* aTask, LayoutDeviceIntSize aSize,
46 layers::WindowKind aWindowKind, layers::SyncHandle* aHandle,
47 nsACString* aError)
48 : mDocHandle(aDocHandle),
49 mBackend(aBackend),
50 mCompositor(aCompositor),
51 mMaxTextureSize(aMaxTextureSize),
52 mUseANGLE(aUseANGLE),
53 mUseDComp(aUseDComp),
54 mUseTripleBuffering(aUseTripleBuffering),
55 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures),
56 mBridge(aBridge),
57 mCompositorWidget(std::move(aWidget)),
58 mTask(aTask),
59 mSize(aSize),
60 mWindowKind(aWindowKind),
61 mSyncHandle(aHandle),
62 mError(aError) {
63 MOZ_COUNT_CTOR(NewRenderer);
66 MOZ_COUNTED_DTOR(NewRenderer)
68 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
69 layers::AutoCompleteTask complete(mTask);
71 UniquePtr<RenderCompositor> compositor =
72 RenderCompositor::Create(std::move(mCompositorWidget), *mError);
73 if (!compositor) {
74 if (!mError->IsEmpty()) {
75 gfxCriticalNote << mError->BeginReading();
77 return;
80 compositor->MakeCurrent();
82 *mBackend = compositor->BackendType();
83 *mCompositor = compositor->CompositorType();
84 *mUseANGLE = compositor->UseANGLE();
85 *mUseDComp = compositor->UseDComp();
86 *mUseTripleBuffering = compositor->UseTripleBuffering();
87 *mSupportsExternalBufferTextures =
88 compositor->SupportsExternalBufferTextures();
90 // Only allow the panic on GL error functionality in nightly builds,
91 // since it (deliberately) crashes the GPU process if any GL call
92 // returns an error code.
93 bool panic_on_gl_error = false;
94 #ifdef NIGHTLY_BUILD
95 panic_on_gl_error =
96 StaticPrefs::gfx_webrender_panic_on_gl_error_AtStartup();
97 #endif
99 bool isMainWindow = true; // TODO!
100 bool supportLowPriorityTransactions = isMainWindow;
101 bool supportLowPriorityThreadpool =
102 supportLowPriorityTransactions &&
103 StaticPrefs::gfx_webrender_enable_low_priority_pool();
104 wr::Renderer* wrRenderer = nullptr;
105 char* errorMessage = nullptr;
106 int picTileWidth = StaticPrefs::gfx_webrender_picture_tile_width();
107 int picTileHeight = StaticPrefs::gfx_webrender_picture_tile_height();
108 auto* swgl = compositor->swgl();
109 auto* gl = (compositor->gl() && !swgl) ? compositor->gl() : nullptr;
110 auto* progCache = (aRenderThread.GetProgramCache() && !swgl)
111 ? aRenderThread.GetProgramCache()->Raw()
112 : nullptr;
113 auto* shaders = (aRenderThread.GetShaders() && !swgl)
114 ? aRenderThread.GetShaders()->RawShaders()
115 : nullptr;
117 // Check That if we are not using SWGL, we have at least a GL or GLES 3.0
118 // context.
119 if (gl && !swgl) {
120 bool versionCheck =
121 gl->IsAtLeast(gl::ContextProfile::OpenGLCore, 300) ||
122 gl->IsAtLeast(gl::ContextProfile::OpenGLCompatibility, 300) ||
123 gl->IsAtLeast(gl::ContextProfile::OpenGLES, 300);
125 if (!versionCheck) {
126 gfxCriticalNote << "GL context version (" << gl->Version()
127 << ") insufficent for hardware WebRender";
129 mError->AssignASCII("GL context version insufficient");
130 return;
134 if (!wr_window_new(
135 aWindowId, mSize.width, mSize.height,
136 mWindowKind == WindowKind::MAIN, supportLowPriorityTransactions,
137 supportLowPriorityThreadpool, gfx::gfxVars::UseGLSwizzle(),
138 gfx::gfxVars::UseWebRenderScissoredCacheClears(), swgl, gl,
139 compositor->SurfaceOriginIsTopLeft(), progCache, shaders,
140 aRenderThread.ThreadPool().Raw(),
141 aRenderThread.ThreadPoolLP().Raw(), &WebRenderMallocSizeOf,
142 &WebRenderMallocEnclosingSizeOf, 0, compositor.get(),
143 compositor->ShouldUseNativeCompositor(),
144 compositor->UsePartialPresent(),
145 compositor->GetMaxPartialPresentRects(),
146 compositor->ShouldDrawPreviousPartialPresentRegions(), mDocHandle,
147 &wrRenderer, mMaxTextureSize, &errorMessage,
148 StaticPrefs::gfx_webrender_enable_gpu_markers_AtStartup(),
149 panic_on_gl_error, picTileWidth, picTileHeight,
150 gfx::gfxVars::WebRenderRequiresHardwareDriver(),
151 StaticPrefs::gfx_webrender_low_quality_pinch_zoom_AtStartup(),
152 StaticPrefs::gfx_webrender_max_shared_surface_size_AtStartup(),
153 StaticPrefs::gfx_webrender_enable_subpixel_aa_AtStartup())) {
154 // wr_window_new puts a message into gfxCriticalNote if it returns false
155 MOZ_ASSERT(errorMessage);
156 mError->AssignASCII(errorMessage);
157 wr_api_free_error_msg(errorMessage);
158 return;
160 MOZ_ASSERT(wrRenderer);
162 RefPtr<RenderThread> thread = &aRenderThread;
163 auto renderer =
164 MakeUnique<RendererOGL>(std::move(thread), std::move(compositor),
165 aWindowId, wrRenderer, mBridge);
166 if (wrRenderer && renderer) {
167 wr::WrExternalImageHandler handler = renderer->GetExternalImageHandler();
168 wr_renderer_set_external_image_handler(wrRenderer, &handler);
171 if (renderer) {
172 layers::SyncObjectHost* syncObj = renderer->GetSyncObject();
173 if (syncObj) {
174 *mSyncHandle = syncObj->GetSyncHandle();
178 aRenderThread.AddRenderer(aWindowId, std::move(renderer));
181 private:
182 wr::DocumentHandle** mDocHandle;
183 WebRenderBackend* mBackend;
184 WebRenderCompositor* mCompositor;
185 int32_t* mMaxTextureSize;
186 bool* mUseANGLE;
187 bool* mUseDComp;
188 bool* mUseTripleBuffering;
189 bool* mSupportsExternalBufferTextures;
190 layers::CompositorBridgeParent* mBridge;
191 RefPtr<widget::CompositorWidget> mCompositorWidget;
192 layers::SynchronousTask* mTask;
193 LayoutDeviceIntSize mSize;
194 layers::WindowKind mWindowKind;
195 layers::SyncHandle* mSyncHandle;
196 nsACString* mError;
199 class RemoveRenderer : public RendererEvent {
200 public:
201 explicit RemoveRenderer(layers::SynchronousTask* aTask) : mTask(aTask) {
202 MOZ_COUNT_CTOR(RemoveRenderer);
205 MOZ_COUNTED_DTOR_OVERRIDE(RemoveRenderer)
207 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
208 aRenderThread.RemoveRenderer(aWindowId);
209 layers::AutoCompleteTask complete(mTask);
212 private:
213 layers::SynchronousTask* mTask;
216 TransactionBuilder::TransactionBuilder(WebRenderAPI* aApi,
217 bool aUseSceneBuilderThread)
218 : mUseSceneBuilderThread(aUseSceneBuilderThread),
219 mApiBackend(aApi->GetBackendType()),
220 mOwnsData(true) {
221 mTxn = wr_transaction_new(mUseSceneBuilderThread);
224 TransactionBuilder::TransactionBuilder(WebRenderAPI* aApi, Transaction* aTxn,
225 bool aUseSceneBuilderThread,
226 bool aOwnsData)
227 : mTxn(aTxn),
228 mUseSceneBuilderThread(aUseSceneBuilderThread),
229 mApiBackend(aApi->GetBackendType()),
230 mOwnsData(aOwnsData) {}
232 TransactionBuilder::~TransactionBuilder() {
233 if (mOwnsData) {
234 wr_transaction_delete(mTxn);
238 void TransactionBuilder::SetLowPriority(bool aIsLowPriority) {
239 wr_transaction_set_low_priority(mTxn, aIsLowPriority);
242 void TransactionBuilder::UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch) {
243 wr_transaction_update_epoch(mTxn, aPipelineId, aEpoch);
246 void TransactionBuilder::SetRootPipeline(PipelineId aPipelineId) {
247 wr_transaction_set_root_pipeline(mTxn, aPipelineId);
250 void TransactionBuilder::RemovePipeline(PipelineId aPipelineId) {
251 wr_transaction_remove_pipeline(mTxn, aPipelineId);
254 void TransactionBuilder::SetDisplayList(
255 Epoch aEpoch, wr::WrPipelineId pipeline_id,
256 wr::BuiltDisplayListDescriptor dl_descriptor,
257 wr::Vec<uint8_t>& dl_items_data, wr::Vec<uint8_t>& dl_cache_data,
258 wr::Vec<uint8_t>& dl_spatial_tree) {
259 wr_transaction_set_display_list(mTxn, aEpoch, pipeline_id, dl_descriptor,
260 &dl_items_data.inner, &dl_cache_data.inner,
261 &dl_spatial_tree.inner);
264 void TransactionBuilder::ClearDisplayList(Epoch aEpoch,
265 wr::WrPipelineId aPipelineId) {
266 wr_transaction_clear_display_list(mTxn, aEpoch, aPipelineId);
269 void TransactionBuilder::GenerateFrame(const VsyncId& aVsyncId,
270 wr::RenderReasons aReasons) {
271 wr_transaction_generate_frame(mTxn, aVsyncId.mId, aReasons);
274 void TransactionBuilder::InvalidateRenderedFrame(wr::RenderReasons aReasons) {
275 wr_transaction_invalidate_rendered_frame(mTxn, aReasons);
278 bool TransactionBuilder::IsEmpty() const {
279 return wr_transaction_is_empty(mTxn);
282 bool TransactionBuilder::IsResourceUpdatesEmpty() const {
283 return wr_transaction_resource_updates_is_empty(mTxn);
286 bool TransactionBuilder::IsRenderedFrameInvalidated() const {
287 return wr_transaction_is_rendered_frame_invalidated(mTxn);
290 void TransactionBuilder::SetDocumentView(
291 const LayoutDeviceIntRect& aDocumentRect) {
292 wr::DeviceIntRect wrDocRect;
293 wrDocRect.min.x = aDocumentRect.x;
294 wrDocRect.min.y = aDocumentRect.y;
295 wrDocRect.max.x = aDocumentRect.x + aDocumentRect.width;
296 wrDocRect.max.y = aDocumentRect.y + aDocumentRect.height;
297 wr_transaction_set_document_view(mTxn, &wrDocRect);
300 TransactionWrapper::TransactionWrapper(Transaction* aTxn) : mTxn(aTxn) {}
302 void TransactionWrapper::AppendDynamicProperties(
303 const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
304 const nsTArray<wr::WrTransformProperty>& aTransformArray,
305 const nsTArray<wr::WrColorProperty>& aColorArray) {
306 wr_transaction_append_dynamic_properties(
307 mTxn, aOpacityArray.IsEmpty() ? nullptr : aOpacityArray.Elements(),
308 aOpacityArray.Length(),
309 aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(),
310 aTransformArray.Length(),
311 aColorArray.IsEmpty() ? nullptr : aColorArray.Elements(),
312 aColorArray.Length());
315 void TransactionWrapper::AppendTransformProperties(
316 const nsTArray<wr::WrTransformProperty>& aTransformArray) {
317 wr_transaction_append_transform_properties(
318 mTxn, aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(),
319 aTransformArray.Length());
322 void TransactionWrapper::UpdateScrollPosition(
323 const wr::ExternalScrollId& aScrollId,
324 const nsTArray<wr::SampledScrollOffset>& aSampledOffsets) {
325 wr_transaction_scroll_layer(mTxn, aScrollId, &aSampledOffsets);
328 void TransactionWrapper::UpdateIsTransformAsyncZooming(uint64_t aAnimationId,
329 bool aIsZooming) {
330 wr_transaction_set_is_transform_async_zooming(mTxn, aAnimationId, aIsZooming);
333 void TransactionWrapper::AddMinimapData(const wr::ExternalScrollId& aScrollId,
334 const MinimapData& aMinimapData) {
335 wr_transaction_add_minimap_data(mTxn, aScrollId, aMinimapData);
338 /*static*/
339 already_AddRefed<WebRenderAPI> WebRenderAPI::Create(
340 layers::CompositorBridgeParent* aBridge,
341 RefPtr<widget::CompositorWidget>&& aWidget, const wr::WrWindowId& aWindowId,
342 LayoutDeviceIntSize aSize, layers::WindowKind aWindowKind,
343 nsACString& aError) {
344 MOZ_ASSERT(aBridge);
345 MOZ_ASSERT(aWidget);
346 static_assert(
347 sizeof(size_t) == sizeof(uintptr_t),
348 "The FFI bindings assume size_t is the same size as uintptr_t!");
350 wr::DocumentHandle* docHandle = nullptr;
351 WebRenderBackend backend = WebRenderBackend::HARDWARE;
352 WebRenderCompositor compositor = WebRenderCompositor::DRAW;
353 int32_t maxTextureSize = 0;
354 bool useANGLE = false;
355 bool useDComp = false;
356 bool useTripleBuffering = false;
357 bool supportsExternalBufferTextures = false;
358 layers::SyncHandle syncHandle = {};
360 // Dispatch a synchronous task because the DocumentHandle object needs to be
361 // created on the render thread. If need be we could delay waiting on this
362 // task until the next time we need to access the DocumentHandle object.
363 layers::SynchronousTask task("Create Renderer");
364 auto event = MakeUnique<NewRenderer>(
365 &docHandle, aBridge, &backend, &compositor, &maxTextureSize, &useANGLE,
366 &useDComp, &useTripleBuffering, &supportsExternalBufferTextures,
367 std::move(aWidget), &task, aSize, aWindowKind, &syncHandle, &aError);
368 RenderThread::Get()->PostEvent(aWindowId, std::move(event));
370 task.Wait();
372 if (!docHandle) {
373 return nullptr;
376 return RefPtr<WebRenderAPI>(
377 new WebRenderAPI(docHandle, aWindowId, backend, compositor,
378 maxTextureSize, useANGLE, useDComp,
379 useTripleBuffering,
380 supportsExternalBufferTextures, syncHandle))
381 .forget();
384 already_AddRefed<WebRenderAPI> WebRenderAPI::Clone() {
385 wr::DocumentHandle* docHandle = nullptr;
386 wr_api_clone(mDocHandle, &docHandle);
388 RefPtr<WebRenderAPI> renderApi = new WebRenderAPI(
389 docHandle, mId, mBackend, mCompositor, mMaxTextureSize, mUseANGLE,
390 mUseDComp, mUseTripleBuffering, mSupportsExternalBufferTextures,
391 mSyncHandle, this, this);
393 return renderApi.forget();
396 wr::WrIdNamespace WebRenderAPI::GetNamespace() {
397 return wr_api_get_namespace(mDocHandle);
400 WebRenderAPI::WebRenderAPI(
401 wr::DocumentHandle* aHandle, wr::WindowId aId, WebRenderBackend aBackend,
402 WebRenderCompositor aCompositor, uint32_t aMaxTextureSize, bool aUseANGLE,
403 bool aUseDComp, bool aUseTripleBuffering,
404 bool aSupportsExternalBufferTextures, layers::SyncHandle aSyncHandle,
405 wr::WebRenderAPI* aRootApi, wr::WebRenderAPI* aRootDocumentApi)
406 : mDocHandle(aHandle),
407 mId(aId),
408 mBackend(aBackend),
409 mCompositor(aCompositor),
410 mMaxTextureSize(aMaxTextureSize),
411 mUseANGLE(aUseANGLE),
412 mUseDComp(aUseDComp),
413 mUseTripleBuffering(aUseTripleBuffering),
414 mSupportsExternalBufferTextures(aSupportsExternalBufferTextures),
415 mCaptureSequence(false),
416 mSyncHandle(aSyncHandle),
417 mRendererDestroyed(false),
418 mRootApi(aRootApi),
419 mRootDocumentApi(aRootDocumentApi) {}
421 WebRenderAPI::~WebRenderAPI() {
422 if (!mRootDocumentApi) {
423 wr_api_delete_document(mDocHandle);
426 if (!mRootApi) {
427 MOZ_RELEASE_ASSERT(mRendererDestroyed);
428 wr_api_shut_down(mDocHandle);
431 wr_api_delete(mDocHandle);
434 void WebRenderAPI::DestroyRenderer() {
435 MOZ_RELEASE_ASSERT(!mRootApi);
437 RenderThread::Get()->SetDestroyed(GetId());
438 // Call wr_api_stop_render_backend() before RemoveRenderer.
439 wr_api_stop_render_backend(mDocHandle);
441 layers::SynchronousTask task("Destroy WebRenderAPI");
442 auto event = MakeUnique<RemoveRenderer>(&task);
443 RunOnRenderThread(std::move(event));
444 task.Wait();
446 mRendererDestroyed = true;
449 wr::WebRenderAPI* WebRenderAPI::GetRootAPI() {
450 if (mRootApi) {
451 return mRootApi;
453 return this;
456 void WebRenderAPI::UpdateDebugFlags(uint32_t aFlags) {
457 wr_api_set_debug_flags(mDocHandle, wr::DebugFlags{aFlags});
460 void WebRenderAPI::SendTransaction(TransactionBuilder& aTxn) {
461 if (mRootApi && mRootApi->mRendererDestroyed) {
462 return;
465 if (mPendingRemoteTextureInfoList &&
466 !mPendingRemoteTextureInfoList->mList.empty()) {
467 mPendingWrTransactionEvents.emplace(
468 WrTransactionEvent::PendingRemoteTextures(
469 std::move(mPendingRemoteTextureInfoList)));
472 if (mPendingAsyncImagePipelineOps &&
473 !mPendingAsyncImagePipelineOps->mList.empty()) {
474 mPendingWrTransactionEvents.emplace(
475 WrTransactionEvent::PendingAsyncImagePipelineOps(
476 std::move(mPendingAsyncImagePipelineOps), this, aTxn.Raw(),
477 aTxn.UseSceneBuilderThread()));
480 if (!mPendingWrTransactionEvents.empty()) {
481 mPendingWrTransactionEvents.emplace(WrTransactionEvent::Transaction(
482 this, aTxn.Take(), aTxn.UseSceneBuilderThread()));
483 HandleWrTransactionEvents(RemoteTextureWaitType::AsyncWait);
484 } else {
485 wr_api_send_transaction(mDocHandle, aTxn.Raw(),
486 aTxn.UseSceneBuilderThread());
490 layers::RemoteTextureInfoList* WebRenderAPI::GetPendingRemoteTextureInfoList() {
491 if (!mRootApi) {
492 // root api does not support async wait RemoteTexture.
493 return nullptr;
496 if (!mPendingRemoteTextureInfoList) {
497 mPendingRemoteTextureInfoList = MakeUnique<layers::RemoteTextureInfoList>();
499 return mPendingRemoteTextureInfoList.get();
502 layers::AsyncImagePipelineOps* WebRenderAPI::GetPendingAsyncImagePipelineOps(
503 TransactionBuilder& aTxn) {
504 if (!mRootApi) {
505 // root api does not support async wait RemoteTexture.
506 return nullptr;
509 if (!mPendingAsyncImagePipelineOps ||
510 mPendingAsyncImagePipelineOps->mTransaction != aTxn.Raw()) {
511 if (mPendingAsyncImagePipelineOps &&
512 !mPendingAsyncImagePipelineOps->mList.empty()) {
513 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
514 gfxCriticalNoteOnce << "Invalid AsyncImagePipelineOps";
516 mPendingAsyncImagePipelineOps =
517 MakeUnique<layers::AsyncImagePipelineOps>(aTxn.Raw());
518 } else {
519 MOZ_RELEASE_ASSERT(mPendingAsyncImagePipelineOps->mTransaction ==
520 aTxn.Raw());
523 return mPendingAsyncImagePipelineOps.get();
526 bool WebRenderAPI::CheckIsRemoteTextureReady(
527 layers::RemoteTextureInfoList* aList, const TimeStamp& aTimeStamp) {
528 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
529 MOZ_ASSERT(aList);
531 RefPtr<WebRenderAPI> self = this;
532 auto callback = [self](const layers::RemoteTextureInfo&) {
533 RefPtr<nsIRunnable> runnable = NewRunnableMethod<RemoteTextureWaitType>(
534 "WebRenderAPI::HandleWrTransactionEvents", self,
535 &WebRenderAPI::HandleWrTransactionEvents,
536 RemoteTextureWaitType::AsyncWait);
537 layers::CompositorThread()->Dispatch(runnable.forget());
540 const auto maxWaitDurationMs = 10000;
541 const auto now = TimeStamp::Now();
542 const auto waitDurationMs =
543 static_cast<uint32_t>((now - aTimeStamp).ToMilliseconds());
545 const auto isTimeout = waitDurationMs > maxWaitDurationMs;
546 if (isTimeout) {
547 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
548 gfxCriticalNote << "RemoteTexture ready timeout";
551 bool isReady = true;
552 while (!aList->mList.empty() && isReady) {
553 auto& front = aList->mList.front();
554 isReady &= layers::RemoteTextureMap::Get()->CheckRemoteTextureReady(
555 front, callback);
556 if (isTimeout) {
557 isReady = true;
559 if (isReady) {
560 aList->mList.pop();
564 return isReady;
567 void WebRenderAPI::WaitRemoteTextureReady(
568 layers::RemoteTextureInfoList* aList) {
569 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
570 MOZ_ASSERT(aList);
572 while (!aList->mList.empty()) {
573 auto& front = aList->mList.front();
574 layers::RemoteTextureMap::Get()->WaitRemoteTextureReady(front);
575 aList->mList.pop();
579 void WebRenderAPI::FlushPendingWrTransactionEventsWithoutWait() {
580 HandleWrTransactionEvents(RemoteTextureWaitType::FlushWithoutWait);
583 void WebRenderAPI::FlushPendingWrTransactionEventsWithWait() {
584 HandleWrTransactionEvents(RemoteTextureWaitType::FlushWithWait);
587 void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType) {
588 auto& events = mPendingWrTransactionEvents;
590 while (!events.empty()) {
591 auto& front = events.front();
592 switch (front.mTag) {
593 case WrTransactionEvent::Tag::Transaction:
594 wr_api_send_transaction(mDocHandle, front.RawTransaction(),
595 front.UseSceneBuilderThread());
596 break;
597 case WrTransactionEvent::Tag::PendingRemoteTextures: {
598 bool isReady = true;
599 if (aType == RemoteTextureWaitType::AsyncWait) {
600 isReady = CheckIsRemoteTextureReady(front.RemoteTextureInfoList(),
601 front.mTimeStamp);
602 } else if (aType == RemoteTextureWaitType::FlushWithWait) {
603 WaitRemoteTextureReady(front.RemoteTextureInfoList());
604 } else {
605 MOZ_ASSERT(aType == RemoteTextureWaitType::FlushWithoutWait);
606 auto* list = front.RemoteTextureInfoList();
607 while (!list->mList.empty()) {
608 auto& front = list->mList.front();
609 layers::RemoteTextureMap::Get()->SuppressRemoteTextureReadyCheck(
610 front.mTextureId, front.mForPid);
611 list->mList.pop();
614 if (!isReady && (aType != RemoteTextureWaitType::FlushWithoutWait)) {
615 return;
617 break;
619 case WrTransactionEvent::Tag::PendingAsyncImagePipelineOps: {
620 auto* list = front.AsyncImagePipelineOps();
621 TransactionBuilder& txn = *front.GetTransactionBuilder();
623 list->HandleOps(txn);
624 break;
627 events.pop();
631 std::vector<WrHitResult> WebRenderAPI::HitTest(const wr::WorldPoint& aPoint) {
632 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits<12>(),
633 "CompositorHitTestFlags MAX value has to be less than number "
634 "of bits in uint16_t minus 4 for SideBitsPacked");
636 nsTArray<wr::HitResult> wrResults;
637 wr_api_hit_test(mDocHandle, aPoint, &wrResults);
639 std::vector<WrHitResult> geckoResults;
640 for (wr::HitResult wrResult : wrResults) {
641 WrHitResult geckoResult;
642 geckoResult.mLayersId = wr::AsLayersId(wrResult.pipeline_id);
643 geckoResult.mScrollId =
644 static_cast<layers::ScrollableLayerGuid::ViewID>(wrResult.scroll_id);
645 geckoResult.mHitInfo.deserialize(wrResult.hit_info & 0x0fff);
646 geckoResult.mSideBits = static_cast<SideBits>(wrResult.hit_info >> 12);
648 if (wrResult.animation_id != 0) {
649 geckoResult.mAnimationId = Some(wrResult.animation_id);
650 } else {
651 geckoResult.mAnimationId = Nothing();
653 geckoResults.push_back(geckoResult);
655 return geckoResults;
658 void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
659 const gfx::SurfaceFormat& aFormat,
660 const Range<uint8_t>& buffer, bool* aNeedsYFlip) {
661 class Readback : public RendererEvent {
662 public:
663 explicit Readback(layers::SynchronousTask* aTask, TimeStamp aStartTime,
664 gfx::IntSize aSize, const gfx::SurfaceFormat& aFormat,
665 const Range<uint8_t>& aBuffer, bool* aNeedsYFlip)
666 : mTask(aTask),
667 mStartTime(aStartTime),
668 mSize(aSize),
669 mFormat(aFormat),
670 mBuffer(aBuffer),
671 mNeedsYFlip(aNeedsYFlip) {
672 MOZ_COUNT_CTOR(Readback);
675 MOZ_COUNTED_DTOR_OVERRIDE(Readback)
677 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
678 aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime,
679 /* aRender */ true, Some(mSize),
680 wr::SurfaceFormatToImageFormat(mFormat),
681 Some(mBuffer), mNeedsYFlip);
682 layers::AutoCompleteTask complete(mTask);
685 layers::SynchronousTask* mTask;
686 TimeStamp mStartTime;
687 gfx::IntSize mSize;
688 gfx::SurfaceFormat mFormat;
689 const Range<uint8_t>& mBuffer;
690 bool* mNeedsYFlip;
693 // Disable debug flags during readback. See bug 1436020.
694 UpdateDebugFlags(0);
696 layers::SynchronousTask task("Readback");
697 auto event = MakeUnique<Readback>(&task, aStartTime, size, aFormat, buffer,
698 aNeedsYFlip);
699 // This event will be passed from wr_backend thread to renderer thread. That
700 // implies that all frame data have been processed when the renderer runs this
701 // read-back event. Then, we could make sure this read-back event gets the
702 // latest result.
703 RunOnRenderThread(std::move(event));
705 task.Wait();
707 UpdateDebugFlags(gfx::gfxVars::WebRenderDebugFlags());
710 void WebRenderAPI::ClearAllCaches() { wr_api_clear_all_caches(mDocHandle); }
712 void WebRenderAPI::EnableNativeCompositor(bool aEnable) {
713 wr_api_enable_native_compositor(mDocHandle, aEnable);
716 void WebRenderAPI::SetBatchingLookback(uint32_t aCount) {
717 wr_api_set_batching_lookback(mDocHandle, aCount);
720 void WebRenderAPI::SetBool(wr::BoolParameter aKey, bool aValue) {
721 wr_api_set_bool(mDocHandle, aKey, aValue);
724 void WebRenderAPI::SetInt(wr::IntParameter aKey, int32_t aValue) {
725 wr_api_set_int(mDocHandle, aKey, aValue);
728 void WebRenderAPI::SetClearColor(const gfx::DeviceColor& aColor) {
729 RenderThread::Get()->SetClearColor(mId, ToColorF(aColor));
732 void WebRenderAPI::SetProfilerUI(const nsACString& aUIString) {
733 RenderThread::Get()->SetProfilerUI(mId, aUIString);
736 void WebRenderAPI::Pause() {
737 class PauseEvent : public RendererEvent {
738 public:
739 explicit PauseEvent(layers::SynchronousTask* aTask) : mTask(aTask) {
740 MOZ_COUNT_CTOR(PauseEvent);
743 MOZ_COUNTED_DTOR_OVERRIDE(PauseEvent)
745 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
746 aRenderThread.Pause(aWindowId);
747 layers::AutoCompleteTask complete(mTask);
750 layers::SynchronousTask* mTask;
753 layers::SynchronousTask task("Pause");
754 auto event = MakeUnique<PauseEvent>(&task);
755 // This event will be passed from wr_backend thread to renderer thread. That
756 // implies that all frame data have been processed when the renderer runs this
757 // event.
758 RunOnRenderThread(std::move(event));
760 task.Wait();
763 bool WebRenderAPI::Resume() {
764 class ResumeEvent : public RendererEvent {
765 public:
766 explicit ResumeEvent(layers::SynchronousTask* aTask, bool* aResult)
767 : mTask(aTask), mResult(aResult) {
768 MOZ_COUNT_CTOR(ResumeEvent);
771 MOZ_COUNTED_DTOR_OVERRIDE(ResumeEvent)
773 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
774 *mResult = aRenderThread.Resume(aWindowId);
775 layers::AutoCompleteTask complete(mTask);
778 layers::SynchronousTask* mTask;
779 bool* mResult;
782 bool result = false;
783 layers::SynchronousTask task("Resume");
784 auto event = MakeUnique<ResumeEvent>(&task, &result);
785 // This event will be passed from wr_backend thread to renderer thread. That
786 // implies that all frame data have been processed when the renderer runs this
787 // event.
788 RunOnRenderThread(std::move(event));
790 task.Wait();
791 return result;
794 void WebRenderAPI::NotifyMemoryPressure() {
795 wr_api_notify_memory_pressure(mDocHandle);
798 void WebRenderAPI::AccumulateMemoryReport(MemoryReport* aReport) {
799 wr_api_accumulate_memory_report(mDocHandle, aReport, &WebRenderMallocSizeOf,
800 &WebRenderMallocEnclosingSizeOf);
803 void WebRenderAPI::WakeSceneBuilder() { wr_api_wake_scene_builder(mDocHandle); }
805 void WebRenderAPI::FlushSceneBuilder() {
806 wr_api_flush_scene_builder(mDocHandle);
809 void WebRenderAPI::WaitFlushed() {
810 class WaitFlushedEvent : public RendererEvent {
811 public:
812 explicit WaitFlushedEvent(layers::SynchronousTask* aTask) : mTask(aTask) {
813 MOZ_COUNT_CTOR(WaitFlushedEvent);
816 MOZ_COUNTED_DTOR_OVERRIDE(WaitFlushedEvent)
818 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
819 layers::AutoCompleteTask complete(mTask);
822 layers::SynchronousTask* mTask;
825 layers::SynchronousTask task("WaitFlushed");
826 auto event = MakeUnique<WaitFlushedEvent>(&task);
827 // This event will be passed from wr_backend thread to renderer thread. That
828 // implies that all frame data have been processed when the renderer runs this
829 // event.
830 RunOnRenderThread(std::move(event));
832 task.Wait();
835 void WebRenderAPI::Capture() {
836 // see CaptureBits
837 // SCENE | FRAME | TILE_CACHE
838 uint8_t bits = 15; // TODO: get from JavaScript
839 const char* path = "wr-capture"; // TODO: get from JavaScript
840 wr_api_capture(mDocHandle, path, bits);
843 void WebRenderAPI::StartCaptureSequence(const nsACString& aPath,
844 uint32_t aFlags) {
845 if (mCaptureSequence) {
846 wr_api_stop_capture_sequence(mDocHandle);
849 wr_api_start_capture_sequence(mDocHandle, PromiseFlatCString(aPath).get(),
850 aFlags);
852 mCaptureSequence = true;
855 void WebRenderAPI::StopCaptureSequence() {
856 if (mCaptureSequence) {
857 wr_api_stop_capture_sequence(mDocHandle);
860 mCaptureSequence = false;
863 void WebRenderAPI::BeginRecording(const TimeStamp& aRecordingStart,
864 wr::PipelineId aRootPipelineId) {
865 class BeginRecordingEvent final : public RendererEvent {
866 public:
867 explicit BeginRecordingEvent(const TimeStamp& aRecordingStart,
868 wr::PipelineId aRootPipelineId)
869 : mRecordingStart(aRecordingStart), mRootPipelineId(aRootPipelineId) {
870 MOZ_COUNT_CTOR(BeginRecordingEvent);
873 ~BeginRecordingEvent() { MOZ_COUNT_DTOR(BeginRecordingEvent); }
875 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
876 aRenderThread.BeginRecordingForWindow(aWindowId, mRecordingStart,
877 mRootPipelineId);
880 private:
881 TimeStamp mRecordingStart;
882 wr::PipelineId mRootPipelineId;
885 auto event =
886 MakeUnique<BeginRecordingEvent>(aRecordingStart, aRootPipelineId);
887 RunOnRenderThread(std::move(event));
890 RefPtr<WebRenderAPI::EndRecordingPromise> WebRenderAPI::EndRecording() {
891 class EndRecordingEvent final : public RendererEvent {
892 public:
893 explicit EndRecordingEvent() { MOZ_COUNT_CTOR(EndRecordingEvent); }
895 MOZ_COUNTED_DTOR(EndRecordingEvent);
897 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
898 Maybe<layers::FrameRecording> recording =
899 aRenderThread.EndRecordingForWindow(aWindowId);
901 if (recording) {
902 mPromise.Resolve(recording.extract(), __func__);
903 } else {
904 mPromise.Reject(NS_ERROR_UNEXPECTED, __func__);
908 RefPtr<WebRenderAPI::EndRecordingPromise> GetPromise() {
909 return mPromise.Ensure(__func__);
912 private:
913 MozPromiseHolder<WebRenderAPI::EndRecordingPromise> mPromise;
916 auto event = MakeUnique<EndRecordingEvent>();
917 auto promise = event->GetPromise();
919 RunOnRenderThread(std::move(event));
920 return promise;
923 void TransactionBuilder::Clear() { wr_resource_updates_clear(mTxn); }
925 Transaction* TransactionBuilder::Take() {
926 if (!mOwnsData) {
927 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
928 return nullptr;
930 Transaction* txn = mTxn;
931 mTxn = wr_transaction_new(mUseSceneBuilderThread);
932 return txn;
935 void TransactionBuilder::Notify(wr::Checkpoint aWhen,
936 UniquePtr<NotificationHandler> aEvent) {
937 wr_transaction_notify(mTxn, aWhen,
938 reinterpret_cast<uintptr_t>(aEvent.release()));
941 void TransactionBuilder::AddImage(ImageKey key,
942 const ImageDescriptor& aDescriptor,
943 wr::Vec<uint8_t>& aBytes) {
944 wr_resource_updates_add_image(mTxn, key, &aDescriptor, &aBytes.inner);
947 void TransactionBuilder::AddBlobImage(BlobImageKey key,
948 const ImageDescriptor& aDescriptor,
949 uint16_t aTileSize,
950 wr::Vec<uint8_t>& aBytes,
951 const wr::DeviceIntRect& aVisibleRect) {
952 wr_resource_updates_add_blob_image(mTxn, key, &aDescriptor, aTileSize,
953 &aBytes.inner, aVisibleRect);
956 void TransactionBuilder::AddExternalImage(ImageKey key,
957 const ImageDescriptor& aDescriptor,
958 ExternalImageId aExtID,
959 wr::ExternalImageType aImageType,
960 uint8_t aChannelIndex) {
961 wr_resource_updates_add_external_image(mTxn, key, &aDescriptor, aExtID,
962 &aImageType, aChannelIndex);
965 void TransactionBuilder::AddExternalImageBuffer(
966 ImageKey aKey, const ImageDescriptor& aDescriptor,
967 ExternalImageId aHandle) {
968 auto channelIndex = 0;
969 AddExternalImage(aKey, aDescriptor, aHandle, wr::ExternalImageType::Buffer(),
970 channelIndex);
973 void TransactionBuilder::UpdateImageBuffer(ImageKey aKey,
974 const ImageDescriptor& aDescriptor,
975 wr::Vec<uint8_t>& aBytes) {
976 wr_resource_updates_update_image(mTxn, aKey, &aDescriptor, &aBytes.inner);
979 void TransactionBuilder::UpdateBlobImage(BlobImageKey aKey,
980 const ImageDescriptor& aDescriptor,
981 wr::Vec<uint8_t>& aBytes,
982 const wr::DeviceIntRect& aVisibleRect,
983 const wr::LayoutIntRect& aDirtyRect) {
984 wr_resource_updates_update_blob_image(mTxn, aKey, &aDescriptor, &aBytes.inner,
985 aVisibleRect, aDirtyRect);
988 void TransactionBuilder::UpdateExternalImage(ImageKey aKey,
989 const ImageDescriptor& aDescriptor,
990 ExternalImageId aExtID,
991 wr::ExternalImageType aImageType,
992 uint8_t aChannelIndex) {
993 wr_resource_updates_update_external_image(mTxn, aKey, &aDescriptor, aExtID,
994 &aImageType, aChannelIndex);
997 void TransactionBuilder::UpdateExternalImageWithDirtyRect(
998 ImageKey aKey, const ImageDescriptor& aDescriptor, ExternalImageId aExtID,
999 wr::ExternalImageType aImageType, const wr::DeviceIntRect& aDirtyRect,
1000 uint8_t aChannelIndex) {
1001 wr_resource_updates_update_external_image_with_dirty_rect(
1002 mTxn, aKey, &aDescriptor, aExtID, &aImageType, aChannelIndex, aDirtyRect);
1005 void TransactionBuilder::SetBlobImageVisibleArea(
1006 BlobImageKey aKey, const wr::DeviceIntRect& aArea) {
1007 wr_resource_updates_set_blob_image_visible_area(mTxn, aKey, &aArea);
1010 void TransactionBuilder::DeleteImage(ImageKey aKey) {
1011 wr_resource_updates_delete_image(mTxn, aKey);
1014 void TransactionBuilder::DeleteBlobImage(BlobImageKey aKey) {
1015 wr_resource_updates_delete_blob_image(mTxn, aKey);
1018 void TransactionBuilder::AddRawFont(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes,
1019 uint32_t aIndex) {
1020 wr_resource_updates_add_raw_font(mTxn, aKey, &aBytes.inner, aIndex);
1023 void TransactionBuilder::AddFontDescriptor(wr::FontKey aKey,
1024 wr::Vec<uint8_t>& aBytes,
1025 uint32_t aIndex) {
1026 wr_resource_updates_add_font_descriptor(mTxn, aKey, &aBytes.inner, aIndex);
1029 void TransactionBuilder::DeleteFont(wr::FontKey aKey) {
1030 wr_resource_updates_delete_font(mTxn, aKey);
1033 void TransactionBuilder::AddFontInstance(
1034 wr::FontInstanceKey aKey, wr::FontKey aFontKey, float aGlyphSize,
1035 const wr::FontInstanceOptions* aOptions,
1036 const wr::FontInstancePlatformOptions* aPlatformOptions,
1037 wr::Vec<uint8_t>& aVariations) {
1038 wr_resource_updates_add_font_instance(mTxn, aKey, aFontKey, aGlyphSize,
1039 aOptions, aPlatformOptions,
1040 &aVariations.inner);
1043 void TransactionBuilder::DeleteFontInstance(wr::FontInstanceKey aKey) {
1044 wr_resource_updates_delete_font_instance(mTxn, aKey);
1047 void TransactionBuilder::UpdateQualitySettings(
1048 bool aForceSubpixelAAWherePossible) {
1049 wr_transaction_set_quality_settings(mTxn, aForceSubpixelAAWherePossible);
1052 class FrameStartTime : public RendererEvent {
1053 public:
1054 explicit FrameStartTime(const TimeStamp& aTime) : mTime(aTime) {
1055 MOZ_COUNT_CTOR(FrameStartTime);
1058 MOZ_COUNTED_DTOR_OVERRIDE(FrameStartTime)
1060 void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
1061 auto renderer = aRenderThread.GetRenderer(aWindowId);
1062 if (renderer) {
1063 renderer->SetFrameStartTime(mTime);
1067 private:
1068 TimeStamp mTime;
1071 void WebRenderAPI::SetFrameStartTime(const TimeStamp& aTime) {
1072 auto event = MakeUnique<FrameStartTime>(aTime);
1073 RunOnRenderThread(std::move(event));
1076 void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) {
1077 auto event = reinterpret_cast<uintptr_t>(aEvent.release());
1078 wr_api_send_external_event(mDocHandle, event);
1081 DisplayListBuilder::DisplayListBuilder(PipelineId aId,
1082 WebRenderBackend aBackend)
1083 : mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
1084 mActiveFixedPosTracker(nullptr),
1085 mPipelineId(aId),
1086 mBackend(aBackend),
1087 mDisplayItemCache(nullptr) {
1088 MOZ_COUNT_CTOR(DisplayListBuilder);
1089 mWrState = wr_state_new(aId);
1091 if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) {
1092 mDisplayItemCache->SetPipelineId(aId);
1096 DisplayListBuilder::~DisplayListBuilder() {
1097 MOZ_COUNT_DTOR(DisplayListBuilder);
1098 wr_state_delete(mWrState);
1101 void DisplayListBuilder::Save() { wr_dp_save(mWrState); }
1102 void DisplayListBuilder::Restore() { wr_dp_restore(mWrState); }
1103 void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState); }
1105 usize DisplayListBuilder::Dump(usize aIndent, const Maybe<usize>& aStart,
1106 const Maybe<usize>& aEnd) {
1107 return wr_dump_display_list(mWrState, aIndent, aStart.ptrOr(nullptr),
1108 aEnd.ptrOr(nullptr));
1111 void DisplayListBuilder::DumpSerializedDisplayList() {
1112 wr_dump_serialized_display_list(mWrState);
1115 void DisplayListBuilder::Begin(layers::DisplayItemCache* aCache) {
1116 wr_api_begin_builder(mWrState);
1118 mScrollIds.clear();
1119 mCurrentSpaceAndClipChain = wr::RootScrollNodeWithChain();
1120 mClipChainLeaf = Nothing();
1121 mSuspendedSpaceAndClipChain = Nothing();
1122 mSuspendedClipChainLeaf = Nothing();
1123 mCachedTextDT = nullptr;
1124 mCachedContext = nullptr;
1125 mActiveFixedPosTracker = nullptr;
1126 mDisplayItemCache = aCache;
1127 mCurrentCacheSlot = Nothing();
1130 void DisplayListBuilder::End(BuiltDisplayList& aOutDisplayList) {
1131 wr_api_end_builder(
1132 mWrState, &aOutDisplayList.dl_desc, &aOutDisplayList.dl_items.inner,
1133 &aOutDisplayList.dl_cache.inner, &aOutDisplayList.dl_spatial_tree.inner);
1135 mDisplayItemCache = nullptr;
1138 void DisplayListBuilder::End(layers::DisplayListData& aOutTransaction) {
1139 if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) {
1140 wr_dp_set_cache_size(mWrState, mDisplayItemCache->CurrentSize());
1143 wr::VecU8 dlItems, dlCache, dlSpatialTree;
1144 wr_api_end_builder(mWrState, &aOutTransaction.mDLDesc, &dlItems.inner,
1145 &dlCache.inner, &dlSpatialTree.inner);
1146 aOutTransaction.mDLItems.emplace(dlItems.inner.data, dlItems.inner.length,
1147 dlItems.inner.capacity);
1148 aOutTransaction.mDLCache.emplace(dlCache.inner.data, dlCache.inner.length,
1149 dlCache.inner.capacity);
1150 aOutTransaction.mDLSpatialTree.emplace(dlSpatialTree.inner.data,
1151 dlSpatialTree.inner.length,
1152 dlSpatialTree.inner.capacity);
1153 dlItems.inner.capacity = 0;
1154 dlItems.inner.data = nullptr;
1155 dlCache.inner.capacity = 0;
1156 dlCache.inner.data = nullptr;
1157 dlSpatialTree.inner.capacity = 0;
1158 dlSpatialTree.inner.data = nullptr;
1161 Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
1162 const wr::StackingContextParams& aParams, const wr::LayoutRect& aBounds,
1163 const wr::RasterSpace& aRasterSpace) {
1164 MOZ_ASSERT(mClipChainLeaf.isNothing(),
1165 "Non-empty leaf from clip chain given, but not used with SC!");
1167 WRDL_LOG(
1168 "PushStackingContext b=%s t=%s id=0x%" PRIx64 "\n", mWrState,
1169 ToString(aBounds).c_str(),
1170 aParams.mTransformPtr ? ToString(*aParams.mTransformPtr).c_str() : "none",
1171 aParams.animation ? aParams.animation->id : 0);
1173 auto spatialId = wr_dp_push_stacking_context(
1174 mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aParams,
1175 aParams.mTransformPtr, aParams.mFilters.Elements(),
1176 aParams.mFilters.Length(), aParams.mFilterDatas.Elements(),
1177 aParams.mFilterDatas.Length(), aRasterSpace);
1179 return spatialId.id != 0 ? Some(spatialId) : Nothing();
1182 void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame) {
1183 WRDL_LOG("PopStackingContext\n", mWrState);
1184 wr_dp_pop_stacking_context(mWrState, aIsReferenceFrame);
1187 wr::WrClipChainId DisplayListBuilder::DefineClipChain(
1188 const nsTArray<wr::WrClipId>& aClips, bool aParentWithCurrentChain) {
1189 CancelGroup();
1191 const uint64_t* parent = nullptr;
1192 if (aParentWithCurrentChain &&
1193 mCurrentSpaceAndClipChain.clip_chain != wr::ROOT_CLIP_CHAIN) {
1194 parent = &mCurrentSpaceAndClipChain.clip_chain;
1196 uint64_t clipchainId = wr_dp_define_clipchain(
1197 mWrState, parent, aClips.Elements(), aClips.Length());
1198 if (MOZ_LOG_TEST(sWrDLLog, LogLevel::Debug)) {
1199 nsCString message;
1200 message.AppendPrintf("DefineClipChain id=%" PRIu64
1201 " clipCount=%zu clipIds=[",
1202 clipchainId, aClips.Length());
1203 for (const auto& clip : aClips) {
1204 message.AppendPrintf("%" PRIuPTR ",", clip.id);
1206 message.Append("]");
1207 WRDL_LOG("%s", mWrState, message.get());
1209 return wr::WrClipChainId{clipchainId};
1212 wr::WrClipId DisplayListBuilder::DefineImageMaskClip(
1213 const wr::ImageMask& aMask, const nsTArray<wr::LayoutPoint>& aPoints,
1214 wr::FillRule aFillRule) {
1215 CancelGroup();
1217 WrClipId clipId = wr_dp_define_image_mask_clip_with_parent_clip_chain(
1218 mWrState, mCurrentSpaceAndClipChain.space, aMask, aPoints.Elements(),
1219 aPoints.Length(), aFillRule);
1221 return clipId;
1224 wr::WrClipId DisplayListBuilder::DefineRoundedRectClip(
1225 Maybe<wr::WrSpatialId> aSpace, const wr::ComplexClipRegion& aComplex) {
1226 CancelGroup();
1228 WrClipId clipId;
1229 if (aSpace) {
1230 clipId = wr_dp_define_rounded_rect_clip(mWrState, *aSpace, aComplex);
1231 } else {
1232 clipId = wr_dp_define_rounded_rect_clip(
1233 mWrState, mCurrentSpaceAndClipChain.space, aComplex);
1236 return clipId;
1239 wr::WrClipId DisplayListBuilder::DefineRectClip(Maybe<wr::WrSpatialId> aSpace,
1240 wr::LayoutRect aClipRect) {
1241 CancelGroup();
1243 WrClipId clipId;
1244 if (aSpace) {
1245 clipId = wr_dp_define_rect_clip(mWrState, *aSpace, aClipRect);
1246 } else {
1247 clipId = wr_dp_define_rect_clip(mWrState, mCurrentSpaceAndClipChain.space,
1248 aClipRect);
1251 return clipId;
1254 wr::WrSpatialId DisplayListBuilder::DefineStickyFrame(
1255 const wr::LayoutRect& aContentRect, const float* aTopMargin,
1256 const float* aRightMargin, const float* aBottomMargin,
1257 const float* aLeftMargin, const StickyOffsetBounds& aVerticalBounds,
1258 const StickyOffsetBounds& aHorizontalBounds,
1259 const wr::LayoutVector2D& aAppliedOffset, wr::SpatialTreeItemKey aKey) {
1260 auto spatialId = wr_dp_define_sticky_frame(
1261 mWrState, mCurrentSpaceAndClipChain.space, aContentRect, aTopMargin,
1262 aRightMargin, aBottomMargin, aLeftMargin, aVerticalBounds,
1263 aHorizontalBounds, aAppliedOffset, aKey);
1265 WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n",
1266 mWrState, spatialId.id, ToString(aContentRect).c_str(),
1267 aTopMargin ? ToString(*aTopMargin).c_str() : "none",
1268 aRightMargin ? ToString(*aRightMargin).c_str() : "none",
1269 aBottomMargin ? ToString(*aBottomMargin).c_str() : "none",
1270 aLeftMargin ? ToString(*aLeftMargin).c_str() : "none",
1271 ToString(aVerticalBounds).c_str(),
1272 ToString(aHorizontalBounds).c_str(),
1273 ToString(aAppliedOffset).c_str());
1275 return spatialId;
1278 Maybe<wr::WrSpatialId> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
1279 layers::ScrollableLayerGuid::ViewID aViewId) const {
1280 if (aViewId == layers::ScrollableLayerGuid::NULL_SCROLL_ID) {
1281 return Some(wr::RootScrollNode());
1284 auto it = mScrollIds.find(aViewId);
1285 if (it == mScrollIds.end()) {
1286 return Nothing();
1289 return Some(it->second);
1292 wr::WrSpatialId DisplayListBuilder::DefineScrollLayer(
1293 const layers::ScrollableLayerGuid::ViewID& aViewId,
1294 const Maybe<wr::WrSpatialId>& aParent, const wr::LayoutRect& aContentRect,
1295 const wr::LayoutRect& aClipRect, const wr::LayoutVector2D& aScrollOffset,
1296 wr::APZScrollGeneration aScrollOffsetGeneration,
1297 wr::HasScrollLinkedEffect aHasScrollLinkedEffect,
1298 wr::SpatialTreeItemKey aKey) {
1299 auto it = mScrollIds.find(aViewId);
1300 if (it != mScrollIds.end()) {
1301 return it->second;
1304 // We haven't defined aViewId before, so let's define it now.
1305 wr::WrSpatialId defaultParent = mCurrentSpaceAndClipChain.space;
1307 auto space = wr_dp_define_scroll_layer(
1308 mWrState, aViewId, aParent ? aParent.ptr() : &defaultParent, aContentRect,
1309 aClipRect, aScrollOffset, aScrollOffsetGeneration, aHasScrollLinkedEffect,
1310 aKey);
1312 WRDL_LOG("DefineScrollLayer id=%" PRIu64
1313 "/%zu p=%s co=%s cl=%s generation=%s hasScrollLinkedEffect=%s\n",
1314 mWrState, aViewId, space.id,
1315 aParent ? ToString(aParent->id).c_str() : "(nil)",
1316 ToString(aContentRect).c_str(), ToString(aClipRect).c_str(),
1317 ToString(aScrollOffsetGeneration).c_str(),
1318 ToString(aHasScrollLinkedEffect).c_str());
1320 mScrollIds[aViewId] = space;
1321 return space;
1324 void DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds,
1325 const wr::LayoutRect& aClip,
1326 bool aIsBackfaceVisible,
1327 bool aForceAntiAliasing, bool aIsCheckerboard,
1328 const wr::ColorF& aColor) {
1329 wr::LayoutRect clip = MergeClipLeaf(aClip);
1330 WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState, ToString(aBounds).c_str(),
1331 ToString(clip).c_str(), ToString(aColor).c_str());
1332 wr_dp_push_rect(mWrState, aBounds, clip, aIsBackfaceVisible,
1333 aForceAntiAliasing, aIsCheckerboard,
1334 &mCurrentSpaceAndClipChain, aColor);
1337 void DisplayListBuilder::PushRoundedRect(const wr::LayoutRect& aBounds,
1338 const wr::LayoutRect& aClip,
1339 bool aIsBackfaceVisible,
1340 const wr::ColorF& aColor) {
1341 wr::LayoutRect clip = MergeClipLeaf(aClip);
1342 WRDL_LOG("PushRoundedRect b=%s cl=%s c=%s\n", mWrState,
1343 ToString(aBounds).c_str(), ToString(clip).c_str(),
1344 ToString(aColor).c_str());
1346 // Draw the rounded rectangle as a border with rounded corners. We could also
1347 // draw this as a rectangle clipped to a rounded rectangle, but:
1348 // - clips are not cached; borders are
1349 // - a simple border like this will be drawn as an image
1350 // - Processing lots of clips is not WebRender's strong point.
1352 // Made the borders thicker than one half the width/height, to avoid
1353 // little white dots at the center at some magnifications.
1354 wr::BorderSide side = {aColor, wr::BorderStyle::Solid};
1355 float h = aBounds.width() * 0.6f;
1356 float v = aBounds.height() * 0.6f;
1357 wr::LayoutSideOffsets widths = {v, h, v, h};
1358 wr::BorderRadius radii = {{h, v}, {h, v}, {h, v}, {h, v}};
1360 // Anti-aliased borders are required for rounded borders.
1361 wr_dp_push_border(mWrState, aBounds, clip, aIsBackfaceVisible,
1362 &mCurrentSpaceAndClipChain, wr::AntialiasBorder::Yes,
1363 widths, side, side, side, side, radii);
1366 void DisplayListBuilder::PushHitTest(
1367 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1368 bool aIsBackfaceVisible,
1369 const layers::ScrollableLayerGuid::ViewID& aScrollId,
1370 const gfx::CompositorHitTestInfo& aHitInfo, SideBits aSideBits) {
1371 wr::LayoutRect clip = MergeClipLeaf(aClip);
1372 WRDL_LOG("PushHitTest b=%s cl=%s\n", mWrState, ToString(aBounds).c_str(),
1373 ToString(clip).c_str());
1375 static_assert(gfx::DoesCompositorHitTestInfoFitIntoBits<12>(),
1376 "CompositorHitTestFlags MAX value has to be less than number "
1377 "of bits in uint16_t minus 4 for SideBitsPacked");
1379 uint16_t hitInfoBits = static_cast<uint16_t>(aHitInfo.serialize()) |
1380 (static_cast<uint16_t>(aSideBits) << 12);
1382 wr_dp_push_hit_test(mWrState, aBounds, clip, aIsBackfaceVisible,
1383 &mCurrentSpaceAndClipChain, aScrollId, hitInfoBits);
1386 void DisplayListBuilder::PushRectWithAnimation(
1387 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1388 bool aIsBackfaceVisible, const wr::ColorF& aColor,
1389 const WrAnimationProperty* aAnimation) {
1390 wr::LayoutRect clip = MergeClipLeaf(aClip);
1391 WRDL_LOG("PushRectWithAnimation b=%s cl=%s c=%s\n", mWrState,
1392 ToString(aBounds).c_str(), ToString(clip).c_str(),
1393 ToString(aColor).c_str());
1395 wr_dp_push_rect_with_animation(mWrState, aBounds, clip, aIsBackfaceVisible,
1396 &mCurrentSpaceAndClipChain, aColor,
1397 aAnimation);
1400 void DisplayListBuilder::PushClearRect(const wr::LayoutRect& aBounds) {
1401 wr::LayoutRect clip = MergeClipLeaf(aBounds);
1402 WRDL_LOG("PushClearRect b=%s c=%s\n", mWrState, ToString(aBounds).c_str(),
1403 ToString(clip).c_str());
1404 wr_dp_push_clear_rect(mWrState, aBounds, clip, &mCurrentSpaceAndClipChain);
1407 void DisplayListBuilder::PushBackdropFilter(
1408 const wr::LayoutRect& aBounds, const wr::ComplexClipRegion& aRegion,
1409 const nsTArray<wr::FilterOp>& aFilters,
1410 const nsTArray<wr::WrFilterData>& aFilterDatas, bool aIsBackfaceVisible) {
1411 wr::LayoutRect clip = MergeClipLeaf(aBounds);
1412 WRDL_LOG("PushBackdropFilter b=%s c=%s\n", mWrState,
1413 ToString(aBounds).c_str(), ToString(clip).c_str());
1415 auto clipId = DefineRoundedRectClip(Nothing(), aRegion);
1416 auto clipChainId = DefineClipChain({clipId}, true);
1417 auto spaceAndClip =
1418 WrSpaceAndClipChain{mCurrentSpaceAndClipChain.space, clipChainId.id};
1420 wr_dp_push_backdrop_filter(mWrState, aBounds, clip, aIsBackfaceVisible,
1421 &spaceAndClip, aFilters.Elements(),
1422 aFilters.Length(), aFilterDatas.Elements(),
1423 aFilterDatas.Length());
1426 void DisplayListBuilder::PushLinearGradient(
1427 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1428 bool aIsBackfaceVisible, const wr::LayoutPoint& aStartPoint,
1429 const wr::LayoutPoint& aEndPoint, const nsTArray<wr::GradientStop>& aStops,
1430 wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize,
1431 const wr::LayoutSize aTileSpacing) {
1432 wr_dp_push_linear_gradient(
1433 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1434 &mCurrentSpaceAndClipChain, aStartPoint, aEndPoint, aStops.Elements(),
1435 aStops.Length(), aExtendMode, aTileSize, aTileSpacing);
1438 void DisplayListBuilder::PushRadialGradient(
1439 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1440 bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter,
1441 const wr::LayoutSize& aRadius, const nsTArray<wr::GradientStop>& aStops,
1442 wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize,
1443 const wr::LayoutSize aTileSpacing) {
1444 wr_dp_push_radial_gradient(
1445 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1446 &mCurrentSpaceAndClipChain, aCenter, aRadius, aStops.Elements(),
1447 aStops.Length(), aExtendMode, aTileSize, aTileSpacing);
1450 void DisplayListBuilder::PushConicGradient(
1451 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1452 bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter, const float aAngle,
1453 const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
1454 const wr::LayoutSize aTileSize, const wr::LayoutSize aTileSpacing) {
1455 wr_dp_push_conic_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
1456 aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
1457 aCenter, aAngle, aStops.Elements(), aStops.Length(),
1458 aExtendMode, aTileSize, aTileSpacing);
1461 void DisplayListBuilder::PushImage(
1462 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1463 bool aIsBackfaceVisible, bool aForceAntiAliasing,
1464 wr::ImageRendering aFilter, wr::ImageKey aImage, bool aPremultipliedAlpha,
1465 const wr::ColorF& aColor, bool aPreferCompositorSurface,
1466 bool aSupportsExternalCompositing) {
1467 wr::LayoutRect clip = MergeClipLeaf(aClip);
1468 WRDL_LOG("PushImage b=%s cl=%s\n", mWrState, ToString(aBounds).c_str(),
1469 ToString(clip).c_str());
1470 wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible,
1471 aForceAntiAliasing, &mCurrentSpaceAndClipChain, aFilter,
1472 aImage, aPremultipliedAlpha, aColor,
1473 aPreferCompositorSurface, aSupportsExternalCompositing);
1476 void DisplayListBuilder::PushRepeatingImage(
1477 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1478 bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize,
1479 const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter,
1480 wr::ImageKey aImage, bool aPremultipliedAlpha, const wr::ColorF& aColor) {
1481 wr::LayoutRect clip = MergeClipLeaf(aClip);
1482 WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState,
1483 ToString(aBounds).c_str(), ToString(clip).c_str(),
1484 ToString(aStretchSize).c_str(), ToString(aTileSpacing).c_str());
1485 wr_dp_push_repeating_image(
1486 mWrState, aBounds, clip, aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
1487 aStretchSize, aTileSpacing, aFilter, aImage, aPremultipliedAlpha, aColor);
1490 void DisplayListBuilder::PushYCbCrPlanarImage(
1491 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1492 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
1493 wr::ImageKey aImageChannel1, wr::ImageKey aImageChannel2,
1494 wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace,
1495 wr::WrColorRange aColorRange, wr::ImageRendering aRendering,
1496 bool aPreferCompositorSurface, bool aSupportsExternalCompositing) {
1497 wr_dp_push_yuv_planar_image(
1498 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1499 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1,
1500 aImageChannel2, aColorDepth, aColorSpace, aColorRange, aRendering,
1501 aPreferCompositorSurface, aSupportsExternalCompositing);
1504 void DisplayListBuilder::PushNV12Image(
1505 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1506 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
1507 wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth,
1508 wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange,
1509 wr::ImageRendering aRendering, bool aPreferCompositorSurface,
1510 bool aSupportsExternalCompositing) {
1511 wr_dp_push_yuv_NV12_image(
1512 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1513 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1, aColorDepth,
1514 aColorSpace, aColorRange, aRendering, aPreferCompositorSurface,
1515 aSupportsExternalCompositing);
1518 void DisplayListBuilder::PushP010Image(
1519 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1520 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
1521 wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth,
1522 wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange,
1523 wr::ImageRendering aRendering, bool aPreferCompositorSurface,
1524 bool aSupportsExternalCompositing) {
1525 wr_dp_push_yuv_P010_image(
1526 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1527 &mCurrentSpaceAndClipChain, aImageChannel0, aImageChannel1, aColorDepth,
1528 aColorSpace, aColorRange, aRendering, aPreferCompositorSurface,
1529 aSupportsExternalCompositing);
1532 void DisplayListBuilder::PushYCbCrInterleavedImage(
1533 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1534 bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
1535 wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace,
1536 wr::WrColorRange aColorRange, wr::ImageRendering aRendering,
1537 bool aPreferCompositorSurface, bool aSupportsExternalCompositing) {
1538 wr_dp_push_yuv_interleaved_image(
1539 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1540 &mCurrentSpaceAndClipChain, aImageChannel0, aColorDepth, aColorSpace,
1541 aColorRange, aRendering, aPreferCompositorSurface,
1542 aSupportsExternalCompositing);
1545 void DisplayListBuilder::PushIFrame(const LayoutDeviceRect& aDevPxBounds,
1546 bool aIsBackfaceVisible,
1547 PipelineId aPipeline,
1548 bool aIgnoreMissingPipeline) {
1549 // If the incoming bounds size has decimals (As it could when zoom is
1550 // involved), and is pushed straight through here, the compositor would end up
1551 // calculating the destination rect to paint the rendered iframe into
1552 // with those decimal values, rounding the result, instead of snapping. This
1553 // can cause the rendered iframe rect and its destination rect to be
1554 // mismatched, resulting in interpolation artifacts.
1555 auto snapped = aDevPxBounds;
1556 auto tl = snapped.TopLeft().Round();
1557 auto br = snapped.BottomRight().Round();
1559 snapped.SizeTo(LayoutDeviceSize(br.x - tl.x, br.y - tl.y));
1561 const auto bounds = wr::ToLayoutRect(snapped);
1562 wr_dp_push_iframe(mWrState, bounds, MergeClipLeaf(bounds), aIsBackfaceVisible,
1563 &mCurrentSpaceAndClipChain, aPipeline,
1564 aIgnoreMissingPipeline);
1567 void DisplayListBuilder::PushBorder(const wr::LayoutRect& aBounds,
1568 const wr::LayoutRect& aClip,
1569 bool aIsBackfaceVisible,
1570 const wr::LayoutSideOffsets& aWidths,
1571 const Range<const wr::BorderSide>& aSides,
1572 const wr::BorderRadius& aRadius,
1573 wr::AntialiasBorder aAntialias) {
1574 MOZ_ASSERT(aSides.length() == 4);
1575 if (aSides.length() != 4) {
1576 return;
1578 wr_dp_push_border(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1579 &mCurrentSpaceAndClipChain, aAntialias, aWidths, aSides[0],
1580 aSides[1], aSides[2], aSides[3], aRadius);
1583 void DisplayListBuilder::PushBorderImage(const wr::LayoutRect& aBounds,
1584 const wr::LayoutRect& aClip,
1585 bool aIsBackfaceVisible,
1586 const wr::WrBorderImage& aParams) {
1587 wr_dp_push_border_image(mWrState, aBounds, MergeClipLeaf(aClip),
1588 aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
1589 &aParams);
1592 void DisplayListBuilder::PushBorderGradient(
1593 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1594 bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths,
1595 const int32_t aWidth, const int32_t aHeight, bool aFill,
1596 const wr::DeviceIntSideOffsets& aSlice, const wr::LayoutPoint& aStartPoint,
1597 const wr::LayoutPoint& aEndPoint, const nsTArray<wr::GradientStop>& aStops,
1598 wr::ExtendMode aExtendMode) {
1599 wr_dp_push_border_gradient(
1600 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1601 &mCurrentSpaceAndClipChain, aWidths, aWidth, aHeight, aFill, aSlice,
1602 aStartPoint, aEndPoint, aStops.Elements(), aStops.Length(), aExtendMode);
1605 void DisplayListBuilder::PushBorderRadialGradient(
1606 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1607 bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
1608 const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
1609 const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode) {
1610 wr_dp_push_border_radial_gradient(
1611 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1612 &mCurrentSpaceAndClipChain, aWidths, aFill, aCenter, aRadius,
1613 aStops.Elements(), aStops.Length(), aExtendMode);
1616 void DisplayListBuilder::PushBorderConicGradient(
1617 const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
1618 bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
1619 const wr::LayoutPoint& aCenter, const float aAngle,
1620 const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode) {
1621 wr_dp_push_border_conic_gradient(
1622 mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1623 &mCurrentSpaceAndClipChain, aWidths, aFill, aCenter, aAngle,
1624 aStops.Elements(), aStops.Length(), aExtendMode);
1627 void DisplayListBuilder::PushText(const wr::LayoutRect& aBounds,
1628 const wr::LayoutRect& aClip,
1629 bool aIsBackfaceVisible,
1630 const wr::ColorF& aColor,
1631 wr::FontInstanceKey aFontKey,
1632 Range<const wr::GlyphInstance> aGlyphBuffer,
1633 const wr::GlyphOptions* aGlyphOptions) {
1634 wr_dp_push_text(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
1635 &mCurrentSpaceAndClipChain, aColor, aFontKey,
1636 &aGlyphBuffer[0], aGlyphBuffer.length(), aGlyphOptions);
1639 void DisplayListBuilder::PushLine(const wr::LayoutRect& aClip,
1640 bool aIsBackfaceVisible,
1641 const wr::Line& aLine) {
1642 wr::LayoutRect clip = MergeClipLeaf(aClip);
1643 wr_dp_push_line(mWrState, &clip, aIsBackfaceVisible,
1644 &mCurrentSpaceAndClipChain, &aLine.bounds,
1645 aLine.wavyLineThickness, aLine.orientation, &aLine.color,
1646 aLine.style);
1649 void DisplayListBuilder::PushShadow(const wr::LayoutRect& aRect,
1650 const wr::LayoutRect& aClip,
1651 bool aIsBackfaceVisible,
1652 const wr::Shadow& aShadow,
1653 bool aShouldInflate) {
1654 // Local clip_rects are translated inside of shadows, as they are assumed to
1655 // be part of the element drawing itself, and not a parent frame clipping it.
1656 // As such, it is not sound to apply the MergeClipLeaf optimization inside of
1657 // shadows. So we disable the optimization when we encounter a shadow.
1658 // Shadows don't span frames, so we don't have to worry about MergeClipLeaf
1659 // being re-enabled mid-shadow. The optimization is restored in PopAllShadows.
1660 SuspendClipLeafMerging();
1661 wr_dp_push_shadow(mWrState, aRect, aClip, aIsBackfaceVisible,
1662 &mCurrentSpaceAndClipChain, aShadow, aShouldInflate);
1665 void DisplayListBuilder::PopAllShadows() {
1666 wr_dp_pop_all_shadows(mWrState);
1667 ResumeClipLeafMerging();
1670 void DisplayListBuilder::SuspendClipLeafMerging() {
1671 if (mClipChainLeaf) {
1672 // No one should reinitialize mClipChainLeaf while we're suspended
1673 MOZ_ASSERT(!mSuspendedClipChainLeaf);
1675 mSuspendedClipChainLeaf = mClipChainLeaf;
1676 mSuspendedSpaceAndClipChain = Some(mCurrentSpaceAndClipChain);
1678 auto clipId = DefineRectClip(Nothing(), *mClipChainLeaf);
1679 auto clipChainId = DefineClipChain({clipId}, true);
1681 mCurrentSpaceAndClipChain.clip_chain = clipChainId.id;
1682 mClipChainLeaf = Nothing();
1686 void DisplayListBuilder::ResumeClipLeafMerging() {
1687 if (mSuspendedClipChainLeaf) {
1688 mCurrentSpaceAndClipChain = *mSuspendedSpaceAndClipChain;
1689 mClipChainLeaf = mSuspendedClipChainLeaf;
1691 mSuspendedClipChainLeaf = Nothing();
1692 mSuspendedSpaceAndClipChain = Nothing();
1696 void DisplayListBuilder::PushBoxShadow(
1697 const wr::LayoutRect& aRect, const wr::LayoutRect& aClip,
1698 bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds,
1699 const wr::LayoutVector2D& aOffset, const wr::ColorF& aColor,
1700 const float& aBlurRadius, const float& aSpreadRadius,
1701 const wr::BorderRadius& aBorderRadius,
1702 const wr::BoxShadowClipMode& aClipMode) {
1703 wr_dp_push_box_shadow(mWrState, aRect, MergeClipLeaf(aClip),
1704 aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
1705 aBoxBounds, aOffset, aColor, aBlurRadius, aSpreadRadius,
1706 aBorderRadius, aClipMode);
1709 void DisplayListBuilder::StartGroup(nsPaintedDisplayItem* aItem) {
1710 if (!mDisplayItemCache || mDisplayItemCache->IsFull()) {
1711 return;
1714 MOZ_ASSERT(!mCurrentCacheSlot);
1715 mCurrentCacheSlot = mDisplayItemCache->AssignSlot(aItem);
1717 if (mCurrentCacheSlot) {
1718 wr_dp_start_item_group(mWrState);
1722 void DisplayListBuilder::CancelGroup(const bool aDiscard) {
1723 if (!mDisplayItemCache || !mCurrentCacheSlot) {
1724 return;
1727 wr_dp_cancel_item_group(mWrState, aDiscard);
1728 mCurrentCacheSlot = Nothing();
1731 void DisplayListBuilder::FinishGroup() {
1732 if (!mDisplayItemCache || !mCurrentCacheSlot) {
1733 return;
1736 MOZ_ASSERT(mCurrentCacheSlot);
1738 if (wr_dp_finish_item_group(mWrState, mCurrentCacheSlot.ref())) {
1739 mDisplayItemCache->MarkSlotOccupied(mCurrentCacheSlot.ref(),
1740 CurrentSpaceAndClipChain());
1741 mDisplayItemCache->Stats().AddCached();
1744 mCurrentCacheSlot = Nothing();
1747 bool DisplayListBuilder::ReuseItem(nsPaintedDisplayItem* aItem) {
1748 if (!mDisplayItemCache) {
1749 return false;
1752 mDisplayItemCache->Stats().AddTotal();
1754 if (mDisplayItemCache->IsEmpty()) {
1755 return false;
1758 Maybe<uint16_t> slot =
1759 mDisplayItemCache->CanReuseItem(aItem, CurrentSpaceAndClipChain());
1761 if (slot) {
1762 mDisplayItemCache->Stats().AddReused();
1763 wr_dp_push_reuse_items(mWrState, slot.ref());
1764 return true;
1767 return false;
1770 Maybe<layers::ScrollableLayerGuid::ViewID>
1771 DisplayListBuilder::GetContainingFixedPosScrollTarget(
1772 const ActiveScrolledRoot* aAsr) {
1773 return mActiveFixedPosTracker
1774 ? mActiveFixedPosTracker->GetScrollTargetForASR(aAsr)
1775 : Nothing();
1778 Maybe<SideBits> DisplayListBuilder::GetContainingFixedPosSideBits(
1779 const ActiveScrolledRoot* aAsr) {
1780 return mActiveFixedPosTracker
1781 ? mActiveFixedPosTracker->GetSideBitsForASR(aAsr)
1782 : Nothing();
1785 DisplayListBuilder::FixedPosScrollTargetTracker::FixedPosScrollTargetTracker(
1786 DisplayListBuilder& aBuilder, const ActiveScrolledRoot* aAsr,
1787 layers::ScrollableLayerGuid::ViewID aScrollId, SideBits aSideBits)
1788 : mParentTracker(aBuilder.mActiveFixedPosTracker),
1789 mBuilder(aBuilder),
1790 mAsr(aAsr),
1791 mScrollId(aScrollId),
1792 mSideBits(aSideBits) {
1793 aBuilder.mActiveFixedPosTracker = this;
1796 DisplayListBuilder::FixedPosScrollTargetTracker::
1797 ~FixedPosScrollTargetTracker() {
1798 mBuilder.mActiveFixedPosTracker = mParentTracker;
1801 Maybe<layers::ScrollableLayerGuid::ViewID>
1802 DisplayListBuilder::FixedPosScrollTargetTracker::GetScrollTargetForASR(
1803 const ActiveScrolledRoot* aAsr) {
1804 return aAsr == mAsr ? Some(mScrollId) : Nothing();
1807 Maybe<SideBits>
1808 DisplayListBuilder::FixedPosScrollTargetTracker::GetSideBitsForASR(
1809 const ActiveScrolledRoot* aAsr) {
1810 return aAsr == mAsr ? Some(mSideBits) : Nothing();
1813 gfxContext* DisplayListBuilder::GetTextContext(
1814 wr::IpcResourceUpdateQueue& aResources,
1815 const layers::StackingContextHelper& aSc,
1816 layers::RenderRootStateManager* aManager, nsDisplayItem* aItem,
1817 nsRect& aBounds, const gfx::Point& aDeviceOffset) {
1818 if (!mCachedTextDT) {
1819 mCachedTextDT = new layout::TextDrawTarget(*this, aResources, aSc, aManager,
1820 aItem, aBounds);
1821 if (mCachedTextDT->IsValid()) {
1822 mCachedContext = MakeUnique<gfxContext>(mCachedTextDT, aDeviceOffset);
1824 } else {
1825 mCachedTextDT->Reinitialize(aResources, aSc, aManager, aItem, aBounds);
1826 mCachedContext->SetDeviceOffset(aDeviceOffset);
1827 mCachedContext->SetMatrix(gfx::Matrix());
1830 return mCachedContext.get();
1833 void DisplayListBuilder::PushInheritedClipChain(
1834 nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aClipChain) {
1835 if (!aClipChain || mInheritedClipChain == aClipChain) {
1836 return;
1838 if (!mInheritedClipChain) {
1839 mInheritedClipChain = aClipChain;
1840 return;
1843 mInheritedClipChain =
1844 aBuilder->CreateClipChainIntersection(mInheritedClipChain, aClipChain);
1847 } // namespace wr
1848 } // namespace mozilla
1850 extern "C" {
1852 void wr_transaction_notification_notified(uintptr_t aHandler,
1853 mozilla::wr::Checkpoint aWhen) {
1854 auto handler = reinterpret_cast<mozilla::wr::NotificationHandler*>(aHandler);
1855 handler->Notify(aWhen);
1856 // TODO: it would be better to get a callback when the object is destroyed on
1857 // the rust side and delete then.
1858 delete handler;
1861 void wr_register_thread_local_arena() {
1862 #ifdef MOZ_MEMORY
1863 jemalloc_thread_local_arena(true);
1864 #endif
1867 } // extern C