Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/widget/WaylandSurface.h
Warning:line 32, column 7
Excessive padding in 'class mozilla::widget::WaylandSurface' (53 padding bytes, where 5 is optimal). Optimal fields order: mRefCnt, mLoggingWidget, mGdkWindow, mParentSurface, mParent, mSurface, mSubsurface, mEGLWindow, mViewport, mReadyToDrawFrameCallback, mFrameCallback, mSurfaceLock, mGdkAfterPaintId, mScreenScale, mFractionalScaleListener, mFormats, mColorSurface, mImageDescription, mReadyToDrawCallbacks, mGdkCommitCallback, mUnmapCallback, mFrameCallbackStateHandler, mFractionalScaleCallback, mDMABufFormatRefreshCallback, mAttachedBuffers, mFrameCallbackHandler, mMutex, mIsMapped, mIsReadyToDraw, mIsPendingGdkCleanup, mBufferAttached, mIsOpaqueSurfaceHandlerSet, mEmulatedFrameCallbackTimerID, mScaleType, mSizeScaled, mSubsurfacePosition, mViewportDestinationSize, mViewportSourceRect, mSurfaceNeedsCommit, mViewportFollowsSizeChanges, mBufferTransformFlippedX, mBufferTransformFlippedY, mFrameCallbackEnabled, mUseDMABufFormats, mHDRSet, consider reordering the fields or adding explicit padding members

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name DocAccessibleWrap.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/accessible/atk -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/accessible/atk -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/accessible/atk -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/accessible/atk -I /root/firefox-clang/accessible/base -I /root/firefox-clang/accessible/generic -I /root/firefox-clang/accessible/html -I /root/firefox-clang/accessible/ipc -I /root/firefox-clang/accessible/xpcom -I /root/firefox-clang/accessible/xul -I /root/firefox-clang/layout/generic -I /root/firefox-clang/other-licenses/atk-1.0 -I /root/firefox-clang/widget -I /root/firefox-clang/widget/gtk -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-error=unused-function -Wno-unused-local-typedefs -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c++ /root/firefox-clang/accessible/atk/DocAccessibleWrap.cpp
1/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4/* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8#ifndef __MOZ_WAYLAND_SURFACE_H__
9#define __MOZ_WAYLAND_SURFACE_H__
10
11#include "nsWaylandDisplay.h"
12#include "mozilla/Mutex.h"
13#include "mozilla/Atomics.h"
14#include "WaylandSurfaceLock.h"
15#include "mozilla/GRefPtr.h"
16
17/* Workaround for bug at wayland-util.h,
18 * present in wayland-devel < 1.12
19 */
20struct wl_surface;
21struct wl_subsurface;
22struct wl_egl_window;
23
24class MessageLoop;
25
26namespace mozilla::widget {
27
28class WaylandBuffer;
29
30// WaylandSurface is a wrapper for Wayland rendering target
31// which is wl_surface / wl_subsurface.
32class WaylandSurface final {
Excessive padding in 'class mozilla::widget::WaylandSurface' (53 padding bytes, where 5 is optimal). Optimal fields order: mRefCnt, mLoggingWidget, mGdkWindow, mParentSurface, mParent, mSurface, mSubsurface, mEGLWindow, mViewport, mReadyToDrawFrameCallback, mFrameCallback, mSurfaceLock, mGdkAfterPaintId, mScreenScale, mFractionalScaleListener, mFormats, mColorSurface, mImageDescription, mReadyToDrawCallbacks, mGdkCommitCallback, mUnmapCallback, mFrameCallbackStateHandler, mFractionalScaleCallback, mDMABufFormatRefreshCallback, mAttachedBuffers, mFrameCallbackHandler, mMutex, mIsMapped, mIsReadyToDraw, mIsPendingGdkCleanup, mBufferAttached, mIsOpaqueSurfaceHandlerSet, mEmulatedFrameCallbackTimerID, mScaleType, mSizeScaled, mSubsurfacePosition, mViewportDestinationSize, mViewportSourceRect, mSurfaceNeedsCommit, mViewportFollowsSizeChanges, mBufferTransformFlippedX, mBufferTransformFlippedY, mFrameCallbackEnabled, mUseDMABufFormats, mHDRSet, consider reordering the fields or adding explicit padding members
33 friend WaylandSurfaceLock;
34
35 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WaylandSurface)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<WaylandSurface>, "Reference-counted class "
"WaylandSurface" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/widget/WaylandSurface.h"
, 35); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 35
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("WaylandSurface"), (uint32_t)(sizeof(*this))); return (nsrefcnt
)count; } MozExternalRefCountType Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/widget/WaylandSurface.h"
, 35); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 35)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("WaylandSurface")); if (count == 0) { delete (this);
return 0; } return count; } using HasThreadSafeRefCnt = std::
true_type; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt
; public:
;
36
37 WaylandSurface(RefPtr<WaylandSurface> aParent, gfx::IntSize aSize);
38
39#ifdef MOZ_LOGGING1
40 nsAutoCString GetDebugTag() const;
41 void* GetLoggingWidget() const { return mLoggingWidget; };
42 void SetLoggingWidget(void* aWidget) { mLoggingWidget = aWidget; }
43#endif
44
45 void ReadyToDrawFrameCallbackHandler(struct wl_callback* aCallback);
46 void AddOrFireReadyToDrawCallback(const std::function<void(void)>& aDrawCB);
47 void ClearReadyToDrawCallbacks();
48
49 void FrameCallbackHandler(struct wl_callback* aCallback, uint32_t aTime,
50 bool aRoutedFromChildSurface);
51
52 // Run frame callback repeatedly. Callback is removed on Unmap.
53 // If aEmulateFrameCallback is set to true and WaylandSurface is mapped and
54 // ready to draw and we don't have buffer attached yet,
55 // fire aFrameCallbackHandler without frame callback from
56 // compositor in sFrameCheckTimeoutMs.
57 void SetFrameCallbackLocked(
58 const WaylandSurfaceLock& aProofOfLock,
59 const std::function<void(wl_callback*, uint32_t)>& aFrameCallbackHandler,
60 bool aEmulateFrameCallback = false);
61
62 // Enable/Disable any frame callback emission (includes emulated ones).
63 void SetFrameCallbackStateLocked(const WaylandSurfaceLock& aProofOfLock,
64 bool aEnabled);
65 void SetFrameCallbackStateHandlerLocked(
66 const WaylandSurfaceLock& aProofOfLock,
67 const std::function<void(bool)>& aFrameCallbackStateHandler);
68
69 // Create and resize EGL window.
70 // GetEGLWindow() takes unscaled window size as we derive size from GdkWindow.
71 // It's scaled internally by WaylandSurface fractional scale.
72 wl_egl_window* GetEGLWindow(nsIntSize aUnscaledSize);
73 // SetEGLWindowSize() takes scaled size - it's called from rendering code
74 // which uses scaled sizes.
75 bool SetEGLWindowSize(nsIntSize aScaledSize);
76 bool HasEGLWindow() const { return !!mEGLWindow; }
77
78 // Read to draw means we got frame callback from parent surface
79 // where we attached to.
80 bool IsReadyToDraw() const { return mIsReadyToDraw; }
81 // Mapped means we have all internals created.
82 bool IsMapped() const { return mIsMapped; }
83 // Indicate that Wayland surface uses Gdk resources which
84 // need to be released on main thread by GdkCleanUpLocked().
85 // It may be called after Unmap() to make sure
86 // Gtk resources are not allocated again.
87 bool IsPendingGdkCleanup() const { return mIsPendingGdkCleanup; }
88
89 bool IsOpaqueSurfaceHandlerSet() const { return mIsOpaqueSurfaceHandlerSet; }
90
91 bool HasBufferAttached() const { return mBufferAttached; }
92
93 // Mapped as direct surface of MozContainer
94 bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
95 wl_surface* aParentWLSurface,
96 gfx::IntPoint aSubsurfacePosition);
97 // Mapped as child of WaylandSurface (used by layers)
98 bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
99 WaylandSurfaceLock* aParentWaylandSurfaceLock,
100 gfx::IntPoint aSubsurfacePosition);
101 // Unmap surface which hides it
102 void UnmapLocked(WaylandSurfaceLock& aSurfaceLock);
103
104 // Clean up Gdk resources, on main thread only
105 void GdkCleanUpLocked(const WaylandSurfaceLock& aProofOfLock);
106
107 // Allow to register and run unmap callback.
108 // Unmap callback needs to be called *before* UnmapLocked() call
109 // on main thread.
110 void SetUnmapCallbackLocked(const WaylandSurfaceLock& aProofOfLock,
111 const std::function<void(void)>& aUnmapCB);
112 void ClearUnmapCallbackLocked(const WaylandSurfaceLock& aProofOfLock);
113
114 void RunUnmapCallback();
115
116 // Create Viewport to manage surface transformations.
117 // aFollowsSizeChanges if set, Viewport destination size
118 // is updated according to buffer size.
119 bool CreateViewportLocked(const WaylandSurfaceLock& aProofOfLock,
120 bool aFollowsSizeChanges);
121
122 void AddReadyToDrawCallbackLocked(
123 const WaylandSurfaceLock& aProofOfLock,
124 const std::function<void(void)>& aInitialDrawCB);
125
126 // Attach WaylandBuffer which shows WaylandBuffer content
127 // on screen.
128 bool AttachLocked(const WaylandSurfaceLock& aSurfaceLock,
129 RefPtr<WaylandBuffer> aWaylandBuffer);
130
131 // If there's any WaylandBuffer recently attached, detach it.
132 // It makes the WaylandSurface invisible and it doesn't have any
133 // content.
134 void RemoveAttachedBufferLocked(const WaylandSurfaceLock& aProofOfLock);
135
136 // Called from Wayland compostor async handler when wl_buffer is
137 // detached or deleted.
138 void BufferFreeCallbackHandler(uintptr_t aWlBufferID, bool aWlBufferDelete);
139
140 // CommitLocked() is needed to call after some of *Locked() method
141 // to submit the action to Wayland compositor by wl_surface_commit().
142
143 // It's possible to stack more *Locked() methods
144 // together and do commit after the last one to do the changes in atomic way.
145
146 // Need of commit is tracked by mSurfaceNeedsCommit flag and
147 // if it's set, CommitLocked() is called when WaylandSurfaceLock is destroyed
148 // and WaylandSurface is unlocked.
149 void CommitLocked(const WaylandSurfaceLock& aProofOfLock,
150 bool aForceCommit = false, bool aForceDisplayFlush = false);
151
152 void EnableDMABufFormatsLocked(
153 const WaylandSurfaceLock& aProofOfLock,
154 const std::function<void(DMABufFormats*)>& aFormatRefreshCB);
155 void DisableDMABufFormatsLocked(const WaylandSurfaceLock& aProofOfLock);
156
157 // Place this WaylandSurface above aLowerSurface
158 void PlaceAboveLocked(const WaylandSurfaceLock& aProofOfLock,
159 WaylandSurfaceLock& aLowerSurfaceLock);
160 void MoveLocked(const WaylandSurfaceLock& aProofOfLock,
161 gfx::IntPoint aPosition);
162 void SetViewPortSourceRectLocked(const WaylandSurfaceLock& aProofOfLock,
163 gfx::Rect aRect);
164 void SetViewPortDestLocked(const WaylandSurfaceLock& aProofOfLock,
165 gfx::IntSize aDestSize);
166 void SetTransformFlippedLocked(const WaylandSurfaceLock& aProofOfLock,
167 bool aFlippedX, bool aFlippedY);
168
169 void SetOpaqueRegion(const gfx::IntRegion& aRegion);
170 void SetOpaqueRegionLocked(const WaylandSurfaceLock& aProofOfLock,
171 const gfx::IntRegion& aRegion);
172 void SetOpaqueLocked(const WaylandSurfaceLock& aProofOfLock);
173 void ClearOpaqueRegionLocked(const WaylandSurfaceLock& aProofOfLock);
174
175 bool DisableUserInputLocked(const WaylandSurfaceLock& aProofOfLock);
176 void InvalidateRegionLocked(const WaylandSurfaceLock& aProofOfLock,
177 const gfx::IntRegion& aInvalidRegion);
178 void InvalidateLocked(const WaylandSurfaceLock& aProofOfLock);
179
180 bool EnableFractionalScaleLocked(
181 const WaylandSurfaceLock& aProofOfLock,
182 std::function<void(void)> aFractionalScaleCallback, bool aManageViewport);
183 bool EnableCeiledScaleLocked(const WaylandSurfaceLock& aProofOfLock);
184
185 bool IsFractionalScaleLocked(const WaylandSurfaceLock& aProofOfLock) const {
186 return mScaleType == ScaleType::Disabled;
187 }
188 bool IsCeiledScaleLocked(const WaylandSurfaceLock& aProofOfLock) const {
189 return mScaleType == ScaleType::Ceiled;
190 }
191 bool IsScaleEnabledLocked(const WaylandSurfaceLock& aProofOfLock) const {
192 return mScaleType != ScaleType::Disabled;
193 }
194
195 // Returns scale as float point number. If WaylandSurface is not mapped,
196 // return fractional scale of parent surface.
197 // Returns sNoScale is we can't get it.
198 static constexpr const double sNoScale = -1;
199 double GetScale();
200
201 // The same as GetScale() but returns monitor scale if window scale is
202 // missing.
203 double GetScaleSafe();
204
205 // Called when screen ceiled scale changed or set initial scale before we map
206 // and paint the surface.
207 void SetCeiledScaleLocked(const WaylandSurfaceLock& aProofOfLock,
208 int aScreenCeiledScale);
209
210 // Called by wayland compositor when fractional scale is changed.
211 static void FractionalScaleHandler(void* data,
212 struct wp_fractional_scale_v1* info,
213 uint32_t wire_scale);
214
215 static void AfterPaintHandler(GdkFrameClock* aClock, void* aData);
216
217 // See https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3111 why we use it.
218 // If child surface covers whole area of parent surface and it's opaque,
219 // parent surface will not get any events (frame callbacks) from compositor
220 // as it's considered as invisible.
221 //
222 // Firefox uses the parent wl_surface (owned by GdkWindow) to get input
223 // events. Without gdk_wayland_window_add_frame_callback_surface() call,
224 // Gdk is not getting any events from compostor and we're frozen.
225 //
226 // So gdk_wayland_window_add_frame_callback_surface() registers wl_surface
227 // owned by WaylandSurface to GtkWindow and requests frame callback
228 // for it. Such frame callback is then routed to GdkWindow and it's used
229 // to fire events like native GdkWindow ones.
230 //
231 // To make sure WaylandSurface's wl_surface frame callback is generated,
232 // we need to commit the wl_surface regularly as Gdk registers frame callback
233 // for it at on_frame_clock_after_paint() event of GdkWindow.
234 bool AddOpaqueSurfaceHandlerLocked(const WaylandSurfaceLock& aProofOfLock,
235 GdkWindow* aGdkWindow,
236 bool aRegisterCommitHandler);
237 bool RemoveOpaqueSurfaceHandlerLocked(const WaylandSurfaceLock& aProofOfLock);
238
239 // Additional callback to call from on_frame_clock_after_paint()
240 // and before this wl_surface is commited.
241 // It can be used to update subsurfaces from main thread.
242 void SetGdkCommitCallbackLocked(
243 const WaylandSurfaceLock& aProofOfLock,
244 const std::function<void(void)>& aGdkCommitCB);
245 void ClearGdkCommitCallbackLocked(const WaylandSurfaceLock& aProofOfLock);
246
247 RefPtr<DMABufFormats> GetDMABufFormats() const { return mFormats; }
248
249 GdkWindow* GetGdkWindow() const;
250
251 static bool IsOpaqueRegionEnabled();
252
253 void SetParentLocked(const WaylandSurfaceLock& aProofOfLock,
254 RefPtr<WaylandSurface> aParent);
255
256 bool EnableColorManagementLocked(const WaylandSurfaceLock& aProofOfLock);
257
258 static void ImageDescriptionFailed(
259 void* aData, struct wp_image_description_v1* aImageDescription,
260 uint32_t aCause, const char* aMsg);
261 static void ImageDescriptionReady(
262 void* aData, struct wp_image_description_v1* aImageDescription,
263 uint32_t aIdentity);
264
265 void AssertCurrentThreadOwnsMutex();
266
267 private:
268 ~WaylandSurface();
269
270 bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
271 wl_surface* aParentWLSurface,
272 WaylandSurfaceLock* aParentWaylandSurfaceLock,
273 gfx::IntPoint aSubsurfacePosition, bool aSubsurfaceDesync,
274 bool aUseReadyToDrawCallback = true);
275
276 void SetSizeLocked(const WaylandSurfaceLock& aProofOfLock,
277 gfx::IntSize aSizeScaled, gfx::IntSize aUnscaledSize);
278
279 wl_surface* Lock(WaylandSurfaceLock* aWaylandSurfaceLock);
280 void Unlock(struct wl_surface** aSurface,
281 WaylandSurfaceLock* aWaylandSurfaceLock);
282 void Commit(WaylandSurfaceLock* aProofOfLock, bool aForceCommit,
283 bool aForceDisplayFlush);
284
285 // Force release/detele all buffers. Some of them may be attached to
286 // compostor and may get wl_buffer::release callback so we need to sync
287 // delete with wayland compostor.
288 void ReleaseAllWaylandBuffersLocked(WaylandSurfaceLock& aSurfaceLock);
289
290 void RequestFrameCallbackLocked(const WaylandSurfaceLock& aProofOfLock);
291 void ClearFrameCallbackLocked(const WaylandSurfaceLock& aProofOfLock);
292 bool HasEmulatedFrameCallbackLocked(
293 const WaylandSurfaceLock& aProofOfLock) const;
294
295 void ClearReadyToDrawCallbacksLocked(const WaylandSurfaceLock& aProofOfLock);
296
297 void ClearScaleLocked(const WaylandSurfaceLock& aProofOfLock);
298
299 // Weak ref to owning widget (nsWindow or NativeLayerWayland),
300 // used for diagnostics/logging only.
301 void* mLoggingWidget = nullptr;
302
303 // WaylandSurface mapped - we have valid wl_surface where we can paint to.
304 mozilla::Atomic<bool, mozilla::Relaxed> mIsMapped{false};
305
306 // Wayland shows only subsurfaces of visible parent surfaces.
307 // mIsReadyToDraw means our parent wl_surface has content so
308 // this WaylandSurface can be visible on screen and get get frame callback.
309 mozilla::Atomic<bool, mozilla::Relaxed> mIsReadyToDraw{false};
310
311 // We used Gdk functions which needs clean up in main thread.
312 mozilla::Atomic<bool, mozilla::Relaxed> mIsPendingGdkCleanup{false};
313
314 std::function<void(void)> mGdkCommitCallback;
315 std::function<void(void)> mUnmapCallback;
316
317 // Scaled surface size, ceiled or fractional.
318 // This reflects real surface size which we paint.
319 gfx::IntSize mSizeScaled;
320
321 // Parent GdkWindow where we paint to, directly or via subsurface.
322 RefPtr<GdkWindow> mGdkWindow;
323
324 // Parent wl_surface owned by mGdkWindow. It's used when we're attached
325 // directly to MozContainer.
326 wl_surface* mParentSurface = nullptr;
327
328 // Parent WaylandSurface.
329 //
330 // Layer rendering (compositor) uses mSurface directly attached to
331 // wl_surface owned by mParent.
332 //
333 // For non-compositing rendering (old) mParent is WaylandSurface
334 // owned by parent nsWindow.
335 RefPtr<WaylandSurface> mParent;
336
337 // wl_surface setup/states
338 wl_surface* mSurface = nullptr;
339 bool mSurfaceNeedsCommit = false;
340 wl_subsurface* mSubsurface = nullptr;
341 gfx::IntPoint mSubsurfacePosition{-1, -1};
342
343 // Wayland buffers recently attached to this surface or held by
344 // Wayland compositor.
345 // There may be more than one buffer attached, for instance if
346 // previous buffer is hold by compositor. We need to keep
347 // there buffers live until compositor notify us that we
348 // can release them.
349 AutoTArray<RefPtr<WaylandBuffer>, 3> mAttachedBuffers;
350
351 // Indicates mSurface has buffer attached so we can attach subsurface
352 // to it and expect to get frame callbacks from Wayland compositor.
353 // We set it at AttachLocked() or when we get first frame callback
354 // (when EGL is used).
355 mozilla::Atomic<bool, mozilla::Relaxed> mBufferAttached{false};
356
357 mozilla::Atomic<wl_egl_window*, mozilla::Relaxed> mEGLWindow{nullptr};
358
359 bool mViewportFollowsSizeChanges = true;
360 wp_viewport* mViewport = nullptr;
361 gfx::Rect mViewportSourceRect{-1, -1, -1, -1};
362 gfx::IntSize mViewportDestinationSize{-1, -1};
363
364 // Surface flip state on X/Y asix
365 bool mBufferTransformFlippedX = false;
366 bool mBufferTransformFlippedY = false;
367
368 // Frame callback registered to parent surface. When we get it we know
369 // parent surface is ready and we can paint.
370 wl_callback* mReadyToDrawFrameCallback = nullptr;
371 std::vector<std::function<void(void)>> mReadyToDrawCallbacks;
372
373 // Frame callbacks of this surface
374 wl_callback* mFrameCallback = nullptr;
375
376 struct FrameCallback {
377 std::function<void(wl_callback*, uint32_t)> mCb = nullptr;
378 bool mEmulated = false;
379 bool IsSet() const { return !!mCb; }
380 void Clear() { mCb = nullptr; }
381 };
382
383 bool mFrameCallbackEnabled = true;
384 std::function<void(bool)> mFrameCallbackStateHandler = nullptr;
385
386 // Frame callback handler called every frame
387 FrameCallback mFrameCallbackHandler;
388
389 // WaylandSurface is used from Compositor/Rendering/Main threads.
390 mozilla::Mutex mMutex{"WaylandSurface"};
391 WaylandSurfaceLock* mSurfaceLock = nullptr;
392
393 // We may mark part of mSurface as opaque (non-transparent) if it's supported
394 // by Gtk which allows compositor to skip painting of covered parts.
395 mozilla::Atomic<bool, mozilla::Relaxed> mIsOpaqueSurfaceHandlerSet{false};
396 gulong mGdkAfterPaintId = 0;
397 static bool sIsOpaqueRegionEnabled;
398 static void (*sGdkWaylandWindowAddCallbackSurface)(GdkWindow*,
399 struct wl_surface*);
400 static void (*sGdkWaylandWindowRemoveCallbackSurface)(GdkWindow*,
401 struct wl_surface*);
402 guint mEmulatedFrameCallbackTimerID = 0;
403 constexpr static int sEmulatedFrameCallbackTimeoutMs = (int)(1000.0 / 60.0);
404
405 // We use two scale systems in Firefox/Wayland. Ceiled (integer) scale and
406 // fractional scale. Ceiled scale is easy to implement but comes with
407 // rendering overhead while fractional rendering paints buffers with exact
408 // scale.
409 //
410 // Fractional scale is used as rendering optimization.
411 // For instance if 225% scale is used, ceiled scale is 3
412 // and fractional 2.20.
413 //
414 // If we paint content with ceiled scale 3 and desktop uses scale 225%,
415 // Wayland compositor downscales buffer to 2.20 on rendering
416 // but we paint more pixels than neccessary (so we use name ceiled).
417 //
418 // Scale is used by wp_viewport. If a surface has a surface-local size
419 // of 100 px by 50 px and wishes to submit buffers with a scale of 1.5,
420 // then a buffer of 150px by 75 px should be used and the wp_viewport
421 // destination rectangle should be 100 px by 50 px.
422 // The wl_surface buffer scale should remain set to 1.
423 //
424 // For scale 2 (200%) we use surface size 200 x 100 px and set
425 // viewport size to 100 x 50 px.
426 //
427 // We're getting fractional scale number with a small delay from
428 // wp_fractional_scale_v1 after fist commit to surface.
429 // Meanwhile we can use ceiled scale number instead of fractional one or
430 // get fractional scale from parent window (if there's any).
431 //
432 enum class ScaleType {
433 Disabled,
434 Ceiled,
435 Fractional,
436 };
437
438 ScaleType mScaleType = ScaleType::Disabled;
439
440 // mScreenScale is set from main thread only but read from
441 // different threads.
442 mozilla::Atomic<double, mozilla::Relaxed> mScreenScale{sNoScale};
443
444 wp_fractional_scale_v1* mFractionalScaleListener = nullptr;
445
446 // mFractionalScaleCallback is called from
447 // wp_fractional_scale_v1_add_listener when scale is changed.
448 std::function<void(void)> mFractionalScaleCallback = []() {};
449
450 bool mUseDMABufFormats = false;
451 // Wayland display notifies us when available DRM formats are are changed.
452 // For instance if wl_surface becomes fullscreen we may get DRM formats
453 // for direct scanout.
454 std::function<void(DMABufFormats*)> mDMABufFormatRefreshCallback;
455 RefPtr<DMABufFormats> mFormats;
456
457 // HDR support
458 bool mHDRSet = false;
459 wp_color_management_surface_v1* mColorSurface = nullptr;
460 wp_image_description_v1* mImageDescription = nullptr;
461};
462
463} // namespace mozilla::widget
464
465#endif /* __MOZ_WAYLAND_SURFACE_H__ */