/src/mozilla-central/gfx/webrender_bindings/WebRenderAPI.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "WebRenderAPI.h" |
8 | | |
9 | | #include "gfxPrefs.h" |
10 | | #include "LayersLogging.h" |
11 | | #include "mozilla/webrender/RendererOGL.h" |
12 | | #include "mozilla/gfx/gfxVars.h" |
13 | | #include "mozilla/layers/CompositorThread.h" |
14 | | #include "mozilla/webrender/RenderCompositor.h" |
15 | | #include "mozilla/widget/CompositorWidget.h" |
16 | | #include "mozilla/layers/SynchronousTask.h" |
17 | | |
18 | | #define WRDL_LOG(...) |
19 | | //#define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__) |
20 | | //#define WRDL_LOG(...) if (XRE_IsContentProcess()) printf_stderr("WRDL(%p): " __VA_ARGS__) |
21 | | |
22 | | namespace mozilla { |
23 | | namespace wr { |
24 | | |
25 | | using layers::Stringify; |
26 | | |
27 | | MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderMallocSizeOf) |
28 | | |
29 | | class NewRenderer : public RendererEvent |
30 | | { |
31 | | public: |
32 | | NewRenderer(wr::DocumentHandle** aDocHandle, |
33 | | layers::CompositorBridgeParent* aBridge, |
34 | | uint32_t* aMaxTextureSize, |
35 | | bool* aUseANGLE, |
36 | | bool* aUseDComp, |
37 | | RefPtr<widget::CompositorWidget>&& aWidget, |
38 | | layers::SynchronousTask* aTask, |
39 | | LayoutDeviceIntSize aSize, |
40 | | layers::SyncHandle* aHandle) |
41 | | : mDocHandle(aDocHandle) |
42 | | , mMaxTextureSize(aMaxTextureSize) |
43 | | , mUseANGLE(aUseANGLE) |
44 | | , mUseDComp(aUseDComp) |
45 | | , mBridge(aBridge) |
46 | | , mCompositorWidget(std::move(aWidget)) |
47 | | , mTask(aTask) |
48 | | , mSize(aSize) |
49 | | , mSyncHandle(aHandle) |
50 | 0 | { |
51 | 0 | MOZ_COUNT_CTOR(NewRenderer); |
52 | 0 | } |
53 | | |
54 | | ~NewRenderer() |
55 | 0 | { |
56 | 0 | MOZ_COUNT_DTOR(NewRenderer); |
57 | 0 | } |
58 | | |
59 | | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
60 | 0 | { |
61 | 0 | layers::AutoCompleteTask complete(mTask); |
62 | 0 |
|
63 | 0 | UniquePtr<RenderCompositor> compositor = RenderCompositor::Create(std::move(mCompositorWidget)); |
64 | 0 | if (!compositor) { |
65 | 0 | // RenderCompositor::Create puts a message into gfxCriticalNote if it is nullptr |
66 | 0 | return; |
67 | 0 | } |
68 | 0 | |
69 | 0 | *mUseANGLE = compositor->UseANGLE(); |
70 | 0 | *mUseDComp = compositor->UseDComp(); |
71 | 0 |
|
72 | 0 | bool supportLowPriorityTransactions = true; // TODO only for main windows. |
73 | 0 | wr::Renderer* wrRenderer = nullptr; |
74 | 0 | if (!wr_window_new(aWindowId, mSize.width, mSize.height, supportLowPriorityTransactions, |
75 | 0 | compositor->gl(), |
76 | 0 | aRenderThread.ThreadPool().Raw(), |
77 | 0 | &WebRenderMallocSizeOf, |
78 | 0 | mDocHandle, &wrRenderer, |
79 | 0 | mMaxTextureSize)) { |
80 | 0 | // wr_window_new puts a message into gfxCriticalNote if it returns false |
81 | 0 | return; |
82 | 0 | } |
83 | 0 | MOZ_ASSERT(wrRenderer); |
84 | 0 |
|
85 | 0 | RefPtr<RenderThread> thread = &aRenderThread; |
86 | 0 | auto renderer = MakeUnique<RendererOGL>(std::move(thread), |
87 | 0 | std::move(compositor), |
88 | 0 | aWindowId, |
89 | 0 | wrRenderer, |
90 | 0 | mBridge); |
91 | 0 | if (wrRenderer && renderer) { |
92 | 0 | wr::WrExternalImageHandler handler = renderer->GetExternalImageHandler(); |
93 | 0 | wr_renderer_set_external_image_handler(wrRenderer, &handler); |
94 | 0 | if (gfx::gfxVars::UseWebRenderProgramBinary()) { |
95 | 0 | wr_renderer_update_program_cache(wrRenderer, aRenderThread.ProgramCache()->Raw()); |
96 | 0 | } |
97 | 0 | } |
98 | 0 |
|
99 | 0 | if (renderer) { |
100 | 0 | layers::SyncObjectHost* syncObj = renderer->GetSyncObject(); |
101 | 0 | if (syncObj) { |
102 | 0 | *mSyncHandle = syncObj->GetSyncHandle(); |
103 | 0 | } |
104 | 0 | } |
105 | 0 |
|
106 | 0 | aRenderThread.AddRenderer(aWindowId, std::move(renderer)); |
107 | 0 | } |
108 | | |
109 | | private: |
110 | | wr::DocumentHandle** mDocHandle; |
111 | | uint32_t* mMaxTextureSize; |
112 | | bool* mUseANGLE; |
113 | | bool* mUseDComp; |
114 | | layers::CompositorBridgeParent* mBridge; |
115 | | RefPtr<widget::CompositorWidget> mCompositorWidget; |
116 | | layers::SynchronousTask* mTask; |
117 | | LayoutDeviceIntSize mSize; |
118 | | layers::SyncHandle* mSyncHandle; |
119 | | }; |
120 | | |
121 | | class RemoveRenderer : public RendererEvent |
122 | | { |
123 | | public: |
124 | | explicit RemoveRenderer(layers::SynchronousTask* aTask) |
125 | | : mTask(aTask) |
126 | 0 | { |
127 | 0 | MOZ_COUNT_CTOR(RemoveRenderer); |
128 | 0 | } |
129 | | |
130 | | ~RemoveRenderer() |
131 | 0 | { |
132 | 0 | MOZ_COUNT_DTOR(RemoveRenderer); |
133 | 0 | } |
134 | | |
135 | | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
136 | 0 | { |
137 | 0 | aRenderThread.RemoveRenderer(aWindowId); |
138 | 0 | layers::AutoCompleteTask complete(mTask); |
139 | 0 | } |
140 | | |
141 | | private: |
142 | | layers::SynchronousTask* mTask; |
143 | | }; |
144 | | |
145 | | |
146 | | TransactionBuilder::TransactionBuilder(bool aUseSceneBuilderThread) |
147 | | : mUseSceneBuilderThread(aUseSceneBuilderThread) |
148 | 0 | { |
149 | 0 | mTxn = wr_transaction_new(mUseSceneBuilderThread); |
150 | 0 | } |
151 | | |
152 | | TransactionBuilder::~TransactionBuilder() |
153 | 0 | { |
154 | 0 | wr_transaction_delete(mTxn); |
155 | 0 | } |
156 | | |
157 | | void |
158 | | TransactionBuilder::SetLowPriority(bool aIsLowPriority) |
159 | 0 | { |
160 | 0 | wr_transaction_set_low_priority(mTxn, aIsLowPriority); |
161 | 0 | } |
162 | | |
163 | | void |
164 | | TransactionBuilder::UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch) |
165 | 0 | { |
166 | 0 | wr_transaction_update_epoch(mTxn, aPipelineId, aEpoch); |
167 | 0 | } |
168 | | |
169 | | void |
170 | | TransactionBuilder::SetRootPipeline(PipelineId aPipelineId) |
171 | 0 | { |
172 | 0 | wr_transaction_set_root_pipeline(mTxn, aPipelineId); |
173 | 0 | } |
174 | | |
175 | | void |
176 | | TransactionBuilder::RemovePipeline(PipelineId aPipelineId) |
177 | 0 | { |
178 | 0 | wr_transaction_remove_pipeline(mTxn, aPipelineId); |
179 | 0 | } |
180 | | |
181 | | void |
182 | | TransactionBuilder::SetDisplayList(gfx::Color aBgColor, |
183 | | Epoch aEpoch, |
184 | | mozilla::LayerSize aViewportSize, |
185 | | wr::WrPipelineId pipeline_id, |
186 | | const wr::LayoutSize& content_size, |
187 | | wr::BuiltDisplayListDescriptor dl_descriptor, |
188 | | wr::Vec<uint8_t>& dl_data) |
189 | 0 | { |
190 | 0 | wr_transaction_set_display_list(mTxn, |
191 | 0 | aEpoch, |
192 | 0 | ToColorF(aBgColor), |
193 | 0 | aViewportSize.width, aViewportSize.height, |
194 | 0 | pipeline_id, |
195 | 0 | content_size, |
196 | 0 | dl_descriptor, |
197 | 0 | &dl_data.inner); |
198 | 0 | } |
199 | | |
200 | | void |
201 | | TransactionBuilder::ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipelineId) |
202 | 0 | { |
203 | 0 | wr_transaction_clear_display_list(mTxn, aEpoch, aPipelineId); |
204 | 0 | } |
205 | | |
206 | | void |
207 | | TransactionBuilder::GenerateFrame() |
208 | 0 | { |
209 | 0 | wr_transaction_generate_frame(mTxn); |
210 | 0 | } |
211 | | |
212 | | void |
213 | | TransactionBuilder::UpdateDynamicProperties(const nsTArray<wr::WrOpacityProperty>& aOpacityArray, |
214 | | const nsTArray<wr::WrTransformProperty>& aTransformArray) |
215 | 0 | { |
216 | 0 | wr_transaction_update_dynamic_properties( |
217 | 0 | mTxn, |
218 | 0 | aOpacityArray.IsEmpty() ? nullptr : aOpacityArray.Elements(), |
219 | 0 | aOpacityArray.Length(), |
220 | 0 | aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(), |
221 | 0 | aTransformArray.Length()); |
222 | 0 | } |
223 | | |
224 | | bool |
225 | | TransactionBuilder::IsEmpty() const |
226 | 0 | { |
227 | 0 | return wr_transaction_is_empty(mTxn); |
228 | 0 | } |
229 | | |
230 | | void |
231 | | TransactionBuilder::SetWindowParameters(const LayoutDeviceIntSize& aWindowSize, |
232 | | const LayoutDeviceIntRect& aDocumentRect) |
233 | 0 | { |
234 | 0 | wr::DeviceUintSize wrWindowSize; |
235 | 0 | wrWindowSize.width = aWindowSize.width; |
236 | 0 | wrWindowSize.height = aWindowSize.height; |
237 | 0 | wr::DeviceUintRect wrDocRect; |
238 | 0 | wrDocRect.origin.x = aDocumentRect.x; |
239 | 0 | wrDocRect.origin.y = aDocumentRect.y; |
240 | 0 | wrDocRect.size.width = aDocumentRect.width; |
241 | 0 | wrDocRect.size.height = aDocumentRect.height; |
242 | 0 | wr_transaction_set_window_parameters(mTxn, &wrWindowSize, &wrDocRect); |
243 | 0 | } |
244 | | |
245 | | void |
246 | | TransactionBuilder::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId, |
247 | | const layers::FrameMetrics::ViewID& aScrollId, |
248 | | const wr::LayoutPoint& aScrollPosition) |
249 | 0 | { |
250 | 0 | wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition); |
251 | 0 | } |
252 | | |
253 | | TransactionWrapper::TransactionWrapper(Transaction* aTxn) |
254 | | : mTxn(aTxn) |
255 | 0 | { |
256 | 0 | } |
257 | | |
258 | | void |
259 | | TransactionWrapper::AppendTransformProperties(const nsTArray<wr::WrTransformProperty>& aTransformArray) |
260 | 0 | { |
261 | 0 | wr_transaction_append_transform_properties( |
262 | 0 | mTxn, |
263 | 0 | aTransformArray.IsEmpty() ? nullptr : aTransformArray.Elements(), |
264 | 0 | aTransformArray.Length()); |
265 | 0 | } |
266 | | |
267 | | void |
268 | | TransactionWrapper::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId, |
269 | | const layers::FrameMetrics::ViewID& aScrollId, |
270 | | const wr::LayoutPoint& aScrollPosition) |
271 | 0 | { |
272 | 0 | wr_transaction_scroll_layer(mTxn, aPipelineId, aScrollId, aScrollPosition); |
273 | 0 | } |
274 | | |
275 | | /*static*/ already_AddRefed<WebRenderAPI> |
276 | | WebRenderAPI::Create(layers::CompositorBridgeParent* aBridge, |
277 | | RefPtr<widget::CompositorWidget>&& aWidget, |
278 | | const wr::WrWindowId& aWindowId, |
279 | | LayoutDeviceIntSize aSize) |
280 | 0 | { |
281 | 0 | MOZ_ASSERT(aBridge); |
282 | 0 | MOZ_ASSERT(aWidget); |
283 | 0 | static_assert(sizeof(size_t) == sizeof(uintptr_t), |
284 | 0 | "The FFI bindings assume size_t is the same size as uintptr_t!"); |
285 | 0 |
|
286 | 0 | wr::DocumentHandle* docHandle = nullptr; |
287 | 0 | uint32_t maxTextureSize = 0; |
288 | 0 | bool useANGLE = false; |
289 | 0 | bool useDComp = false; |
290 | 0 | layers::SyncHandle syncHandle = 0; |
291 | 0 |
|
292 | 0 | // Dispatch a synchronous task because the DocumentHandle object needs to be created |
293 | 0 | // on the render thread. If need be we could delay waiting on this task until |
294 | 0 | // the next time we need to access the DocumentHandle object. |
295 | 0 | layers::SynchronousTask task("Create Renderer"); |
296 | 0 | auto event = MakeUnique<NewRenderer>(&docHandle, aBridge, &maxTextureSize, &useANGLE, &useDComp, |
297 | 0 | std::move(aWidget), &task, aSize, |
298 | 0 | &syncHandle); |
299 | 0 | RenderThread::Get()->RunEvent(aWindowId, std::move(event)); |
300 | 0 |
|
301 | 0 | task.Wait(); |
302 | 0 |
|
303 | 0 | if (!docHandle) { |
304 | 0 | return nullptr; |
305 | 0 | } |
306 | 0 | |
307 | 0 | return RefPtr<WebRenderAPI>(new WebRenderAPI(docHandle, aWindowId, maxTextureSize, useANGLE, useDComp, syncHandle)).forget(); |
308 | 0 | } |
309 | | |
310 | | already_AddRefed<WebRenderAPI> |
311 | | WebRenderAPI::Clone() |
312 | 0 | { |
313 | 0 | wr::DocumentHandle* docHandle = nullptr; |
314 | 0 | wr_api_clone(mDocHandle, &docHandle); |
315 | 0 |
|
316 | 0 | RefPtr<WebRenderAPI> renderApi = new WebRenderAPI(docHandle, mId, mMaxTextureSize, mUseANGLE, mUseDComp, mSyncHandle); |
317 | 0 | renderApi->mRootApi = this; // Hold root api |
318 | 0 | renderApi->mRootDocumentApi = this; |
319 | 0 | return renderApi.forget(); |
320 | 0 | } |
321 | | |
322 | | already_AddRefed<WebRenderAPI> |
323 | | WebRenderAPI::CreateDocument(LayoutDeviceIntSize aSize, int8_t aLayerIndex) |
324 | 0 | { |
325 | 0 | wr::DeviceUintSize wrSize; |
326 | 0 | wrSize.width = aSize.width; |
327 | 0 | wrSize.height = aSize.height; |
328 | 0 | wr::DocumentHandle* newDoc; |
329 | 0 |
|
330 | 0 | wr_api_create_document(mDocHandle, &newDoc, wrSize, aLayerIndex); |
331 | 0 |
|
332 | 0 | RefPtr<WebRenderAPI> api(new WebRenderAPI(newDoc, mId, |
333 | 0 | mMaxTextureSize, |
334 | 0 | mUseANGLE, |
335 | 0 | mUseDComp, |
336 | 0 | mSyncHandle)); |
337 | 0 | api->mRootApi = this; |
338 | 0 | return api.forget(); |
339 | 0 | } |
340 | | |
341 | | wr::WrIdNamespace |
342 | 0 | WebRenderAPI::GetNamespace() { |
343 | 0 | return wr_api_get_namespace(mDocHandle); |
344 | 0 | } |
345 | | |
346 | | WebRenderAPI::~WebRenderAPI() |
347 | 0 | { |
348 | 0 | if (!mRootDocumentApi) { |
349 | 0 | wr_api_delete_document(mDocHandle); |
350 | 0 | } |
351 | 0 |
|
352 | 0 | if (!mRootApi) { |
353 | 0 | RenderThread::Get()->SetDestroyed(GetId()); |
354 | 0 |
|
355 | 0 | layers::SynchronousTask task("Destroy WebRenderAPI"); |
356 | 0 | auto event = MakeUnique<RemoveRenderer>(&task); |
357 | 0 | RunOnRenderThread(std::move(event)); |
358 | 0 | task.Wait(); |
359 | 0 |
|
360 | 0 | wr_api_shut_down(mDocHandle); |
361 | 0 | } |
362 | 0 |
|
363 | 0 | wr_api_delete(mDocHandle); |
364 | 0 | } |
365 | | |
366 | | void |
367 | | WebRenderAPI::SendTransaction(TransactionBuilder& aTxn) |
368 | 0 | { |
369 | 0 | wr_api_send_transaction(mDocHandle, aTxn.Raw(), aTxn.UseSceneBuilderThread()); |
370 | 0 | } |
371 | | |
372 | | bool |
373 | | WebRenderAPI::HitTest(const wr::WorldPoint& aPoint, |
374 | | wr::WrPipelineId& aOutPipelineId, |
375 | | layers::FrameMetrics::ViewID& aOutScrollId, |
376 | | gfx::CompositorHitTestInfo& aOutHitInfo) |
377 | 0 | { |
378 | 0 | static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint16_t), |
379 | 0 | "CompositorHitTestInfo should be u16-sized"); |
380 | 0 | return wr_api_hit_test(mDocHandle, aPoint, |
381 | 0 | &aOutPipelineId, &aOutScrollId, (uint16_t*)&aOutHitInfo); |
382 | 0 | } |
383 | | |
384 | | void |
385 | | WebRenderAPI::Readback(const TimeStamp& aStartTime, |
386 | | gfx::IntSize size, |
387 | | uint8_t *buffer, |
388 | | uint32_t buffer_size) |
389 | 0 | { |
390 | 0 | class Readback : public RendererEvent |
391 | 0 | { |
392 | 0 | public: |
393 | 0 | explicit Readback(layers::SynchronousTask* aTask, |
394 | 0 | TimeStamp aStartTime, |
395 | 0 | gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize) |
396 | 0 | : mTask(aTask) |
397 | 0 | , mStartTime(aStartTime) |
398 | 0 | , mSize(aSize) |
399 | 0 | , mBuffer(aBuffer) |
400 | 0 | , mBufferSize(aBufferSize) |
401 | 0 | { |
402 | 0 | MOZ_COUNT_CTOR(Readback); |
403 | 0 | } |
404 | 0 |
|
405 | 0 | ~Readback() |
406 | 0 | { |
407 | 0 | MOZ_COUNT_DTOR(Readback); |
408 | 0 | } |
409 | 0 |
|
410 | 0 | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
411 | 0 | { |
412 | 0 | aRenderThread.UpdateAndRender(aWindowId, mStartTime, /* aReadback */ true); |
413 | 0 | wr_renderer_readback(aRenderThread.GetRenderer(aWindowId)->GetRenderer(), |
414 | 0 | mSize.width, mSize.height, mBuffer, mBufferSize); |
415 | 0 | layers::AutoCompleteTask complete(mTask); |
416 | 0 | } |
417 | 0 |
|
418 | 0 | layers::SynchronousTask* mTask; |
419 | 0 | TimeStamp mStartTime; |
420 | 0 | gfx::IntSize mSize; |
421 | 0 | uint8_t *mBuffer; |
422 | 0 | uint32_t mBufferSize; |
423 | 0 | }; |
424 | 0 |
|
425 | 0 | layers::SynchronousTask task("Readback"); |
426 | 0 | auto event = MakeUnique<Readback>(&task, aStartTime, size, buffer, buffer_size); |
427 | 0 | // This event will be passed from wr_backend thread to renderer thread. That |
428 | 0 | // implies that all frame data have been processed when the renderer runs this |
429 | 0 | // read-back event. Then, we could make sure this read-back event gets the |
430 | 0 | // latest result. |
431 | 0 | RunOnRenderThread(std::move(event)); |
432 | 0 |
|
433 | 0 | task.Wait(); |
434 | 0 | } |
435 | | |
436 | | void |
437 | | WebRenderAPI::ClearAllCaches() |
438 | 0 | { |
439 | 0 | wr_api_clear_all_caches(mDocHandle); |
440 | 0 | } |
441 | | |
442 | | void |
443 | | WebRenderAPI::Pause() |
444 | 0 | { |
445 | 0 | class PauseEvent : public RendererEvent |
446 | 0 | { |
447 | 0 | public: |
448 | 0 | explicit PauseEvent(layers::SynchronousTask* aTask) |
449 | 0 | : mTask(aTask) |
450 | 0 | { |
451 | 0 | MOZ_COUNT_CTOR(PauseEvent); |
452 | 0 | } |
453 | 0 |
|
454 | 0 | ~PauseEvent() |
455 | 0 | { |
456 | 0 | MOZ_COUNT_DTOR(PauseEvent); |
457 | 0 | } |
458 | 0 |
|
459 | 0 | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
460 | 0 | { |
461 | 0 | aRenderThread.Pause(aWindowId); |
462 | 0 | layers::AutoCompleteTask complete(mTask); |
463 | 0 | } |
464 | 0 |
|
465 | 0 | layers::SynchronousTask* mTask; |
466 | 0 | }; |
467 | 0 |
|
468 | 0 | layers::SynchronousTask task("Pause"); |
469 | 0 | auto event = MakeUnique<PauseEvent>(&task); |
470 | 0 | // This event will be passed from wr_backend thread to renderer thread. That |
471 | 0 | // implies that all frame data have been processed when the renderer runs this event. |
472 | 0 | RunOnRenderThread(std::move(event)); |
473 | 0 |
|
474 | 0 | task.Wait(); |
475 | 0 | } |
476 | | |
477 | | bool |
478 | | WebRenderAPI::Resume() |
479 | 0 | { |
480 | 0 | class ResumeEvent : public RendererEvent |
481 | 0 | { |
482 | 0 | public: |
483 | 0 | explicit ResumeEvent(layers::SynchronousTask* aTask, bool* aResult) |
484 | 0 | : mTask(aTask) |
485 | 0 | , mResult(aResult) |
486 | 0 | { |
487 | 0 | MOZ_COUNT_CTOR(ResumeEvent); |
488 | 0 | } |
489 | 0 |
|
490 | 0 | ~ResumeEvent() |
491 | 0 | { |
492 | 0 | MOZ_COUNT_DTOR(ResumeEvent); |
493 | 0 | } |
494 | 0 |
|
495 | 0 | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
496 | 0 | { |
497 | 0 | *mResult = aRenderThread.Resume(aWindowId); |
498 | 0 | layers::AutoCompleteTask complete(mTask); |
499 | 0 | } |
500 | 0 |
|
501 | 0 | layers::SynchronousTask* mTask; |
502 | 0 | bool* mResult; |
503 | 0 | }; |
504 | 0 |
|
505 | 0 | bool result = false; |
506 | 0 | layers::SynchronousTask task("Resume"); |
507 | 0 | auto event = MakeUnique<ResumeEvent>(&task, &result); |
508 | 0 | // This event will be passed from wr_backend thread to renderer thread. That |
509 | 0 | // implies that all frame data have been processed when the renderer runs this event. |
510 | 0 | RunOnRenderThread(std::move(event)); |
511 | 0 |
|
512 | 0 | task.Wait(); |
513 | 0 | return result; |
514 | 0 | } |
515 | | |
516 | | void |
517 | | WebRenderAPI::NotifyMemoryPressure() |
518 | 0 | { |
519 | 0 | wr_api_notify_memory_pressure(mDocHandle); |
520 | 0 | } |
521 | | |
522 | | void |
523 | | WebRenderAPI::AccumulateMemoryReport(MemoryReport* aReport) |
524 | 0 | { |
525 | 0 | wr_api_accumulate_memory_report(mDocHandle, aReport); |
526 | 0 | } |
527 | | |
528 | | void |
529 | | WebRenderAPI::WakeSceneBuilder() |
530 | 0 | { |
531 | 0 | wr_api_wake_scene_builder(mDocHandle); |
532 | 0 | } |
533 | | |
534 | | void |
535 | | WebRenderAPI::FlushSceneBuilder() |
536 | 0 | { |
537 | 0 | wr_api_flush_scene_builder(mDocHandle); |
538 | 0 | } |
539 | | |
540 | | void |
541 | | WebRenderAPI::WaitFlushed() |
542 | 0 | { |
543 | 0 | class WaitFlushedEvent : public RendererEvent |
544 | 0 | { |
545 | 0 | public: |
546 | 0 | explicit WaitFlushedEvent(layers::SynchronousTask* aTask) |
547 | 0 | : mTask(aTask) |
548 | 0 | { |
549 | 0 | MOZ_COUNT_CTOR(WaitFlushedEvent); |
550 | 0 | } |
551 | 0 |
|
552 | 0 | ~WaitFlushedEvent() |
553 | 0 | { |
554 | 0 | MOZ_COUNT_DTOR(WaitFlushedEvent); |
555 | 0 | } |
556 | 0 |
|
557 | 0 | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
558 | 0 | { |
559 | 0 | layers::AutoCompleteTask complete(mTask); |
560 | 0 | } |
561 | 0 |
|
562 | 0 | layers::SynchronousTask* mTask; |
563 | 0 | }; |
564 | 0 |
|
565 | 0 | layers::SynchronousTask task("WaitFlushed"); |
566 | 0 | auto event = MakeUnique<WaitFlushedEvent>(&task); |
567 | 0 | // This event will be passed from wr_backend thread to renderer thread. That |
568 | 0 | // implies that all frame data have been processed when the renderer runs this event. |
569 | 0 | RunOnRenderThread(std::move(event)); |
570 | 0 |
|
571 | 0 | task.Wait(); |
572 | 0 | } |
573 | | |
574 | | void |
575 | | WebRenderAPI::Capture() |
576 | 0 | { |
577 | 0 | uint8_t bits = 3; //TODO: get from JavaScript |
578 | 0 | const char* path = "wr-capture"; //TODO: get from JavaScript |
579 | 0 | const char* border = "--------------------------\n"; |
580 | 0 | printf("%s Capturing WR state to: %s\n%s", border, path, border); |
581 | 0 | wr_api_capture(mDocHandle, path, bits); |
582 | 0 | } |
583 | | |
584 | | |
585 | | void |
586 | | TransactionBuilder::Clear() |
587 | 0 | { |
588 | 0 | wr_resource_updates_clear(mTxn); |
589 | 0 | } |
590 | | |
591 | | void |
592 | 0 | TransactionBuilder::Notify(wr::Checkpoint aWhen, UniquePtr<NotificationHandler> aEvent) { |
593 | 0 | wr_transaction_notify(mTxn, aWhen, reinterpret_cast<uintptr_t>(aEvent.release())); |
594 | 0 | } |
595 | | |
596 | | void |
597 | | TransactionBuilder::AddImage(ImageKey key, const ImageDescriptor& aDescriptor, |
598 | | wr::Vec<uint8_t>& aBytes) |
599 | 0 | { |
600 | 0 | wr_resource_updates_add_image(mTxn, |
601 | 0 | key, |
602 | 0 | &aDescriptor, |
603 | 0 | &aBytes.inner); |
604 | 0 | } |
605 | | |
606 | | void |
607 | | TransactionBuilder::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor, |
608 | | wr::Vec<uint8_t>& aBytes) |
609 | 0 | { |
610 | 0 | wr_resource_updates_add_blob_image(mTxn, |
611 | 0 | key, |
612 | 0 | &aDescriptor, |
613 | 0 | &aBytes.inner); |
614 | 0 | } |
615 | | |
616 | | void |
617 | | TransactionBuilder::AddExternalImage(ImageKey key, |
618 | | const ImageDescriptor& aDescriptor, |
619 | | ExternalImageId aExtID, |
620 | | wr::WrExternalImageBufferType aBufferType, |
621 | | uint8_t aChannelIndex) |
622 | 0 | { |
623 | 0 | wr_resource_updates_add_external_image(mTxn, |
624 | 0 | key, |
625 | 0 | &aDescriptor, |
626 | 0 | aExtID, |
627 | 0 | aBufferType, |
628 | 0 | aChannelIndex); |
629 | 0 | } |
630 | | |
631 | | void |
632 | | TransactionBuilder::AddExternalImageBuffer(ImageKey aKey, |
633 | | const ImageDescriptor& aDescriptor, |
634 | | ExternalImageId aHandle) |
635 | 0 | { |
636 | 0 | auto channelIndex = 0; |
637 | 0 | AddExternalImage(aKey, aDescriptor, aHandle, |
638 | 0 | wr::WrExternalImageBufferType::ExternalBuffer, |
639 | 0 | channelIndex); |
640 | 0 | } |
641 | | |
642 | | void |
643 | | TransactionBuilder::UpdateImageBuffer(ImageKey aKey, |
644 | | const ImageDescriptor& aDescriptor, |
645 | | wr::Vec<uint8_t>& aBytes) |
646 | 0 | { |
647 | 0 | wr_resource_updates_update_image(mTxn, |
648 | 0 | aKey, |
649 | 0 | &aDescriptor, |
650 | 0 | &aBytes.inner); |
651 | 0 | } |
652 | | |
653 | | void |
654 | | TransactionBuilder::UpdateBlobImage(ImageKey aKey, |
655 | | const ImageDescriptor& aDescriptor, |
656 | | wr::Vec<uint8_t>& aBytes, |
657 | | const wr::DeviceUintRect& aDirtyRect) |
658 | 0 | { |
659 | 0 | wr_resource_updates_update_blob_image(mTxn, |
660 | 0 | aKey, |
661 | 0 | &aDescriptor, |
662 | 0 | &aBytes.inner, |
663 | 0 | aDirtyRect); |
664 | 0 | } |
665 | | |
666 | | void |
667 | | TransactionBuilder::UpdateExternalImage(ImageKey aKey, |
668 | | const ImageDescriptor& aDescriptor, |
669 | | ExternalImageId aExtID, |
670 | | wr::WrExternalImageBufferType aBufferType, |
671 | | uint8_t aChannelIndex) |
672 | 0 | { |
673 | 0 | wr_resource_updates_update_external_image(mTxn, |
674 | 0 | aKey, |
675 | 0 | &aDescriptor, |
676 | 0 | aExtID, |
677 | 0 | aBufferType, |
678 | 0 | aChannelIndex); |
679 | 0 | } |
680 | | |
681 | | void |
682 | | TransactionBuilder::UpdateExternalImageWithDirtyRect(ImageKey aKey, |
683 | | const ImageDescriptor& aDescriptor, |
684 | | ExternalImageId aExtID, |
685 | | wr::WrExternalImageBufferType aBufferType, |
686 | | const wr::DeviceUintRect& aDirtyRect, |
687 | | uint8_t aChannelIndex) |
688 | 0 | { |
689 | 0 | wr_resource_updates_update_external_image_with_dirty_rect(mTxn, |
690 | 0 | aKey, |
691 | 0 | &aDescriptor, |
692 | 0 | aExtID, |
693 | 0 | aBufferType, |
694 | 0 | aChannelIndex, |
695 | 0 | aDirtyRect); |
696 | 0 | } |
697 | | |
698 | | void TransactionBuilder::SetImageVisibleArea(ImageKey aKey, const wr::NormalizedRect& aArea) |
699 | 0 | { |
700 | 0 | wr_resource_updates_set_image_visible_area(mTxn, aKey, &aArea); |
701 | 0 | } |
702 | | |
703 | | void |
704 | | TransactionBuilder::DeleteImage(ImageKey aKey) |
705 | 0 | { |
706 | 0 | wr_resource_updates_delete_image(mTxn, aKey); |
707 | 0 | } |
708 | | |
709 | | void |
710 | | TransactionBuilder::AddRawFont(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes, uint32_t aIndex) |
711 | 0 | { |
712 | 0 | wr_resource_updates_add_raw_font(mTxn, aKey, &aBytes.inner, aIndex); |
713 | 0 | } |
714 | | |
715 | | void |
716 | | TransactionBuilder::AddFontDescriptor(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes, uint32_t aIndex) |
717 | 0 | { |
718 | 0 | wr_resource_updates_add_font_descriptor(mTxn, aKey, &aBytes.inner, aIndex); |
719 | 0 | } |
720 | | |
721 | | void |
722 | | TransactionBuilder::DeleteFont(wr::FontKey aKey) |
723 | 0 | { |
724 | 0 | wr_resource_updates_delete_font(mTxn, aKey); |
725 | 0 | } |
726 | | |
727 | | void |
728 | | TransactionBuilder::AddFontInstance(wr::FontInstanceKey aKey, |
729 | | wr::FontKey aFontKey, |
730 | | float aGlyphSize, |
731 | | const wr::FontInstanceOptions* aOptions, |
732 | | const wr::FontInstancePlatformOptions* aPlatformOptions, |
733 | | wr::Vec<uint8_t>& aVariations) |
734 | 0 | { |
735 | 0 | wr_resource_updates_add_font_instance(mTxn, aKey, aFontKey, aGlyphSize, |
736 | 0 | aOptions, aPlatformOptions, |
737 | 0 | &aVariations.inner); |
738 | 0 | } |
739 | | |
740 | | void |
741 | | TransactionBuilder::DeleteFontInstance(wr::FontInstanceKey aKey) |
742 | 0 | { |
743 | 0 | wr_resource_updates_delete_font_instance(mTxn, aKey); |
744 | 0 | } |
745 | | |
746 | | class FrameStartTime : public RendererEvent |
747 | | { |
748 | | public: |
749 | | explicit FrameStartTime(const TimeStamp& aTime) |
750 | | : mTime(aTime) |
751 | 0 | { |
752 | 0 | MOZ_COUNT_CTOR(FrameStartTime); |
753 | 0 | } |
754 | | |
755 | | ~FrameStartTime() |
756 | 0 | { |
757 | 0 | MOZ_COUNT_DTOR(FrameStartTime); |
758 | 0 | } |
759 | | |
760 | | virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override |
761 | 0 | { |
762 | 0 | auto renderer = aRenderThread.GetRenderer(aWindowId); |
763 | 0 | if (renderer) { |
764 | 0 | renderer->SetFrameStartTime(mTime); |
765 | 0 | } |
766 | 0 | } |
767 | | |
768 | | private: |
769 | | TimeStamp mTime; |
770 | | }; |
771 | | |
772 | | void |
773 | | WebRenderAPI::SetFrameStartTime(const TimeStamp& aTime) |
774 | 0 | { |
775 | 0 | auto event = MakeUnique<FrameStartTime>(aTime); |
776 | 0 | RunOnRenderThread(std::move(event)); |
777 | 0 | } |
778 | | |
779 | | void |
780 | | WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) |
781 | 0 | { |
782 | 0 | auto event = reinterpret_cast<uintptr_t>(aEvent.release()); |
783 | 0 | wr_api_send_external_event(mDocHandle, event); |
784 | 0 | } |
785 | | |
786 | | DisplayListBuilder::DisplayListBuilder(PipelineId aId, |
787 | | const wr::LayoutSize& aContentSize, |
788 | | size_t aCapacity) |
789 | | : mActiveFixedPosTracker(nullptr) |
790 | 0 | { |
791 | 0 | MOZ_COUNT_CTOR(DisplayListBuilder); |
792 | 0 | mWrState = wr_state_new(aId, aContentSize, aCapacity); |
793 | 0 | } |
794 | | |
795 | | DisplayListBuilder::~DisplayListBuilder() |
796 | 0 | { |
797 | 0 | MOZ_COUNT_DTOR(DisplayListBuilder); |
798 | 0 | wr_state_delete(mWrState); |
799 | 0 | } |
800 | | |
801 | 0 | void DisplayListBuilder::Save() { wr_dp_save(mWrState); } |
802 | 0 | void DisplayListBuilder::Restore() { wr_dp_restore(mWrState); } |
803 | 0 | void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState); } |
804 | | |
805 | | usize DisplayListBuilder::Dump(usize aIndent, |
806 | | const Maybe<usize>& aStart, |
807 | | const Maybe<usize>& aEnd) |
808 | 0 | { |
809 | 0 | return wr_dump_display_list(mWrState, aIndent, aStart.ptrOr(nullptr), aEnd.ptrOr(nullptr)); |
810 | 0 | } |
811 | | |
812 | | void |
813 | | DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize, |
814 | | BuiltDisplayList& aOutDisplayList) |
815 | 0 | { |
816 | 0 | wr_api_finalize_builder(mWrState, |
817 | 0 | &aOutContentSize, |
818 | 0 | &aOutDisplayList.dl_desc, |
819 | 0 | &aOutDisplayList.dl.inner); |
820 | 0 | } |
821 | | |
822 | | Maybe<wr::WrClipId> |
823 | | DisplayListBuilder::PushStackingContext(const wr::LayoutRect& aBounds, |
824 | | const wr::WrClipId* aClipNodeId, |
825 | | const WrAnimationProperty* aAnimation, |
826 | | const float* aOpacity, |
827 | | const gfx::Matrix4x4* aTransform, |
828 | | wr::TransformStyle aTransformStyle, |
829 | | const gfx::Matrix4x4* aPerspective, |
830 | | const wr::MixBlendMode& aMixBlendMode, |
831 | | const nsTArray<wr::WrFilterOp>& aFilters, |
832 | | bool aIsBackfaceVisible, |
833 | | const wr::RasterSpace& aRasterSpace) |
834 | 0 | { |
835 | 0 | MOZ_ASSERT(mClipChainLeaf.isNothing(), |
836 | 0 | "Non-empty leaf from clip chain given, but not used with SC!"); |
837 | 0 |
|
838 | 0 | wr::LayoutTransform matrix; |
839 | 0 | if (aTransform) { |
840 | 0 | matrix = ToLayoutTransform(*aTransform); |
841 | 0 | } |
842 | 0 | const wr::LayoutTransform* maybeTransform = aTransform ? &matrix : nullptr; |
843 | 0 | wr::LayoutTransform perspective; |
844 | 0 | if (aPerspective) { |
845 | 0 | perspective = ToLayoutTransform(*aPerspective); |
846 | 0 | } |
847 | 0 |
|
848 | 0 | const wr::LayoutTransform* maybePerspective = aPerspective ? &perspective : nullptr; |
849 | 0 | const size_t* maybeClipNodeId = aClipNodeId ? &aClipNodeId->id : nullptr; |
850 | 0 | WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState, Stringify(aBounds).c_str(), |
851 | 0 | aTransform ? Stringify(*aTransform).c_str() : "none"); |
852 | 0 |
|
853 | 0 | bool outIsReferenceFrame = false; |
854 | 0 | uintptr_t outReferenceFrameId = 0; |
855 | 0 | wr_dp_push_stacking_context(mWrState, aBounds, maybeClipNodeId, aAnimation, |
856 | 0 | aOpacity, maybeTransform, aTransformStyle, |
857 | 0 | maybePerspective, aMixBlendMode, |
858 | 0 | aFilters.Elements(), aFilters.Length(), |
859 | 0 | aIsBackfaceVisible, aRasterSpace, |
860 | 0 | &outIsReferenceFrame, &outReferenceFrameId); |
861 | 0 | return outIsReferenceFrame ? Some(wr::WrClipId { outReferenceFrameId }) : Nothing(); |
862 | 0 | } |
863 | | |
864 | | void |
865 | | DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame) |
866 | 0 | { |
867 | 0 | WRDL_LOG("PopStackingContext\n", mWrState); |
868 | 0 | wr_dp_pop_stacking_context(mWrState, aIsReferenceFrame); |
869 | 0 | } |
870 | | |
871 | | wr::WrClipChainId |
872 | | DisplayListBuilder::DefineClipChain(const Maybe<wr::WrClipChainId>& aParent, |
873 | | const nsTArray<wr::WrClipId>& aClips) |
874 | 0 | { |
875 | 0 | nsTArray<size_t> clipIds; |
876 | 0 | for (wr::WrClipId id : aClips) { |
877 | 0 | clipIds.AppendElement(id.id); |
878 | 0 | } |
879 | 0 | uint64_t clipchainId = wr_dp_define_clipchain(mWrState, |
880 | 0 | aParent ? &(aParent->id) : nullptr, |
881 | 0 | clipIds.Elements(), clipIds.Length()); |
882 | 0 | WRDL_LOG("DefineClipChain id=%" PRIu64 " p=%s clips=%zu\n", mWrState, |
883 | 0 | clipchainId, |
884 | 0 | aParent ? Stringify(aParent->id).c_str() : "(nil)", |
885 | 0 | clipIds.Length()); |
886 | 0 | return wr::WrClipChainId{ clipchainId }; |
887 | 0 | } |
888 | | |
889 | | wr::WrClipId |
890 | | DisplayListBuilder::DefineClip(const Maybe<wr::WrClipId>& aParentId, |
891 | | const wr::LayoutRect& aClipRect, |
892 | | const nsTArray<wr::ComplexClipRegion>* aComplex, |
893 | | const wr::WrImageMask* aMask) |
894 | 0 | { |
895 | 0 | size_t clip_id = wr_dp_define_clip(mWrState, |
896 | 0 | aParentId ? &(aParentId->id) : nullptr, |
897 | 0 | aClipRect, |
898 | 0 | aComplex ? aComplex->Elements() : nullptr, |
899 | 0 | aComplex ? aComplex->Length() : 0, |
900 | 0 | aMask); |
901 | 0 | WRDL_LOG("DefineClip id=%zu p=%s r=%s m=%p b=%s complex=%zu\n", mWrState, |
902 | 0 | clip_id, aParentId ? Stringify(aParentId->id).c_str() : "(nil)", |
903 | 0 | Stringify(aClipRect).c_str(), aMask, |
904 | 0 | aMask ? Stringify(aMask->rect).c_str() : "none", |
905 | 0 | aComplex ? aComplex->Length() : 0); |
906 | 0 | return wr::WrClipId { clip_id }; |
907 | 0 | } |
908 | | |
909 | | void |
910 | | DisplayListBuilder::PushClip(const wr::WrClipId& aClipId) |
911 | 0 | { |
912 | 0 | WRDL_LOG("PushClip id=%zu\n", mWrState, aClipId.id); |
913 | 0 | wr_dp_push_clip(mWrState, aClipId.id); |
914 | 0 | } |
915 | | |
916 | | void |
917 | | DisplayListBuilder::PopClip() |
918 | 0 | { |
919 | 0 | WRDL_LOG("PopClip\n", mWrState); |
920 | 0 | wr_dp_pop_clip(mWrState); |
921 | 0 | } |
922 | | |
923 | | wr::WrClipId |
924 | | DisplayListBuilder::DefineStickyFrame(const wr::LayoutRect& aContentRect, |
925 | | const float* aTopMargin, |
926 | | const float* aRightMargin, |
927 | | const float* aBottomMargin, |
928 | | const float* aLeftMargin, |
929 | | const StickyOffsetBounds& aVerticalBounds, |
930 | | const StickyOffsetBounds& aHorizontalBounds, |
931 | | const wr::LayoutVector2D& aAppliedOffset) |
932 | 0 | { |
933 | 0 | size_t id = wr_dp_define_sticky_frame(mWrState, aContentRect, aTopMargin, |
934 | 0 | aRightMargin, aBottomMargin, aLeftMargin, aVerticalBounds, aHorizontalBounds, |
935 | 0 | aAppliedOffset); |
936 | 0 | WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n", |
937 | 0 | mWrState, id, |
938 | 0 | Stringify(aContentRect).c_str(), |
939 | 0 | aTopMargin ? Stringify(*aTopMargin).c_str() : "none", |
940 | 0 | aRightMargin ? Stringify(*aRightMargin).c_str() : "none", |
941 | 0 | aBottomMargin ? Stringify(*aBottomMargin).c_str() : "none", |
942 | 0 | aLeftMargin ? Stringify(*aLeftMargin).c_str() : "none", |
943 | 0 | Stringify(aVerticalBounds).c_str(), |
944 | 0 | Stringify(aHorizontalBounds).c_str(), |
945 | 0 | Stringify(aAppliedOffset).c_str()); |
946 | 0 | return wr::WrClipId { id }; |
947 | 0 | } |
948 | | |
949 | | Maybe<wr::WrClipId> |
950 | | DisplayListBuilder::GetScrollIdForDefinedScrollLayer(layers::FrameMetrics::ViewID aViewId) const |
951 | 0 | { |
952 | 0 | if (aViewId == layers::FrameMetrics::NULL_SCROLL_ID) { |
953 | 0 | return Some(wr::WrClipId::RootScrollNode()); |
954 | 0 | } |
955 | 0 | |
956 | 0 | auto it = mScrollIds.find(aViewId); |
957 | 0 | if (it == mScrollIds.end()) { |
958 | 0 | return Nothing(); |
959 | 0 | } |
960 | 0 | |
961 | 0 | return Some(it->second); |
962 | 0 | } |
963 | | |
964 | | wr::WrClipId |
965 | | DisplayListBuilder::DefineScrollLayer(const layers::FrameMetrics::ViewID& aViewId, |
966 | | const Maybe<wr::WrClipId>& aParentId, |
967 | | const wr::LayoutRect& aContentRect, |
968 | | const wr::LayoutRect& aClipRect) |
969 | 0 | { |
970 | 0 | auto it = mScrollIds.find(aViewId); |
971 | 0 | if (it != mScrollIds.end()) { |
972 | 0 | return it->second; |
973 | 0 | } |
974 | 0 | |
975 | 0 | // We haven't defined aViewId before, so let's define it now. |
976 | 0 | size_t numericScrollId = wr_dp_define_scroll_layer( |
977 | 0 | mWrState, |
978 | 0 | aViewId, |
979 | 0 | aParentId ? &(aParentId->id) : nullptr, |
980 | 0 | aContentRect, |
981 | 0 | aClipRect); |
982 | 0 |
|
983 | 0 | WRDL_LOG("DefineScrollLayer id=%" PRIu64 "/%zu p=%s co=%s cl=%s\n", mWrState, |
984 | 0 | aViewId, numericScrollId, |
985 | 0 | aParentId ? Stringify(aParentId->id).c_str() : "(nil)", |
986 | 0 | Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str()); |
987 | 0 |
|
988 | 0 | auto clipId = wr::WrClipId { numericScrollId }; |
989 | 0 | mScrollIds[aViewId] = clipId; |
990 | 0 | return clipId; |
991 | 0 | } |
992 | | |
993 | | void |
994 | | DisplayListBuilder::PushClipAndScrollInfo(const wr::WrClipId* aScrollId, |
995 | | const wr::WrClipChainId* aClipChainId, |
996 | | const Maybe<wr::LayoutRect>& aClipChainLeaf) |
997 | 0 | { |
998 | 0 | if (aScrollId) { |
999 | 0 | WRDL_LOG("PushClipAndScroll s=%zu c=%s\n", mWrState, aScrollId->id, |
1000 | 0 | aClipChainId ? Stringify(aClipChainId->id).c_str() : "none"); |
1001 | 0 | wr_dp_push_clip_and_scroll_info(mWrState, aScrollId->id, |
1002 | 0 | aClipChainId ? &(aClipChainId->id) : nullptr); |
1003 | 0 | } |
1004 | 0 | mClipChainLeaf = aClipChainLeaf; |
1005 | 0 | } |
1006 | | |
1007 | | void |
1008 | | DisplayListBuilder::PopClipAndScrollInfo(const wr::WrClipId* aScrollId) |
1009 | 0 | { |
1010 | 0 | if (aScrollId) { |
1011 | 0 | WRDL_LOG("PopClipAndScroll\n", mWrState); |
1012 | 0 | wr_dp_pop_clip_and_scroll_info(mWrState); |
1013 | 0 | } |
1014 | 0 | mClipChainLeaf.reset(); |
1015 | 0 | } |
1016 | | |
1017 | | void |
1018 | | DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds, |
1019 | | const wr::LayoutRect& aClip, |
1020 | | bool aIsBackfaceVisible, |
1021 | | const wr::ColorF& aColor) |
1022 | 0 | { |
1023 | 0 | wr::LayoutRect clip = MergeClipLeaf(aClip); |
1024 | 0 | WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState, |
1025 | 0 | Stringify(aBounds).c_str(), |
1026 | 0 | Stringify(clip).c_str(), |
1027 | 0 | Stringify(aColor).c_str()); |
1028 | 0 | wr_dp_push_rect(mWrState, aBounds, clip, |
1029 | 0 | aIsBackfaceVisible, aColor); |
1030 | 0 | } |
1031 | | |
1032 | | void |
1033 | | DisplayListBuilder::PushClearRect(const wr::LayoutRect& aBounds) |
1034 | 0 | { |
1035 | 0 | wr::LayoutRect clip = MergeClipLeaf(aBounds); |
1036 | 0 | WRDL_LOG("PushClearRect b=%s c=%s\n", mWrState, |
1037 | 0 | Stringify(aBounds).c_str(), Stringify(clip).c_str()); |
1038 | 0 | wr_dp_push_clear_rect(mWrState, aBounds, clip); |
1039 | 0 | } |
1040 | | |
1041 | | void |
1042 | | DisplayListBuilder::PushLinearGradient(const wr::LayoutRect& aBounds, |
1043 | | const wr::LayoutRect& aClip, |
1044 | | bool aIsBackfaceVisible, |
1045 | | const wr::LayoutPoint& aStartPoint, |
1046 | | const wr::LayoutPoint& aEndPoint, |
1047 | | const nsTArray<wr::GradientStop>& aStops, |
1048 | | wr::ExtendMode aExtendMode, |
1049 | | const wr::LayoutSize aTileSize, |
1050 | | const wr::LayoutSize aTileSpacing) |
1051 | 0 | { |
1052 | 0 | wr_dp_push_linear_gradient(mWrState, |
1053 | 0 | aBounds, MergeClipLeaf(aClip), |
1054 | 0 | aIsBackfaceVisible, |
1055 | 0 | aStartPoint, aEndPoint, |
1056 | 0 | aStops.Elements(), aStops.Length(), |
1057 | 0 | aExtendMode, |
1058 | 0 | aTileSize, aTileSpacing); |
1059 | 0 | } |
1060 | | |
1061 | | void |
1062 | | DisplayListBuilder::PushRadialGradient(const wr::LayoutRect& aBounds, |
1063 | | const wr::LayoutRect& aClip, |
1064 | | bool aIsBackfaceVisible, |
1065 | | const wr::LayoutPoint& aCenter, |
1066 | | const wr::LayoutSize& aRadius, |
1067 | | const nsTArray<wr::GradientStop>& aStops, |
1068 | | wr::ExtendMode aExtendMode, |
1069 | | const wr::LayoutSize aTileSize, |
1070 | | const wr::LayoutSize aTileSpacing) |
1071 | 0 | { |
1072 | 0 | wr_dp_push_radial_gradient(mWrState, |
1073 | 0 | aBounds, MergeClipLeaf(aClip), |
1074 | 0 | aIsBackfaceVisible, |
1075 | 0 | aCenter, aRadius, |
1076 | 0 | aStops.Elements(), aStops.Length(), |
1077 | 0 | aExtendMode, |
1078 | 0 | aTileSize, aTileSpacing); |
1079 | 0 | } |
1080 | | |
1081 | | void |
1082 | | DisplayListBuilder::PushImage(const wr::LayoutRect& aBounds, |
1083 | | const wr::LayoutRect& aClip, |
1084 | | bool aIsBackfaceVisible, |
1085 | | wr::ImageRendering aFilter, |
1086 | | wr::ImageKey aImage, |
1087 | | bool aPremultipliedAlpha, |
1088 | | const wr::ColorF& aColor) |
1089 | 0 | { |
1090 | 0 | wr::LayoutSize size; |
1091 | 0 | size.width = aBounds.size.width; |
1092 | 0 | size.height = aBounds.size.height; |
1093 | 0 | PushImage(aBounds, aClip, aIsBackfaceVisible, size, size, |
1094 | 0 | aFilter, aImage, aPremultipliedAlpha, aColor); |
1095 | 0 | } |
1096 | | |
1097 | | void |
1098 | | DisplayListBuilder::PushImage(const wr::LayoutRect& aBounds, |
1099 | | const wr::LayoutRect& aClip, |
1100 | | bool aIsBackfaceVisible, |
1101 | | const wr::LayoutSize& aStretchSize, |
1102 | | const wr::LayoutSize& aTileSpacing, |
1103 | | wr::ImageRendering aFilter, |
1104 | | wr::ImageKey aImage, |
1105 | | bool aPremultipliedAlpha, |
1106 | | const wr::ColorF& aColor) |
1107 | 0 | { |
1108 | 0 | wr::LayoutRect clip = MergeClipLeaf(aClip); |
1109 | 0 | WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState, |
1110 | 0 | Stringify(aBounds).c_str(), |
1111 | 0 | Stringify(clip).c_str(), Stringify(aStretchSize).c_str(), |
1112 | 0 | Stringify(aTileSpacing).c_str()); |
1113 | 0 | wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible, |
1114 | 0 | aStretchSize, aTileSpacing, aFilter, aImage, |
1115 | 0 | aPremultipliedAlpha, aColor); |
1116 | 0 | } |
1117 | | |
1118 | | void |
1119 | | DisplayListBuilder::PushYCbCrPlanarImage(const wr::LayoutRect& aBounds, |
1120 | | const wr::LayoutRect& aClip, |
1121 | | bool aIsBackfaceVisible, |
1122 | | wr::ImageKey aImageChannel0, |
1123 | | wr::ImageKey aImageChannel1, |
1124 | | wr::ImageKey aImageChannel2, |
1125 | | wr::WrYuvColorSpace aColorSpace, |
1126 | | wr::ImageRendering aRendering) |
1127 | 0 | { |
1128 | 0 | wr_dp_push_yuv_planar_image(mWrState, |
1129 | 0 | aBounds, |
1130 | 0 | MergeClipLeaf(aClip), |
1131 | 0 | aIsBackfaceVisible, |
1132 | 0 | aImageChannel0, |
1133 | 0 | aImageChannel1, |
1134 | 0 | aImageChannel2, |
1135 | 0 | aColorSpace, |
1136 | 0 | aRendering); |
1137 | 0 | } |
1138 | | |
1139 | | void |
1140 | | DisplayListBuilder::PushNV12Image(const wr::LayoutRect& aBounds, |
1141 | | const wr::LayoutRect& aClip, |
1142 | | bool aIsBackfaceVisible, |
1143 | | wr::ImageKey aImageChannel0, |
1144 | | wr::ImageKey aImageChannel1, |
1145 | | wr::WrYuvColorSpace aColorSpace, |
1146 | | wr::ImageRendering aRendering) |
1147 | 0 | { |
1148 | 0 | wr_dp_push_yuv_NV12_image(mWrState, |
1149 | 0 | aBounds, |
1150 | 0 | MergeClipLeaf(aClip), |
1151 | 0 | aIsBackfaceVisible, |
1152 | 0 | aImageChannel0, |
1153 | 0 | aImageChannel1, |
1154 | 0 | aColorSpace, |
1155 | 0 | aRendering); |
1156 | 0 | } |
1157 | | |
1158 | | void |
1159 | | DisplayListBuilder::PushYCbCrInterleavedImage(const wr::LayoutRect& aBounds, |
1160 | | const wr::LayoutRect& aClip, |
1161 | | bool aIsBackfaceVisible, |
1162 | | wr::ImageKey aImageChannel0, |
1163 | | wr::WrYuvColorSpace aColorSpace, |
1164 | | wr::ImageRendering aRendering) |
1165 | 0 | { |
1166 | 0 | wr_dp_push_yuv_interleaved_image(mWrState, |
1167 | 0 | aBounds, |
1168 | 0 | MergeClipLeaf(aClip), |
1169 | 0 | aIsBackfaceVisible, |
1170 | 0 | aImageChannel0, |
1171 | 0 | aColorSpace, |
1172 | 0 | aRendering); |
1173 | 0 | } |
1174 | | |
1175 | | void |
1176 | | DisplayListBuilder::PushIFrame(const wr::LayoutRect& aBounds, |
1177 | | bool aIsBackfaceVisible, |
1178 | | PipelineId aPipeline, |
1179 | | bool aIgnoreMissingPipeline) |
1180 | 0 | { |
1181 | 0 | wr_dp_push_iframe(mWrState, aBounds, MergeClipLeaf(aBounds), |
1182 | 0 | aIsBackfaceVisible, aPipeline, aIgnoreMissingPipeline); |
1183 | 0 | } |
1184 | | |
1185 | | void |
1186 | | DisplayListBuilder::PushBorder(const wr::LayoutRect& aBounds, |
1187 | | const wr::LayoutRect& aClip, |
1188 | | bool aIsBackfaceVisible, |
1189 | | const wr::LayoutSideOffsets& aWidths, |
1190 | | const Range<const wr::BorderSide>& aSides, |
1191 | | const wr::BorderRadius& aRadius) |
1192 | 0 | { |
1193 | 0 | MOZ_ASSERT(aSides.length() == 4); |
1194 | 0 | if (aSides.length() != 4) { |
1195 | 0 | return; |
1196 | 0 | } |
1197 | 0 | wr_dp_push_border(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, |
1198 | 0 | aWidths, aSides[0], aSides[1], aSides[2], aSides[3], aRadius); |
1199 | 0 | } |
1200 | | |
1201 | | void |
1202 | | DisplayListBuilder::PushBorderImage(const wr::LayoutRect& aBounds, |
1203 | | const wr::LayoutRect& aClip, |
1204 | | bool aIsBackfaceVisible, |
1205 | | const wr::LayoutSideOffsets& aWidths, |
1206 | | wr::ImageKey aImage, |
1207 | | const uint32_t aWidth, |
1208 | | const uint32_t aHeight, |
1209 | | const wr::SideOffsets2D<uint32_t>& aSlice, |
1210 | | const wr::SideOffsets2D<float>& aOutset, |
1211 | | const wr::RepeatMode& aRepeatHorizontal, |
1212 | | const wr::RepeatMode& aRepeatVertical) |
1213 | 0 | { |
1214 | 0 | wr_dp_push_border_image(mWrState, aBounds, MergeClipLeaf(aClip), |
1215 | 0 | aIsBackfaceVisible, aWidths, aImage, aWidth, aHeight, |
1216 | 0 | aSlice, aOutset, aRepeatHorizontal, aRepeatVertical); |
1217 | 0 | } |
1218 | | |
1219 | | void |
1220 | | DisplayListBuilder::PushBorderGradient(const wr::LayoutRect& aBounds, |
1221 | | const wr::LayoutRect& aClip, |
1222 | | bool aIsBackfaceVisible, |
1223 | | const wr::LayoutSideOffsets& aWidths, |
1224 | | const uint32_t aWidth, |
1225 | | const uint32_t aHeight, |
1226 | | const wr::SideOffsets2D<uint32_t>& aSlice, |
1227 | | const wr::LayoutPoint& aStartPoint, |
1228 | | const wr::LayoutPoint& aEndPoint, |
1229 | | const nsTArray<wr::GradientStop>& aStops, |
1230 | | wr::ExtendMode aExtendMode, |
1231 | | const wr::SideOffsets2D<float>& aOutset) |
1232 | 0 | { |
1233 | 0 | wr_dp_push_border_gradient(mWrState, aBounds, MergeClipLeaf(aClip), |
1234 | 0 | aIsBackfaceVisible, aWidths, aWidth, aHeight, |
1235 | 0 | aSlice, aStartPoint, aEndPoint, |
1236 | 0 | aStops.Elements(), aStops.Length(), |
1237 | 0 | aExtendMode, aOutset); |
1238 | 0 | } |
1239 | | |
1240 | | void |
1241 | | DisplayListBuilder::PushBorderRadialGradient(const wr::LayoutRect& aBounds, |
1242 | | const wr::LayoutRect& aClip, |
1243 | | bool aIsBackfaceVisible, |
1244 | | const wr::LayoutSideOffsets& aWidths, |
1245 | | const wr::LayoutPoint& aCenter, |
1246 | | const wr::LayoutSize& aRadius, |
1247 | | const nsTArray<wr::GradientStop>& aStops, |
1248 | | wr::ExtendMode aExtendMode, |
1249 | | const wr::SideOffsets2D<float>& aOutset) |
1250 | 0 | { |
1251 | 0 | wr_dp_push_border_radial_gradient( |
1252 | 0 | mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible, |
1253 | 0 | aWidths, aCenter, aRadius, aStops.Elements(), aStops.Length(), |
1254 | 0 | aExtendMode, aOutset); |
1255 | 0 | } |
1256 | | |
1257 | | void |
1258 | | DisplayListBuilder::PushText(const wr::LayoutRect& aBounds, |
1259 | | const wr::LayoutRect& aClip, |
1260 | | bool aIsBackfaceVisible, |
1261 | | const wr::ColorF& aColor, |
1262 | | wr::FontInstanceKey aFontKey, |
1263 | | Range<const wr::GlyphInstance> aGlyphBuffer, |
1264 | | const wr::GlyphOptions* aGlyphOptions) |
1265 | 0 | { |
1266 | 0 | wr_dp_push_text(mWrState, aBounds, MergeClipLeaf(aClip), |
1267 | 0 | aIsBackfaceVisible, |
1268 | 0 | aColor, |
1269 | 0 | aFontKey, |
1270 | 0 | &aGlyphBuffer[0], aGlyphBuffer.length(), |
1271 | 0 | aGlyphOptions); |
1272 | 0 | } |
1273 | | |
1274 | | void |
1275 | | DisplayListBuilder::PushLine(const wr::LayoutRect& aClip, |
1276 | | bool aIsBackfaceVisible, |
1277 | | const wr::Line& aLine) |
1278 | 0 | { |
1279 | 0 | wr::LayoutRect clip = MergeClipLeaf(aClip); |
1280 | 0 | wr_dp_push_line(mWrState, &clip, aIsBackfaceVisible, |
1281 | 0 | &aLine.bounds, aLine.wavyLineThickness, aLine.orientation, |
1282 | 0 | &aLine.color, aLine.style); |
1283 | 0 | } |
1284 | | |
1285 | | void |
1286 | | DisplayListBuilder::PushShadow(const wr::LayoutRect& aRect, |
1287 | | const wr::LayoutRect& aClip, |
1288 | | bool aIsBackfaceVisible, |
1289 | | const wr::Shadow& aShadow) |
1290 | 0 | { |
1291 | 0 | wr_dp_push_shadow(mWrState, aRect, MergeClipLeaf(aClip), |
1292 | 0 | aIsBackfaceVisible, aShadow); |
1293 | 0 | } |
1294 | | |
1295 | | void |
1296 | | DisplayListBuilder::PopAllShadows() |
1297 | 0 | { |
1298 | 0 | wr_dp_pop_all_shadows(mWrState); |
1299 | 0 | } |
1300 | | |
1301 | | void |
1302 | | DisplayListBuilder::PushBoxShadow(const wr::LayoutRect& aRect, |
1303 | | const wr::LayoutRect& aClip, |
1304 | | bool aIsBackfaceVisible, |
1305 | | const wr::LayoutRect& aBoxBounds, |
1306 | | const wr::LayoutVector2D& aOffset, |
1307 | | const wr::ColorF& aColor, |
1308 | | const float& aBlurRadius, |
1309 | | const float& aSpreadRadius, |
1310 | | const wr::BorderRadius& aBorderRadius, |
1311 | | const wr::BoxShadowClipMode& aClipMode) |
1312 | 0 | { |
1313 | 0 | wr_dp_push_box_shadow(mWrState, aRect, MergeClipLeaf(aClip), |
1314 | 0 | aIsBackfaceVisible, aBoxBounds, aOffset, aColor, |
1315 | 0 | aBlurRadius, aSpreadRadius, aBorderRadius, |
1316 | 0 | aClipMode); |
1317 | 0 | } |
1318 | | |
1319 | | Maybe<layers::FrameMetrics::ViewID> |
1320 | | DisplayListBuilder::GetContainingFixedPosScrollTarget(const ActiveScrolledRoot* aAsr) |
1321 | 0 | { |
1322 | 0 | return mActiveFixedPosTracker |
1323 | 0 | ? mActiveFixedPosTracker->GetScrollTargetForASR(aAsr) |
1324 | 0 | : Nothing(); |
1325 | 0 | } |
1326 | | |
1327 | | void |
1328 | | DisplayListBuilder::SetHitTestInfo(const layers::FrameMetrics::ViewID& aScrollId, |
1329 | | gfx::CompositorHitTestInfo aHitInfo) |
1330 | 0 | { |
1331 | 0 | static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint16_t), |
1332 | 0 | "CompositorHitTestInfo should be u16-sized"); |
1333 | 0 | wr_set_item_tag(mWrState, aScrollId, static_cast<uint16_t>(aHitInfo)); |
1334 | 0 | } |
1335 | | |
1336 | | void |
1337 | | DisplayListBuilder::ClearHitTestInfo() |
1338 | 0 | { |
1339 | 0 | wr_clear_item_tag(mWrState); |
1340 | 0 | } |
1341 | | |
1342 | | DisplayListBuilder::FixedPosScrollTargetTracker::FixedPosScrollTargetTracker( |
1343 | | DisplayListBuilder& aBuilder, |
1344 | | const ActiveScrolledRoot* aAsr, |
1345 | | layers::FrameMetrics::ViewID aScrollId) |
1346 | | : mParentTracker(aBuilder.mActiveFixedPosTracker) |
1347 | | , mBuilder(aBuilder) |
1348 | | , mAsr(aAsr) |
1349 | | , mScrollId(aScrollId) |
1350 | 0 | { |
1351 | 0 | aBuilder.mActiveFixedPosTracker = this; |
1352 | 0 | } |
1353 | | |
1354 | | DisplayListBuilder::FixedPosScrollTargetTracker::~FixedPosScrollTargetTracker() |
1355 | 0 | { |
1356 | 0 | mBuilder.mActiveFixedPosTracker = mParentTracker; |
1357 | 0 | } |
1358 | | |
1359 | | Maybe<layers::FrameMetrics::ViewID> |
1360 | | DisplayListBuilder::FixedPosScrollTargetTracker::GetScrollTargetForASR(const ActiveScrolledRoot* aAsr) |
1361 | 0 | { |
1362 | 0 | return aAsr == mAsr ? Some(mScrollId) : Nothing(); |
1363 | 0 | } |
1364 | | |
1365 | | } // namespace wr |
1366 | | } // namespace mozilla |
1367 | | |
1368 | | extern "C" { |
1369 | | |
1370 | 0 | void wr_transaction_notification_notified(uintptr_t aHandler, mozilla::wr::Checkpoint aWhen) { |
1371 | 0 | auto handler = reinterpret_cast<mozilla::wr::NotificationHandler*>(aHandler); |
1372 | 0 | handler->Notify(aWhen); |
1373 | 0 | // TODO: it would be better to get a callback when the object is destroyed on the |
1374 | 0 | // rust side and delete then. |
1375 | 0 | delete handler; |
1376 | 0 | } |
1377 | | |
1378 | | } // extern C |