Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/widget/WaylandSurface.h
Warning:line 32, column 7
Excessive padding in 'class mozilla::widget::WaylandSurface' (41 padding bytes, where 1 is optimal). Optimal fields order: mRefCnt, mLoggingWidget, mGdkWindow, mParentSurface, mParent, mSurface, mSubsurface, mEGLWindow, mViewport, mReadyToDrawFrameCallback, mFrameCallback, mColorSurface, mImageDescription, mImageCreatorParams, mSurfaceLock, mGdkAfterPaintId, mScreenScale, mFractionalScaleListener, mReadToDrawCallbacks, mPersistentFrameCallbackHandlers, mOneTimeFrameCallbackHandlers, mGdkCommitCallback, mUnmapCallback, mFractionalScaleCallback, mAttachedBuffers, mMutex, mIsMapped, mIsReadyToDraw, mIsPendingGdkCleanup, mIsOpaqueSurfaceHandlerSet, mEmulatedFrameCallbackTimerID, mScaleType, mSizeScaled, mSubsurfacePosition, mViewportDestinationSize, mViewportSourceRect, mSurfaceNeedsCommit, mBufferAttached, mCommitToParentSurface, mViewportFollowsSizeChanges, mBufferTransformFlippedX, mBufferTransformFlippedY, mFrameCallbackForceCommit, 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=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/accessible/atk -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/accessible/atk -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/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 /var/lib/jenkins/workspace/firefox-scan-build/accessible/atk -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/accessible/atk -I /var/lib/jenkins/workspace/firefox-scan-build/accessible/base -I /var/lib/jenkins/workspace/firefox-scan-build/accessible/generic -I /var/lib/jenkins/workspace/firefox-scan-build/accessible/html -I /var/lib/jenkins/workspace/firefox-scan-build/accessible/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/accessible/xpcom -I /var/lib/jenkins/workspace/firefox-scan-build/accessible/xul -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/other-licenses/atk-1.0 -I /var/lib/jenkins/workspace/firefox-scan-build/widget -I /var/lib/jenkins/workspace/firefox-scan-build/widget/gtk -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/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-20/lib/clang/20/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=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-01-20-090804-167946-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/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' (41 padding bytes, where 1 is optimal). Optimal fields order: mRefCnt, mLoggingWidget, mGdkWindow, mParentSurface, mParent, mSurface, mSubsurface, mEGLWindow, mViewport, mReadyToDrawFrameCallback, mFrameCallback, mColorSurface, mImageDescription, mImageCreatorParams, mSurfaceLock, mGdkAfterPaintId, mScreenScale, mFractionalScaleListener, mReadToDrawCallbacks, mPersistentFrameCallbackHandlers, mOneTimeFrameCallbackHandlers, mGdkCommitCallback, mUnmapCallback, mFractionalScaleCallback, mAttachedBuffers, mMutex, mIsMapped, mIsReadyToDraw, mIsPendingGdkCleanup, mIsOpaqueSurfaceHandlerSet, mEmulatedFrameCallbackTimerID, mScaleType, mSizeScaled, mSubsurfacePosition, mViewportDestinationSize, mViewportSourceRect, mSurfaceNeedsCommit, mBufferAttached, mCommitToParentSurface, mViewportFollowsSizeChanges, mBufferTransformFlippedX, mBufferTransformFlippedY, mFrameCallbackForceCommit, 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/widget/WaylandSurface.h"
, 35); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/widget/WaylandSurface.h"
, 35); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__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 InitialFrameCallbackHandler(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 // Run only once at most.
52 void AddOneTimeFrameCallbackLocked(
53 const WaylandSurfaceLock& aProofOfLock,
54 const std::function<void(wl_callback*, uint32_t)>& aFrameCallbackHandler);
55
56 // Run frame callback repeatedly. Callback is removed on Unmap.
57 // If aEmulateFrameCallback is set to true and WaylandSurface is mapped and
58 // ready to draw and we don't have buffer attached yet,
59 // fire aFrameCallbackHandler without frame callback from
60 // compositor in sFrameCheckTimeoutMs.
61 void AddPersistentFrameCallbackLocked(
62 const WaylandSurfaceLock& aProofOfLock,
63 const std::function<void(wl_callback*, uint32_t)>& aFrameCallbackHandler,
64 bool aEmulateFrameCallback = false);
65
66 // Create and resize EGL window.
67 // GetEGLWindow() takes unscaled window size as we derive size from GdkWindow.
68 // It's scaled internally by WaylandSurface fractional scale.
69 wl_egl_window* GetEGLWindow(nsIntSize aUnscaledSize);
70 // SetEGLWindowSize() takes scaled size - it's called from rendering code
71 // which uses scaled sizes.
72 bool SetEGLWindowSize(nsIntSize aScaledSize);
73 bool HasEGLWindow() const { return !!mEGLWindow; }
74
75 bool DoesCommitToParentSurface() const { return mCommitToParentSurface; }
76
77 // Read to draw means we got frame callback from parent surface
78 // where we attached to.
79 bool IsReadyToDraw() const { return mIsReadyToDraw; }
80 // Mapped means we have all internals created.
81 bool IsMapped() const { return mIsMapped; }
82 // Indicate that Wayland surface uses Gdk resources which
83 // need to be released on main thread by GdkCleanUpLocked().
84 // It may be called after Unmap() to make sure
85 // Gtk resources are not allocated again.
86 bool IsPendingGdkCleanup() const { return mIsPendingGdkCleanup; }
87
88 bool IsOpaqueSurfaceHandlerSet() const { return mIsOpaqueSurfaceHandlerSet; }
89
90 bool HasBufferAttachedLocked(const WaylandSurfaceLock& aProofOfLock) const {
91 return mBufferAttached;
92 }
93
94 // Mapped as direct surface of MozContainer
95 bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
96 wl_surface* aParentWLSurface,
97 gfx::IntPoint aSubsurfacePosition, bool aCommitToParent);
98 // Mapped as child of WaylandSurface (used by layers)
99 bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
100 WaylandSurfaceLock* aParentWaylandSurfaceLock,
101 gfx::IntPoint aSubsurfacePosition);
102 // Unmap surface which hides it
103 void UnmapLocked(const WaylandSurfaceLock& aProofOfLock);
104
105 // Clean up Gdk resources, on main thread only
106 void GdkCleanUpLocked(const WaylandSurfaceLock& aProofOfLock);
107
108 // Allow to register and run unmap callback.
109 // Unmap callback needs to be called *before* UnmapLocked() call
110 // on main thread.
111 void SetUnmapCallbackLocked(const WaylandSurfaceLock& aProofOfLock,
112 const std::function<void(void)>& aUnmapCB);
113 void RunUnmapCallback();
114
115 // Create Viewport to manage surface transformations.
116 // aFollowsSizeChanges if set, Viewport destination size
117 // is updated according to buffer size.
118 bool CreateViewportLocked(const WaylandSurfaceLock& aProofOfLock,
119 bool aFollowsSizeChanges);
120
121 void AddReadyToDrawCallbackLocked(
122 const WaylandSurfaceLock& aProofOfLock,
123 const std::function<void(void)>& aInitialDrawCB);
124
125 // Attach WaylandBuffer which shows WaylandBuffer content
126 // on screen.
127 bool AttachLocked(const WaylandSurfaceLock& aProofOfLock,
128 RefPtr<WaylandBuffer> aWaylandBuffer);
129
130 // Notify WaylandSurface that WaylandBuffer was released by Wayland
131 // compositor.
132 void DetachedByWaylandCompositorLocked(const WaylandSurfaceLock& aProofOfLock,
133 RefPtr<WaylandBuffer> aWaylandBuffer);
134
135 // If there's any WaylandBuffer recently attached, detach it.
136 // It makes the WaylandSurface invisible and it doesn't have any
137 // content.
138 void RemoveAttachedBufferLocked(const WaylandSurfaceLock& aProofOfLock);
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 // Place this WaylandSurface above aLowerSurface
153 void PlaceAboveLocked(const WaylandSurfaceLock& aProofOfLock,
154 WaylandSurfaceLock& aLowerSurfaceLock);
155 void MoveLocked(const WaylandSurfaceLock& aProofOfLock,
156 gfx::IntPoint aPosition);
157 void SetViewPortSourceRectLocked(const WaylandSurfaceLock& aProofOfLock,
158 gfx::Rect aRect);
159 void SetViewPortDestLocked(const WaylandSurfaceLock& aProofOfLock,
160 gfx::IntSize aDestSize);
161 void SetTransformFlippedLocked(const WaylandSurfaceLock& aProofOfLock,
162 bool aFlippedX, bool aFlippedY);
163
164 void SetOpaqueRegion(const gfx::IntRegion& aRegion);
165 void SetOpaqueRegionLocked(const WaylandSurfaceLock& aProofOfLock,
166 const gfx::IntRegion& aRegion);
167 void SetOpaqueLocked(const WaylandSurfaceLock& aProofOfLock);
168 void ClearOpaqueRegionLocked(const WaylandSurfaceLock& aProofOfLock);
169
170 bool DisableUserInputLocked(const WaylandSurfaceLock& aProofOfLock);
171 void InvalidateRegionLocked(const WaylandSurfaceLock& aProofOfLock,
172 const gfx::IntRegion& aInvalidRegion);
173 void InvalidateLocked(const WaylandSurfaceLock& aProofOfLock);
174
175 bool EnableFractionalScaleLocked(
176 const WaylandSurfaceLock& aProofOfLock,
177 std::function<void(void)> aFractionalScaleCallback, bool aManageViewport);
178 bool EnableCeiledScaleLocked(const WaylandSurfaceLock& aProofOfLock);
179
180 bool IsFractionalScaleLocked(const WaylandSurfaceLock& aProofOfLock) const {
181 return mScaleType == ScaleType::Disabled;
182 }
183 bool IsCeiledScaleLocked(const WaylandSurfaceLock& aProofOfLock) const {
184 return mScaleType == ScaleType::Ceiled;
185 }
186 bool IsScaleEnabledLocked(const WaylandSurfaceLock& aProofOfLock) const {
187 return mScaleType != ScaleType::Disabled;
188 }
189
190 // Returns scale as float point number. If WaylandSurface is not mapped,
191 // return fractional scale of parent surface.
192 // Returns sNoScale is we can't get it.
193 static constexpr const double sNoScale = -1;
194 double GetScale();
195
196 // The same as GetScale() but returns monitor scale if window scale is
197 // missing.
198 double GetScaleSafe();
199
200 // Called when screen ceiled scale changed or set initial scale before we map
201 // and paint the surface.
202 void SetCeiledScaleLocked(const WaylandSurfaceLock& aProofOfLock,
203 int aScreenCeiledScale);
204
205 // Called by wayland compositor when fractional scale is changed.
206 static void FractionalScaleHandler(void* data,
207 struct wp_fractional_scale_v1* info,
208 uint32_t wire_scale);
209
210 static void AfterPaintHandler(GdkFrameClock* aClock, void* aData);
211
212 // See https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3111 why we use it.
213 // If child surface covers whole area of parent surface and it's opaque,
214 // parent surface will not get any events (frame callbacks) from compositor
215 // as it's considered as invisible.
216 //
217 // Firefox uses the parent wl_surface (owned by GdkWindow) to get input
218 // events. Without gdk_wayland_window_add_frame_callback_surface() call,
219 // Gdk is not getting any events from compostor and we're frozen.
220 //
221 // So gdk_wayland_window_add_frame_callback_surface() registers wl_surface
222 // owned by WaylandSurface to GtkWindow and requests frame callback
223 // for it. Such frame callback is then routed to GdkWindow and it's used
224 // to fire events like native GdkWindow ones.
225 //
226 // To make sure WaylandSurface's wl_surface frame callback is generated,
227 // we need to commit the wl_surface regularly as Gdk registers frame callback
228 // for it at on_frame_clock_after_paint() event of GdkWindow.
229 bool AddOpaqueSurfaceHandlerLocked(const WaylandSurfaceLock& aProofOfLock,
230 GdkWindow* aGdkWindow,
231 bool aRegisterCommitHandler);
232 bool RemoveOpaqueSurfaceHandlerLocked(const WaylandSurfaceLock& aProofOfLock);
233
234 // Additional callback to call from on_frame_clock_after_paint()
235 // and before this wl_surface is commited.
236 // It can be used to update subsurfaces from main thread.
237 void SetGdkCommitCallbackLocked(
238 const WaylandSurfaceLock& aProofOfLock,
239 const std::function<void(void)>& aGdkCommitCB);
240 void RequestFrameCallbackForceCommitLocked(
241 const WaylandSurfaceLock& aProofOfLock) {
242 mFrameCallbackForceCommit = true;
243 }
244
245 GdkWindow* GetGdkWindow() const;
246
247 static bool IsOpaqueRegionEnabled();
248
249 void SetParentLocked(const WaylandSurfaceLock& aProofOfLock,
250 RefPtr<WaylandSurface> aParent);
251
252 private:
253 ~WaylandSurface();
254
255 bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
256 wl_surface* aParentWLSurface,
257 WaylandSurfaceLock* aParentWaylandSurfaceLock,
258 gfx::IntPoint aSubsurfacePosition, bool aCommitToParent,
259 bool aSubsurfaceDesync, bool aUseReadyToDrawCallback = true);
260
261 void SetSizeLocked(const WaylandSurfaceLock& aProofOfLock,
262 gfx::IntSize aSizeScaled, gfx::IntSize aUnscaledSize);
263
264 wl_surface* Lock(WaylandSurfaceLock* aWaylandSurfaceLock);
265 void Unlock(struct wl_surface** aSurface,
266 WaylandSurfaceLock* aWaylandSurfaceLock);
267 void Commit(WaylandSurfaceLock* aProofOfLock, bool aForceCommit,
268 bool aForceDisplayFlush);
269
270 bool UntrackWaylandBufferLocked(const WaylandSurfaceLock& aProofOfLock,
271 WaylandBuffer* aWaylandBuffer, bool aRemove);
272 void ReleaseAllWaylandBuffersLocked(const WaylandSurfaceLock& aProofOfLock);
273
274 void RequestFrameCallbackLocked(const WaylandSurfaceLock& aProofOfLock,
275 bool aRequestEmulated);
276 void ClearFrameCallbackLocked(const WaylandSurfaceLock& aProofOfLock);
277 bool IsEmulatedFrameCallbackPendingLocked(
278 const WaylandSurfaceLock& aProofOfLock) const;
279
280 void ClearReadyToDrawCallbacksLocked(const WaylandSurfaceLock& aProofOfLock);
281
282 void ClearScaleLocked(const WaylandSurfaceLock& aProofOfLock);
283
284 // Weak ref to owning widget (nsWindow or NativeLayerWayland),
285 // used for diagnostics/logging only.
286 void* mLoggingWidget = nullptr;
287
288 // WaylandSurface mapped - we have valid wl_surface where we can paint to.
289 mozilla::Atomic<bool, mozilla::Relaxed> mIsMapped{false};
290
291 // Wayland shows only subsurfaces of visible parent surfaces.
292 // mIsReadyToDraw means our parent wl_surface has content so
293 // this WaylandSurface can be visible on screen and get get frame callback.
294 mozilla::Atomic<bool, mozilla::Relaxed> mIsReadyToDraw{false};
295
296 // We used Gdk functions which needs clean up in main thread.
297 mozilla::Atomic<bool, mozilla::Relaxed> mIsPendingGdkCleanup{false};
298
299 std::function<void(void)> mGdkCommitCallback;
300 std::function<void(void)> mUnmapCallback;
301
302 // Scaled surface size, ceiled or fractional.
303 // This reflects real surface size which we paint.
304 gfx::IntSize mSizeScaled;
305
306 // Parent GdkWindow where we paint to, directly or via subsurface.
307 RefPtr<GdkWindow> mGdkWindow;
308
309 // Parent wl_surface owned by mGdkWindow. It's used when we're attached
310 // directly to MozContainer.
311 wl_surface* mParentSurface = nullptr;
312
313 // Parent WaylandSurface.
314 //
315 // Layer rendering (compositor) uses mSurface directly attached to
316 // wl_surface owned by mParent.
317 //
318 // For non-compositing rendering (old) mParent is WaylandSurface
319 // owned by parent nsWindow.
320 RefPtr<WaylandSurface> mParent;
321
322 // wl_surface setup/states
323 wl_surface* mSurface = nullptr;
324 bool mSurfaceNeedsCommit = false;
325 wl_subsurface* mSubsurface = nullptr;
326 gfx::IntPoint mSubsurfacePosition{-1, -1};
327
328 // Wayland buffers attached to this surface AND held by Wayland compositor.
329 // There may be more than one buffer attached, for instance if
330 // previous buffer is hold by compositor. We need to keep
331 // there buffers live until compositor notify us that we
332 // can release them.
333 AutoTArray<RefPtr<WaylandBuffer>, 3> mAttachedBuffers;
334
335 // Indicates mSurface has buffer attached so we can attach subsurface
336 // to it and expect to get frame callbacks from Wayland compositor.
337 // We set it at AttachLocked() or when we get first frame callback
338 // (when EGL is used).
339 bool mBufferAttached = false;
340
341 // It's kind of special case here where mSurface equal to mParentSurface
342 // so we directly paint to parent surface without subsurface.
343 // It's used when Wayland compositor doesn't support subsurfaces like D&D
344 // popups. This rendering setup is fragile and we want to use it as less as
345 // possible because we usually don't have control over parent surface.
346 // Calling code needs to make sure mParentSurface is valid and not
347 // used by Gtk/GtkWidget for instance.
348 bool mCommitToParentSurface = false;
349
350 mozilla::Atomic<wl_egl_window*, mozilla::Relaxed> mEGLWindow{nullptr};
351
352 bool mViewportFollowsSizeChanges = true;
353 wp_viewport* mViewport = nullptr;
354 gfx::Rect mViewportSourceRect{-1, -1, -1, -1};
355 gfx::IntSize mViewportDestinationSize{-1, -1};
356
357 // Surface flip state on X/Y asix
358 bool mBufferTransformFlippedX = false;
359 bool mBufferTransformFlippedY = false;
360
361 // Frame callback registered to parent surface. When we get it we know
362 // parent surface is ready and we can paint.
363 wl_callback* mReadyToDrawFrameCallback = nullptr;
364 std::vector<std::function<void(void)>> mReadToDrawCallbacks;
365
366 // Frame callbacks of this surface
367 wl_callback* mFrameCallback = nullptr;
368
369 // Request force commit at end of frame callback handler.
370 // That's useful for synced subsurfaces to perform all changes once.
371 bool mFrameCallbackForceCommit = false;
372
373 struct FrameCallback {
374 std::function<void(wl_callback*, uint32_t)> mCb;
375 bool mEmulated = false;
376 };
377
378 // Frame callback handlers called every frame
379 std::vector<FrameCallback> mPersistentFrameCallbackHandlers;
380 // Frame callback handlers called only once
381 std::vector<FrameCallback> mOneTimeFrameCallbackHandlers;
382
383 xx_color_management_surface_v4* mColorSurface = nullptr;
384 xx_image_description_v4* mImageDescription = nullptr;
385 xx_image_description_creator_params_v4* mImageCreatorParams = nullptr;
386
387 // WaylandSurface is used from Compositor/Rendering/Main threads.
388 mozilla::Mutex mMutex{"WaylandSurface"};
389 WaylandSurfaceLock* mSurfaceLock = nullptr;
390
391 // We may mark part of mSurface as opaque (non-transparent) if it's supported
392 // by Gtk which allows compositor to skip painting of covered parts.
393 mozilla::Atomic<bool, mozilla::Relaxed> mIsOpaqueSurfaceHandlerSet{false};
394 gulong mGdkAfterPaintId = 0;
395 static bool sIsOpaqueRegionEnabled;
396 static void (*sGdkWaylandWindowAddCallbackSurface)(GdkWindow*,
397 struct wl_surface*);
398 static void (*sGdkWaylandWindowRemoveCallbackSurface)(GdkWindow*,
399 struct wl_surface*);
400 guint mEmulatedFrameCallbackTimerID = 0;
401 constexpr static int sEmulatedFrameCallbackTimeoutMs = (int)(1000.0 / 60.0);
402
403 // We use two scale systems in Firefox/Wayland. Ceiled (integer) scale and
404 // fractional scale. Ceiled scale is easy to implement but comes with
405 // rendering overhead while fractional rendering paints buffers with exact
406 // scale.
407 //
408 // Fractional scale is used as rendering optimization.
409 // For instance if 225% scale is used, ceiled scale is 3
410 // and fractional 2.20.
411 //
412 // If we paint content with ceiled scale 3 and desktop uses scale 225%,
413 // Wayland compositor downscales buffer to 2.20 on rendering
414 // but we paint more pixels than neccessary (so we use name ceiled).
415 //
416 // Scale is used by wp_viewport. If a surface has a surface-local size
417 // of 100 px by 50 px and wishes to submit buffers with a scale of 1.5,
418 // then a buffer of 150px by 75 px should be used and the wp_viewport
419 // destination rectangle should be 100 px by 50 px.
420 // The wl_surface buffer scale should remain set to 1.
421 //
422 // For scale 2 (200%) we use surface size 200 x 100 px and set
423 // viewport size to 100 x 50 px.
424 //
425 // We're getting fractional scale number with a small delay from
426 // wp_fractional_scale_v1 after fist commit to surface.
427 // Meanwhile we can use ceiled scale number instead of fractional one or
428 // get fractional scale from parent window (if there's any).
429 //
430 enum class ScaleType {
431 Disabled,
432 Ceiled,
433 Fractional,
434 };
435
436 ScaleType mScaleType = ScaleType::Disabled;
437
438 // mScreenScale is set from main thread only but read from
439 // different threads.
440 mozilla::Atomic<double, mozilla::Relaxed> mScreenScale{sNoScale};
441
442 wp_fractional_scale_v1* mFractionalScaleListener = nullptr;
443
444 // mFractionalScaleCallback is called from
445 // wp_fractional_scale_v1_add_listener when scale is changed.
446 std::function<void(void)> mFractionalScaleCallback = []() {};
447};
448
449} // namespace mozilla::widget
450
451#endif /* __MOZ_WAYLAND_SURFACE_H__ */