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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | */ |
20 | struct wl_surface; |
21 | struct wl_subsurface; |
22 | struct wl_egl_window; |
23 | |
24 | class MessageLoop; |
25 | |
26 | namespace mozilla::widget { |
27 | |
28 | class WaylandBuffer; |
29 | |
30 | // WaylandSurface is a wrapper for Wayland rendering target |
31 | // which is wl_surface / wl_subsurface. |
32 | class 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__ */ |