1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/layers/NativeLayerWayland.h"
12 #include "nsGtkUtils.h"
13 #include "GLContextProvider.h"
14 #include "GLBlitHelper.h"
15 #include "mozilla/gfx/DataSurfaceHelpers.h"
16 #include "mozilla/gfx/Logging.h"
17 #include "mozilla/layers/SurfacePoolWayland.h"
18 #include "mozilla/StaticPrefs_widget.h"
19 #include "mozilla/webrender/RenderThread.h"
21 namespace mozilla::layers
{
23 using gfx::BackendType
;
24 using gfx::DrawTarget
;
32 using gfx::SamplingFilter
;
35 static const struct wl_callback_listener sFrameListenerNativeLayerWayland
= {
36 NativeLayerWayland::FrameCallbackHandler
};
38 CallbackMultiplexHelper::CallbackMultiplexHelper(CallbackFunc aCallbackFunc
,
40 : mCallbackFunc(aCallbackFunc
), mCallbackData(aCallbackData
) {}
42 void CallbackMultiplexHelper::Callback(uint32_t aTime
) {
48 // This is likely the first of a batch of frame callbacks being processed and
49 // may trigger the setup of a successive one. In order to avoid complexity,
50 // defer calling the callback function until we had a chance to process
51 // all pending frame callbacks.
54 nsCOMPtr
<nsIRunnable
> runnable
= NewRunnableMethod
<uint32_t>(
55 "layers::CallbackMultiplexHelper::RunCallback", this,
56 &CallbackMultiplexHelper::RunCallback
, aTime
);
57 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThreadQueue(
58 runnable
.forget(), EventQueuePriority::Vsync
));
61 void CallbackMultiplexHelper::RunCallback(uint32_t aTime
) {
62 mCallbackFunc(mCallbackData
, aTime
);
67 already_AddRefed
<NativeLayerRootWayland
>
68 NativeLayerRootWayland::CreateForMozContainer(MozContainer
* aContainer
) {
69 RefPtr
<NativeLayerRootWayland
> layerRoot
=
70 new NativeLayerRootWayland(aContainer
);
71 return layerRoot
.forget();
74 NativeLayerRootWayland::NativeLayerRootWayland(MozContainer
* aContainer
)
75 : mMutex("NativeLayerRootWayland"), mContainer(aContainer
) {
76 g_object_ref(mContainer
);
79 NativeLayerRootWayland::~NativeLayerRootWayland() {
80 GdkWindow
* gdkWindow
= gtk_widget_get_window(GTK_WIDGET(mContainer
));
82 GdkFrameClock
* frameClock
= gdk_window_get_frame_clock(gdkWindow
);
83 g_signal_handlers_disconnect_by_data(frameClock
, this);
85 g_object_unref(mContainer
);
88 already_AddRefed
<NativeLayer
> NativeLayerRootWayland::CreateLayer(
89 const IntSize
& aSize
, bool aIsOpaque
,
90 SurfacePoolHandle
* aSurfacePoolHandle
) {
91 RefPtr
<NativeLayer
> layer
= new NativeLayerWayland(
92 aSize
, aIsOpaque
, aSurfacePoolHandle
->AsSurfacePoolHandleWayland());
93 return layer
.forget();
96 already_AddRefed
<NativeLayer
>
97 NativeLayerRootWayland::CreateLayerForExternalTexture(bool aIsOpaque
) {
98 RefPtr
<NativeLayer
> layer
= new NativeLayerWayland(aIsOpaque
);
99 return layer
.forget();
102 void NativeLayerRootWayland::AppendLayer(NativeLayer
* aLayer
) {
103 MOZ_RELEASE_ASSERT(false);
104 MutexAutoLock
lock(mMutex
);
106 RefPtr
<NativeLayerWayland
> layerWayland
= aLayer
->AsNativeLayerWayland();
107 MOZ_RELEASE_ASSERT(layerWayland
);
109 mSublayers
.AppendElement(layerWayland
);
112 void NativeLayerRootWayland::RemoveLayer(NativeLayer
* aLayer
) {
113 MOZ_RELEASE_ASSERT(false);
114 MutexAutoLock
lock(mMutex
);
116 RefPtr
<NativeLayerWayland
> layerWayland
= aLayer
->AsNativeLayerWayland();
117 MOZ_RELEASE_ASSERT(layerWayland
);
119 mSublayers
.RemoveElement(layerWayland
);
122 void NativeLayerRootWayland::SetLayers(
123 const nsTArray
<RefPtr
<NativeLayer
>>& aLayers
) {
124 MutexAutoLock
lock(mMutex
);
126 nsTArray
<RefPtr
<NativeLayerWayland
>> newSublayers(aLayers
.Length());
127 for (const RefPtr
<NativeLayer
>& sublayer
: aLayers
) {
128 RefPtr
<NativeLayerWayland
> layer
= sublayer
->AsNativeLayerWayland();
129 newSublayers
.AppendElement(layer
);
132 if (newSublayers
!= mSublayers
) {
133 for (const RefPtr
<NativeLayerWayland
>& layer
: mSublayers
) {
134 if (!newSublayers
.Contains(layer
)) {
135 mOldSublayers
.AppendElement(layer
);
138 mSublayers
= std::move(newSublayers
);
143 bool NativeLayerRootWayland::CommitToScreen() {
144 MutexAutoLock
lock(mMutex
);
145 return CommitToScreen(lock
);
148 bool NativeLayerRootWayland::CommitToScreen(const MutexAutoLock
& aProofOfLock
) {
149 mFrameInProcess
= false;
151 MozContainerSurfaceLock
lock(mContainer
);
152 struct wl_surface
* containerSurface
= lock
.GetSurface();
153 if (!containerSurface
) {
154 if (!mCallbackRequested
) {
155 RefPtr
<NativeLayerRootWayland
> self(this);
156 moz_container_wayland_add_initial_draw_callback_locked(
157 mContainer
, [self
]() -> void {
158 MutexAutoLock
lock(self
->mMutex
);
159 if (!self
->mFrameInProcess
) {
160 self
->CommitToScreen(lock
);
162 self
->mCallbackRequested
= false;
164 mCallbackRequested
= true;
169 wl_surface
* previousSurface
= nullptr;
170 for (RefPtr
<NativeLayerWayland
>& layer
: mSublayers
) {
171 layer
->EnsureParentSurface(containerSurface
);
174 wl_subsurface_place_above(layer
->mWlSubsurface
, previousSurface
177 previousSurface
= layer
->mWlSurface
;
180 MOZ_RELEASE_ASSERT(layer
->mTransform
.Is2D());
181 auto transform2D
= layer
->mTransform
.As2D();
183 Rect surfaceRectClipped
=
184 Rect(0, 0, (float)layer
->mSize
.width
, (float)layer
->mSize
.height
);
186 surfaceRectClipped
.Intersect(Rect(layer
->mDisplayRect
));
188 transform2D
.PostTranslate((float)layer
->mPosition
.x
,
189 (float)layer
->mPosition
.y
);
190 surfaceRectClipped
= transform2D
.TransformBounds(surfaceRectClipped
);
192 if (layer
->mClipRect
) {
194 surfaceRectClipped
.Intersect(Rect(layer
->mClipRect
.value()));
197 if (roundf(surfaceRectClipped
.width
) > 0 &&
198 roundf(surfaceRectClipped
.height
) > 0) {
199 layer
->SetBufferTransformFlipped(transform2D
._11
< 0.0,
200 transform2D
._22
< 0.0);
202 double bufferScale
= moz_container_wayland_get_scale(mContainer
);
203 layer
->SetSubsurfacePosition(floor(surfaceRectClipped
.x
/ bufferScale
),
204 floor(surfaceRectClipped
.y
/ bufferScale
));
205 layer
->SetViewportDestinationSize(
206 ceil(surfaceRectClipped
.width
/ bufferScale
),
207 ceil(surfaceRectClipped
.height
/ bufferScale
));
209 auto transform2DInversed
= transform2D
.Inverse();
210 Rect bufferClip
= transform2DInversed
.TransformBounds(surfaceRectClipped
);
211 layer
->SetViewportSourceRect(bufferClip
);
220 for (RefPtr
<NativeLayerWayland
>& layer
: mOldSublayers
) {
223 mOldSublayers
.Clear();
225 nsCOMPtr
<nsIRunnable
> updateLayersRunnable
= NewRunnableMethod
<>(
226 "layers::NativeLayerRootWayland::UpdateLayersOnMainThread", this,
227 &NativeLayerRootWayland::UpdateLayersOnMainThread
);
228 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThreadQueue(
229 updateLayersRunnable
.forget(), EventQueuePriority::Normal
));
233 if (containerSurface
!= mWlSurface
) {
235 mShmBuffer
= widget::WaylandBufferSHM::Create(LayoutDeviceIntSize(1, 1));
238 mShmBuffer
->AttachAndCommit(containerSurface
);
239 mWlSurface
= containerSurface
;
241 wl_surface_commit(containerSurface
);
244 wl_display_flush(widget::WaylandDisplayGet()->GetDisplay());
248 void NativeLayerRootWayland::RequestFrameCallback(CallbackFunc aCallbackFunc
,
249 void* aCallbackData
) {
250 MutexAutoLock
lock(mMutex
);
252 mCallbackMultiplexHelper
=
253 new CallbackMultiplexHelper(aCallbackFunc
, aCallbackData
);
255 for (const RefPtr
<NativeLayerWayland
>& layer
: mSublayersOnMainThread
) {
256 layer
->RequestFrameCallback(mCallbackMultiplexHelper
);
259 MozContainerSurfaceLock
lockContainer(mContainer
);
260 struct wl_surface
* wlSurface
= lockContainer
.GetSurface();
262 wl_surface_commit(wlSurface
);
263 wl_display_flush(widget::WaylandDisplayGet()->GetDisplay());
267 static void sAfterFrameClockAfterPaint(
268 GdkFrameClock
* aClock
, NativeLayerRootWayland
* aNativeLayerRoot
) {
269 aNativeLayerRoot
->AfterFrameClockAfterPaint();
272 void NativeLayerRootWayland::AfterFrameClockAfterPaint() {
273 MutexAutoLock
lock(mMutex
);
274 MozContainerSurfaceLock
lockContainer(mContainer
);
275 struct wl_surface
* containerSurface
= lockContainer
.GetSurface();
276 for (const RefPtr
<NativeLayerWayland
>& layer
: mSublayersOnMainThread
) {
277 wl_surface_commit(layer
->mWlSurface
);
279 if (containerSurface
) {
280 wl_surface_commit(containerSurface
);
284 void NativeLayerRootWayland::UpdateLayersOnMainThread() {
285 AssertIsOnMainThread();
286 MutexAutoLock
lock(mMutex
);
288 static auto sGdkWaylandWindowAddCallbackSurface
=
289 (void (*)(GdkWindow
*, struct wl_surface
*))dlsym(
290 RTLD_DEFAULT
, "gdk_wayland_window_add_frame_callback_surface");
291 static auto sGdkWaylandWindowRemoveCallbackSurface
=
292 (void (*)(GdkWindow
*, struct wl_surface
*))dlsym(
293 RTLD_DEFAULT
, "gdk_wayland_window_remove_frame_callback_surface");
295 MozContainerSurfaceLock
lockContainer(mContainer
);
296 struct wl_surface
* containerSurface
= lockContainer
.GetSurface();
297 GdkWindow
* gdkWindow
= gtk_widget_get_window(GTK_WIDGET(mContainer
));
299 mSublayersOnMainThread
.RemoveElementsBy([&](const auto& layer
) {
300 if (!mSublayers
.Contains(layer
)) {
301 if (layer
->IsOpaque() &&
302 StaticPrefs::widget_wayland_opaque_region_enabled_AtStartup() &&
303 sGdkWaylandWindowAddCallbackSurface
&& gdkWindow
) {
304 sGdkWaylandWindowRemoveCallbackSurface(gdkWindow
, layer
->mWlSurface
);
306 wl_compositor
* compositor
=
307 widget::WaylandDisplayGet()->GetCompositor();
308 wl_region
* region
= wl_compositor_create_region(compositor
);
309 wl_surface_set_opaque_region(layer
->mWlSurface
, region
);
310 wl_region_destroy(region
);
311 wl_surface_commit(layer
->mWlSurface
);
318 for (const RefPtr
<NativeLayerWayland
>& layer
: mSublayers
) {
319 if (!mSublayersOnMainThread
.Contains(layer
)) {
320 if (layer
->IsOpaque() &&
321 StaticPrefs::widget_wayland_opaque_region_enabled_AtStartup() &&
322 sGdkWaylandWindowRemoveCallbackSurface
&& gdkWindow
) {
323 sGdkWaylandWindowAddCallbackSurface(gdkWindow
, layer
->mWlSurface
);
325 wl_compositor
* compositor
=
326 widget::WaylandDisplayGet()->GetCompositor();
327 wl_region
* region
= wl_compositor_create_region(compositor
);
328 wl_region_add(region
, 0, 0, INT32_MAX
, INT32_MAX
);
329 wl_surface_set_opaque_region(layer
->mWlSurface
, region
);
330 wl_region_destroy(region
);
331 wl_surface_commit(layer
->mWlSurface
);
333 if (mCallbackMultiplexHelper
&& mCallbackMultiplexHelper
->IsActive()) {
334 layer
->RequestFrameCallback(mCallbackMultiplexHelper
);
336 mSublayersOnMainThread
.AppendElement(layer
);
340 if (containerSurface
) {
341 wl_surface_commit(containerSurface
);
344 if (!mGdkAfterPaintId
&& gdkWindow
) {
345 GdkFrameClock
* frameClock
= gdk_window_get_frame_clock(gdkWindow
);
347 g_signal_connect_after(frameClock
, "after-paint",
348 G_CALLBACK(sAfterFrameClockAfterPaint
), this);
352 NativeLayerWayland::NativeLayerWayland(
353 const IntSize
& aSize
, bool aIsOpaque
,
354 SurfacePoolHandleWayland
* aSurfacePoolHandle
)
355 : mMutex("NativeLayerWayland"),
356 mSurfacePoolHandle(aSurfacePoolHandle
),
358 mIsOpaque(aIsOpaque
) {
359 MOZ_RELEASE_ASSERT(mSurfacePoolHandle
,
360 "Need a non-null surface pool handle.");
362 widget::nsWaylandDisplay
* waylandDisplay
= widget::WaylandDisplayGet();
363 wl_compositor
* compositor
= waylandDisplay
->GetCompositor();
364 mWlSurface
= wl_compositor_create_surface(compositor
);
366 wl_region
* region
= wl_compositor_create_region(compositor
);
367 wl_surface_set_input_region(mWlSurface
, region
);
368 wl_region_destroy(region
);
370 wp_viewporter
* viewporter
= waylandDisplay
->GetViewporter();
371 mViewport
= wp_viewporter_get_viewport(viewporter
, mWlSurface
);
374 NativeLayerWayland::NativeLayerWayland(bool aIsOpaque
)
375 : mMutex("NativeLayerWayland"),
376 mSurfacePoolHandle(nullptr),
377 mIsOpaque(aIsOpaque
) {
378 MOZ_RELEASE_ASSERT(false); // external image
381 NativeLayerWayland::~NativeLayerWayland() {
382 MutexAutoLock
lock(mMutex
);
384 if (mInProgressBuffer
) {
385 mSurfacePoolHandle
->ReturnBufferToPool(mInProgressBuffer
);
386 mInProgressBuffer
= nullptr;
389 mSurfacePoolHandle
->ReturnBufferToPool(mFrontBuffer
);
390 mFrontBuffer
= nullptr;
392 MozClearPointer(mCallback
, wl_callback_destroy
);
393 MozClearPointer(mViewport
, wp_viewport_destroy
);
394 MozClearPointer(mWlSubsurface
, wl_subsurface_destroy
);
395 MozClearPointer(mWlSurface
, wl_surface_destroy
);
398 void NativeLayerWayland::AttachExternalImage(
399 wr::RenderTextureHost
* aExternalImage
) {
400 MOZ_RELEASE_ASSERT(false);
403 void NativeLayerWayland::SetSurfaceIsFlipped(bool aIsFlipped
) {
404 MutexAutoLock
lock(mMutex
);
406 if (aIsFlipped
!= mSurfaceIsFlipped
) {
407 mSurfaceIsFlipped
= aIsFlipped
;
411 bool NativeLayerWayland::SurfaceIsFlipped() {
412 MutexAutoLock
lock(mMutex
);
414 return mSurfaceIsFlipped
;
417 IntSize
NativeLayerWayland::GetSize() {
418 MutexAutoLock
lock(mMutex
);
422 void NativeLayerWayland::SetPosition(const IntPoint
& aPosition
) {
423 MutexAutoLock
lock(mMutex
);
425 if (aPosition
!= mPosition
) {
426 mPosition
= aPosition
;
430 IntPoint
NativeLayerWayland::GetPosition() {
431 MutexAutoLock
lock(mMutex
);
435 void NativeLayerWayland::SetTransform(const Matrix4x4
& aTransform
) {
436 MutexAutoLock
lock(mMutex
);
437 MOZ_ASSERT(aTransform
.IsRectilinear());
439 if (aTransform
!= mTransform
) {
440 mTransform
= aTransform
;
444 void NativeLayerWayland::SetSamplingFilter(SamplingFilter aSamplingFilter
) {
445 MutexAutoLock
lock(mMutex
);
447 if (aSamplingFilter
!= mSamplingFilter
) {
448 mSamplingFilter
= aSamplingFilter
;
452 Matrix4x4
NativeLayerWayland::GetTransform() {
453 MutexAutoLock
lock(mMutex
);
457 IntRect
NativeLayerWayland::GetRect() {
458 MutexAutoLock
lock(mMutex
);
459 return IntRect(mPosition
, mSize
);
462 bool NativeLayerWayland::IsOpaque() {
463 MutexAutoLock
lock(mMutex
);
467 void NativeLayerWayland::SetClipRect(const Maybe
<IntRect
>& aClipRect
) {
468 MutexAutoLock
lock(mMutex
);
470 if (aClipRect
!= mClipRect
) {
471 mClipRect
= aClipRect
;
475 Maybe
<IntRect
> NativeLayerWayland::ClipRect() {
476 MutexAutoLock
lock(mMutex
);
480 IntRect
NativeLayerWayland::CurrentSurfaceDisplayRect() {
481 MutexAutoLock
lock(mMutex
);
485 RefPtr
<DrawTarget
> NativeLayerWayland::NextSurfaceAsDrawTarget(
486 const IntRect
& aDisplayRect
, const IntRegion
& aUpdateRegion
,
487 BackendType aBackendType
) {
488 MutexAutoLock
lock(mMutex
);
490 mDisplayRect
= IntRect(aDisplayRect
);
491 mDirtyRegion
= IntRegion(aUpdateRegion
);
493 MOZ_ASSERT(!mInProgressBuffer
);
494 if (mFrontBuffer
&& !mFrontBuffer
->IsAttached()) {
495 // the Wayland compositor released the buffer early, we can reuse it
496 mInProgressBuffer
= std::move(mFrontBuffer
);
498 mInProgressBuffer
= mSurfacePoolHandle
->ObtainBufferFromPool(mSize
);
500 HandlePartialUpdate(lock
);
501 mSurfacePoolHandle
->ReturnBufferToPool(mFrontBuffer
);
504 mFrontBuffer
= nullptr;
506 if (!mInProgressBuffer
) {
507 gfxCriticalError() << "Failed to obtain buffer";
508 wr::RenderThread::Get()->HandleWebRenderError(
509 wr::WebRenderError::NEW_SURFACE
);
513 return mInProgressBuffer
->Lock();
516 Maybe
<GLuint
> NativeLayerWayland::NextSurfaceAsFramebuffer(
517 const IntRect
& aDisplayRect
, const IntRegion
& aUpdateRegion
,
519 MutexAutoLock
lock(mMutex
);
521 mDisplayRect
= IntRect(aDisplayRect
);
522 mDirtyRegion
= IntRegion(aUpdateRegion
);
524 MOZ_ASSERT(!mInProgressBuffer
);
525 if (mFrontBuffer
&& !mFrontBuffer
->IsAttached()) {
526 // the Wayland compositor released the buffer early, we can reuse it
527 mInProgressBuffer
= std::move(mFrontBuffer
);
528 mFrontBuffer
= nullptr;
530 mInProgressBuffer
= mSurfacePoolHandle
->ObtainBufferFromPool(mSize
);
533 if (!mInProgressBuffer
) {
534 gfxCriticalError() << "Failed to obtain buffer";
535 wr::RenderThread::Get()->HandleWebRenderError(
536 wr::WebRenderError::NEW_SURFACE
);
540 // get the framebuffer before handling partial damage so we don't accidently
541 // create one without depth buffer
542 Maybe
<GLuint
> fbo
= mSurfacePoolHandle
->GetFramebufferForBuffer(
543 mInProgressBuffer
, aNeedsDepth
);
544 MOZ_RELEASE_ASSERT(fbo
, "GetFramebufferForBuffer failed.");
547 HandlePartialUpdate(lock
);
548 mSurfacePoolHandle
->ReturnBufferToPool(mFrontBuffer
);
549 mFrontBuffer
= nullptr;
555 void NativeLayerWayland::HandlePartialUpdate(
556 const MutexAutoLock
& aProofOfLock
) {
557 IntRegion copyRegion
= IntRegion(mDisplayRect
);
558 copyRegion
.SubOut(mDirtyRegion
);
560 if (!copyRegion
.IsEmpty()) {
561 if (mSurfacePoolHandle
->gl()) {
562 mSurfacePoolHandle
->gl()->MakeCurrent();
563 for (auto iter
= copyRegion
.RectIter(); !iter
.Done(); iter
.Next()) {
564 gfx::IntRect r
= iter
.Get();
565 Maybe
<GLuint
> sourceFB
=
566 mSurfacePoolHandle
->GetFramebufferForBuffer(mFrontBuffer
, false);
567 Maybe
<GLuint
> destFB
= mSurfacePoolHandle
->GetFramebufferForBuffer(
568 mInProgressBuffer
, false);
569 MOZ_RELEASE_ASSERT(sourceFB
&& destFB
);
570 mSurfacePoolHandle
->gl()->BlitHelper()->BlitFramebufferToFramebuffer(
571 sourceFB
.value(), destFB
.value(), r
, r
, LOCAL_GL_NEAREST
);
574 RefPtr
<gfx::DataSourceSurface
> dataSourceSurface
=
575 gfx::CreateDataSourceSurfaceFromData(
576 mSize
, mFrontBuffer
->GetSurfaceFormat(),
577 (const uint8_t*)mFrontBuffer
->GetImageData(),
578 mSize
.width
* BytesPerPixel(mFrontBuffer
->GetSurfaceFormat()));
579 RefPtr
<DrawTarget
> dt
= mInProgressBuffer
->Lock();
581 for (auto iter
= copyRegion
.RectIter(); !iter
.Done(); iter
.Next()) {
582 IntRect r
= iter
.Get();
583 dt
->CopySurface(dataSourceSurface
, r
, IntPoint(r
.x
, r
.y
));
589 void NativeLayerWayland::NotifySurfaceReady() {
590 MOZ_ASSERT(!mFrontBuffer
);
591 MOZ_ASSERT(mInProgressBuffer
);
592 mFrontBuffer
= mInProgressBuffer
;
593 mInProgressBuffer
= nullptr;
596 void NativeLayerWayland::DiscardBackbuffers() {}
598 void NativeLayerWayland::Commit() {
599 MutexAutoLock
lock(mMutex
);
601 if (mDirtyRegion
.IsEmpty() && mHasBufferAttached
) {
602 wl_surface_commit(mWlSurface
);
606 for (auto iter
= mDirtyRegion
.RectIter(); !iter
.Done(); iter
.Next()) {
607 IntRect r
= iter
.Get();
608 wl_surface_damage_buffer(mWlSurface
, r
.x
, r
.y
, r
.width
, r
.height
);
611 MOZ_ASSERT(mFrontBuffer
);
612 mFrontBuffer
->AttachAndCommit(mWlSurface
);
613 mHasBufferAttached
= true;
614 mDirtyRegion
.SetEmpty();
617 void NativeLayerWayland::Unmap() {
618 MutexAutoLock
lock(mMutex
);
620 if (!mHasBufferAttached
) {
624 wl_surface_attach(mWlSurface
, nullptr, 0, 0);
625 wl_surface_commit(mWlSurface
);
626 mHasBufferAttached
= false;
629 void NativeLayerWayland::EnsureParentSurface(wl_surface
* aParentSurface
) {
630 MutexAutoLock
lock(mMutex
);
632 if (aParentSurface
!= mParentWlSurface
) {
633 MozClearPointer(mWlSubsurface
, wl_subsurface_destroy
);
634 mSubsurfacePosition
= IntPoint(0, 0);
636 if (aParentSurface
) {
637 wl_subcompositor
* subcompositor
=
638 widget::WaylandDisplayGet()->GetSubcompositor();
639 mWlSubsurface
= wl_subcompositor_get_subsurface(subcompositor
, mWlSurface
,
642 mParentWlSurface
= aParentSurface
;
646 void NativeLayerWayland::SetBufferTransformFlipped(bool aFlippedX
,
648 MutexAutoLock
lock(mMutex
);
650 if (aFlippedX
== mBufferTransformFlippedX
&&
651 aFlippedY
== mBufferTransformFlippedY
) {
655 mBufferTransformFlippedX
= aFlippedX
;
656 mBufferTransformFlippedY
= aFlippedY
;
658 if (mBufferTransformFlippedY
) {
659 if (mBufferTransformFlippedX
) {
660 wl_surface_set_buffer_transform(mWlSurface
, WL_OUTPUT_TRANSFORM_180
);
662 wl_surface_set_buffer_transform(mWlSurface
,
663 WL_OUTPUT_TRANSFORM_FLIPPED_180
);
666 if (mBufferTransformFlippedX
) {
667 wl_surface_set_buffer_transform(mWlSurface
, WL_OUTPUT_TRANSFORM_FLIPPED
);
669 wl_surface_set_buffer_transform(mWlSurface
, WL_OUTPUT_TRANSFORM_NORMAL
);
674 void NativeLayerWayland::SetSubsurfacePosition(int aX
, int aY
) {
675 MutexAutoLock
lock(mMutex
);
677 if ((aX
== mSubsurfacePosition
.x
&& aY
== mSubsurfacePosition
.y
) ||
682 mSubsurfacePosition
.x
= aX
;
683 mSubsurfacePosition
.y
= aY
;
684 wl_subsurface_set_position(mWlSubsurface
, mSubsurfacePosition
.x
,
685 mSubsurfacePosition
.y
);
688 void NativeLayerWayland::SetViewportSourceRect(const Rect aSourceRect
) {
689 MutexAutoLock
lock(mMutex
);
691 Rect bufferRect
= Rect(0, 0, mSize
.width
, mSize
.height
);
692 Rect sourceRect
= aSourceRect
.Intersect(bufferRect
);
694 if (mViewportSourceRect
== sourceRect
) {
698 mViewportSourceRect
= sourceRect
;
699 wp_viewport_set_source(mViewport
, wl_fixed_from_double(mViewportSourceRect
.x
),
700 wl_fixed_from_double(mViewportSourceRect
.y
),
701 wl_fixed_from_double(mViewportSourceRect
.width
),
702 wl_fixed_from_double(mViewportSourceRect
.height
));
705 void NativeLayerWayland::SetViewportDestinationSize(int aWidth
, int aHeight
) {
706 MutexAutoLock
lock(mMutex
);
708 if (aWidth
== mViewportDestinationSize
.width
&&
709 aHeight
== mViewportDestinationSize
.height
) {
713 mViewportDestinationSize
.width
= aWidth
;
714 mViewportDestinationSize
.height
= aHeight
;
715 wp_viewport_set_destination(mViewport
, mViewportDestinationSize
.width
,
716 mViewportDestinationSize
.height
);
719 void NativeLayerWayland::RequestFrameCallback(
720 const RefPtr
<CallbackMultiplexHelper
>& aMultiplexHelper
) {
721 MutexAutoLock
lock(mMutex
);
722 MOZ_ASSERT(aMultiplexHelper
->IsActive());
724 // Avoid piling up old helpers if this surface does not receive callbacks
726 mCallbackMultiplexHelpers
.RemoveElementsBy(
727 [&](const auto& object
) { return !object
->IsActive(); });
729 mCallbackMultiplexHelpers
.AppendElement(aMultiplexHelper
);
731 mCallback
= wl_surface_frame(mWlSurface
);
732 wl_callback_add_listener(mCallback
, &sFrameListenerNativeLayerWayland
,
734 wl_surface_commit(mWlSurface
);
738 void NativeLayerWayland::FrameCallbackHandler(wl_callback
* aCallback
,
740 MutexAutoLock
lock(mMutex
);
742 MOZ_RELEASE_ASSERT(aCallback
== mCallback
);
743 MozClearPointer(mCallback
, wl_callback_destroy
);
745 for (const RefPtr
<CallbackMultiplexHelper
>& callbackMultiplexHelper
:
746 mCallbackMultiplexHelpers
) {
747 callbackMultiplexHelper
->Callback(aTime
);
749 mCallbackMultiplexHelpers
.Clear();
753 void NativeLayerWayland::FrameCallbackHandler(void* aData
,
754 wl_callback
* aCallback
,
756 auto surface
= reinterpret_cast<NativeLayerWayland
*>(aData
);
757 surface
->FrameCallbackHandler(aCallback
, aTime
);
760 } // namespace mozilla::layers