Skip to content

Commit b39b0ef

Browse files
committed
Bug 1998657 [Wayland] Make WaylandSurface ready to draw right after its created r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D271772
1 parent b167b65 commit b39b0ef

File tree

8 files changed

+28
-265
lines changed

8 files changed

+28
-265
lines changed

widget/gtk/MozContainerWayland.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@ static void moz_container_wayland_invalidate(MozContainer* container) {
9999
gdk_window_invalidate_rect(window, nullptr, true);
100100
}
101101

102-
void moz_container_wayland_add_or_fire_initial_draw_callback(
103-
MozContainer* container, const std::function<void(void)>& initial_draw_cb) {
104-
MOZ_WL_SURFACE(container)->AddOrFireReadyToDrawCallback(initial_draw_cb);
105-
}
106-
107102
void moz_container_wayland_unmap(GtkWidget* widget) {
108103
g_return_if_fail(IS_MOZ_CONTAINER(widget));
109104

@@ -143,23 +138,9 @@ gboolean moz_container_wayland_map_event(GtkWidget* widget,
143138
// below.
144139
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
145140

146-
// Set waiting_to_show flag. It means the mozcontainer is cofigured/mapped
147-
// and it's supposed to be visible. *But* it's really visible when we get
148-
// moz_container_wayland_add_or_fire_initial_draw_callback() which means
149-
// wayland compositor makes it live.
150-
MOZ_WL_CONTAINER(widget)->waiting_to_show = true;
151-
MozContainer* container = MOZ_CONTAINER(widget);
152-
MOZ_WL_SURFACE(container)->AddOrFireReadyToDrawCallback(
153-
[container]() -> void {
154-
LOGCONTAINER(
155-
"[%p] moz_container_wayland_add_or_fire_initial_draw_callback set "
156-
"visible",
157-
moz_container_get_nsWindow(container));
158-
moz_container_wayland_clear_waiting_to_show_flag(container);
159-
});
160-
161141
// Don't create wl_subsurface in map_event when it's already created or
162142
// if we create it for the first time.
143+
MozContainer* container = MOZ_CONTAINER(widget);
163144
if (MOZ_WL_SURFACE(container)->IsMapped() ||
164145
MOZ_WL_CONTAINER(container)->before_first_size_alloc) {
165146
return false;
@@ -300,21 +281,7 @@ struct wl_egl_window* moz_container_wayland_get_egl_window(
300281
return MOZ_WL_SURFACE(container)->GetEGLWindow(size);
301282
}
302283

303-
gboolean moz_container_wayland_can_draw(MozContainer* container) {
304-
return MOZ_WL_SURFACE(container)->IsReadyToDraw();
305-
}
306-
307284
double moz_container_wayland_get_scale(MozContainer* container) {
308285
nsWindow* window = moz_container_get_nsWindow(container);
309286
return window ? window->FractionalScaleFactor() : 1.0;
310287
}
311-
312-
bool moz_container_wayland_is_waiting_to_show(MozContainer* container) {
313-
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
314-
return MOZ_WL_CONTAINER(container)->waiting_to_show;
315-
}
316-
317-
void moz_container_wayland_clear_waiting_to_show_flag(MozContainer* container) {
318-
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
319-
MOZ_WL_CONTAINER(container)->waiting_to_show = false;
320-
}

widget/gtk/MozContainerWayland.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ struct MozContainerWayland {
4343

4444
RefPtr<mozilla::widget::WaylandSurface> mSurface;
4545
gboolean before_first_size_alloc = false;
46-
gboolean waiting_to_show = false;
4746
};
4847

4948
void moz_container_wayland_map(GtkWidget*);
@@ -54,13 +53,7 @@ void moz_container_wayland_unmap(GtkWidget*);
5453
struct wl_egl_window* moz_container_wayland_get_egl_window(
5554
MozContainer* container);
5655

57-
void moz_container_wayland_add_or_fire_initial_draw_callback(
58-
MozContainer* container, const std::function<void(void)>& initial_draw_cb);
59-
6056
wl_surface* moz_gtk_widget_get_wl_surface(GtkWidget* aWidget);
61-
gboolean moz_container_wayland_can_draw(MozContainer* container);
6257
double moz_container_wayland_get_scale(MozContainer* container);
63-
bool moz_container_wayland_is_waiting_to_show(MozContainer* container);
64-
void moz_container_wayland_clear_waiting_to_show_flag(MozContainer* container);
6558

6659
#endif /* __MOZ_CONTAINER_WAYLAND_H__ */

widget/gtk/WaylandSurface.cpp

Lines changed: 5 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -117,104 +117,6 @@ WaylandSurface::~WaylandSurface() {
117117
"We can't release WaylandSurface with numap callback!");
118118
}
119119

120-
void WaylandSurface::ReadyToDrawFrameCallbackHandler(
121-
struct wl_callback* callback) {
122-
LOGWAYLAND(
123-
"WaylandSurface::ReadyToDrawFrameCallbackHandler() "
124-
"mReadyToDrawFrameCallback %p mIsReadyToDraw %d initial_draw callback "
125-
"%zd\n",
126-
(void*)mReadyToDrawFrameCallback, (bool)mIsReadyToDraw,
127-
mReadyToDrawCallbacks.size());
128-
129-
// We're supposed to run on main thread only.
130-
AssertIsOnMainThread();
131-
132-
// mReadyToDrawFrameCallback/callback can be nullptr when redering directly
133-
// to GtkWidget and ReadyToDrawFrameCallbackHandler is called by us from main
134-
// thread by WaylandSurface::Map().
135-
MOZ_RELEASE_ASSERT(mReadyToDrawFrameCallback == callback);
136-
137-
std::vector<std::function<void(void)>> cbs;
138-
{
139-
WaylandSurfaceLock lock(this);
140-
MozClearPointer(mReadyToDrawFrameCallback, wl_callback_destroy);
141-
// It's possible that we're already unmapped so quit in such case.
142-
if (!mIsMapped) {
143-
LOGWAYLAND(" WaylandSurface is unmapped, quit.");
144-
if (!mReadyToDrawCallbacks.empty()) {
145-
NS_WARNING("Unmapping WaylandSurface with active draw callback!");
146-
mReadyToDrawCallbacks.clear();
147-
}
148-
return;
149-
}
150-
if (mIsReadyToDraw) {
151-
return;
152-
}
153-
mIsReadyToDraw = true;
154-
cbs = std::move(mReadyToDrawCallbacks);
155-
156-
RequestFrameCallbackLocked(lock);
157-
}
158-
159-
// We can't call the callbacks under lock
160-
#ifdef MOZ_LOGGING
161-
int callbackNum = 0;
162-
#endif
163-
for (auto const& cb : cbs) {
164-
LOGWAYLAND(" initial callback fire [%d]", callbackNum++);
165-
cb();
166-
}
167-
}
168-
169-
static void ReadyToDrawFrameCallbackHandler(void* aWaylandSurface,
170-
struct wl_callback* callback,
171-
uint32_t time) {
172-
auto* waylandSurface = static_cast<WaylandSurface*>(aWaylandSurface);
173-
waylandSurface->ReadyToDrawFrameCallbackHandler(callback);
174-
}
175-
176-
static const struct wl_callback_listener
177-
sWaylandSurfaceReadyToDrawFrameListener = {
178-
::ReadyToDrawFrameCallbackHandler};
179-
180-
void WaylandSurface::AddReadyToDrawCallbackLocked(
181-
const WaylandSurfaceLock& aProofOfLock,
182-
const std::function<void(void)>& aDrawCB) {
183-
LOGVERBOSE("WaylandSurface::AddReadyToDrawCallbackLocked()");
184-
MOZ_DIAGNOSTIC_ASSERT(&aProofOfLock == mSurfaceLock);
185-
mReadyToDrawCallbacks.push_back(aDrawCB);
186-
}
187-
188-
void WaylandSurface::AddOrFireReadyToDrawCallback(
189-
const std::function<void(void)>& aDrawCB) {
190-
{
191-
WaylandSurfaceLock lock(this);
192-
if (!mIsReadyToDraw) {
193-
LOGVERBOSE(
194-
"WaylandSurface::AddOrFireReadyToDrawCallback() callback stored");
195-
mReadyToDrawCallbacks.push_back(aDrawCB);
196-
return;
197-
}
198-
}
199-
200-
LOGWAYLAND("WaylandSurface::AddOrFireReadyToDrawCallback() callback fire");
201-
202-
// We're ready to draw and we have a surface to draw into.
203-
aDrawCB();
204-
}
205-
206-
void WaylandSurface::ClearReadyToDrawCallbacksLocked(
207-
const WaylandSurfaceLock& aProofOfLock) {
208-
MOZ_DIAGNOSTIC_ASSERT(&aProofOfLock == mSurfaceLock);
209-
MozClearPointer(mReadyToDrawFrameCallback, wl_callback_destroy);
210-
mReadyToDrawCallbacks.clear();
211-
}
212-
213-
void WaylandSurface::ClearReadyToDrawCallbacks() {
214-
WaylandSurfaceLock lock(this);
215-
ClearReadyToDrawCallbacksLocked(lock);
216-
}
217-
218120
bool WaylandSurface::HasEmulatedFrameCallbackLocked(
219121
const WaylandSurfaceLock& aProofOfLock) const {
220122
return mFrameCallbackHandler.IsSet() && mFrameCallbackHandler.mEmulated;
@@ -233,7 +135,7 @@ void WaylandSurface::FrameCallbackHandler(struct wl_callback* aCallback,
233135
WaylandSurfaceLock lock(this);
234136

235137
// Don't run emulated callbacks on hidden surfaces
236-
if ((emulatedCallback || aRoutedFromChildSurface) && !mIsReadyToDraw) {
138+
if ((emulatedCallback || aRoutedFromChildSurface) && !mIsVisible) {
237139
return;
238140
}
239141

@@ -259,6 +161,7 @@ void WaylandSurface::FrameCallbackHandler(struct wl_callback* aCallback,
259161
// We're getting regular frame callback from this surface so we must
260162
// have buffer attached.
261163
if (!emulatedCallback && !aRoutedFromChildSurface) {
164+
mIsVisible = true;
262165
mBufferAttached = true;
263166
}
264167

@@ -478,8 +381,7 @@ bool WaylandSurface::MapLocked(const WaylandSurfaceLock& aProofOfLock,
478381
wl_surface* aParentWLSurface,
479382
WaylandSurfaceLock* aParentWaylandSurfaceLock,
480383
gfx::IntPoint aSubsurfacePosition,
481-
bool aSubsurfaceDesync,
482-
bool aUseReadyToDrawCallback) {
384+
bool aSubsurfaceDesync) {
483385
LOGWAYLAND("WaylandSurface::MapLocked()");
484386
MOZ_DIAGNOSTIC_ASSERT(&aProofOfLock == mSurfaceLock);
485387
MOZ_DIAGNOSTIC_ASSERT(!mIsMapped, "Already mapped?");
@@ -519,14 +421,6 @@ bool WaylandSurface::MapLocked(const WaylandSurfaceLock& aProofOfLock,
519421
LOGWAYLAND(" subsurface position [%d,%d]", (int)mSubsurfacePosition.x,
520422
(int)mSubsurfacePosition.y);
521423

522-
if (aUseReadyToDrawCallback) {
523-
mReadyToDrawFrameCallback = wl_surface_frame(mParentSurface);
524-
wl_callback_add_listener(mReadyToDrawFrameCallback,
525-
&sWaylandSurfaceReadyToDrawFrameListener, this);
526-
LOGWAYLAND(" created ready to draw frame callback ID %d\n",
527-
wl_proxy_get_id((struct wl_proxy*)mReadyToDrawFrameCallback));
528-
}
529-
530424
LOGWAYLAND(" register frame callback");
531425
RequestFrameCallbackLocked(aProofOfLock);
532426

@@ -556,8 +450,7 @@ bool WaylandSurface::MapLocked(const WaylandSurfaceLock& aProofOfLock,
556450
gfx::IntPoint aSubsurfacePosition) {
557451
return MapLocked(aProofOfLock, nullptr, aParentWaylandSurfaceLock,
558452
aSubsurfacePosition,
559-
/* aSubsurfaceDesync */ false,
560-
/* aUseReadyToDrawCallback */ false);
453+
/* aSubsurfaceDesync */ false);
561454
}
562455

563456
void WaylandSurface::SetUnmapCallbackLocked(
@@ -609,11 +502,11 @@ void WaylandSurface::UnmapLocked(WaylandSurfaceLock& aSurfaceLock) {
609502
return;
610503
}
611504
mIsMapped = false;
505+
mIsVisible = false;
612506

613507
LOGWAYLAND("WaylandSurface::UnmapLocked()");
614508

615509
RemoveAttachedBufferLocked(aSurfaceLock);
616-
ClearReadyToDrawCallbacksLocked(aSurfaceLock);
617510
ClearFrameCallbackLocked(aSurfaceLock);
618511
ClearScaleLocked(aSurfaceLock);
619512

@@ -633,9 +526,6 @@ void WaylandSurface::UnmapLocked(WaylandSurfaceLock& aSurfaceLock) {
633526
MozClearPointer(mPendingOpaqueRegion, wl_region_destroy);
634527
MozClearPointer(mOpaqueRegionFrameCallback, wl_callback_destroy);
635528

636-
mIsReadyToDraw = false;
637-
mBufferAttached = false;
638-
639529
// Remove references to WaylandBuffers attached to mSurface,
640530
// we don't want to get any buffer release callback when we're unmapped.
641531
ReleaseAllWaylandTransactionsLocked(aSurfaceLock);

widget/gtk/WaylandSurface.h

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ class WaylandSurface final {
4343
void SetLoggingWidget(void* aWidget) { mLoggingWidget = aWidget; }
4444
#endif
4545

46-
void ReadyToDrawFrameCallbackHandler(struct wl_callback* aCallback);
47-
void AddOrFireReadyToDrawCallback(const std::function<void(void)>& aDrawCB);
48-
void ClearReadyToDrawCallbacks();
49-
5046
void FrameCallbackHandler(struct wl_callback* aCallback, uint32_t aTime,
5147
bool aRoutedFromChildSurface);
5248

@@ -78,11 +74,12 @@ class WaylandSurface final {
7874
bool SetEGLWindowSize(LayoutDeviceIntSize aSize);
7975
bool HasEGLWindow() const { return !!mEGLWindow; }
8076

81-
// Read to draw means we got frame callback from parent surface
82-
// where we attached to.
83-
bool IsReadyToDraw() const { return mIsReadyToDraw; }
8477
// Mapped means we have all internals created.
8578
bool IsMapped() const { return mIsMapped; }
79+
80+
// We've got first frame callback so we're really visible now.
81+
bool IsVisible() const { return mIsVisible; }
82+
8683
// Indicate that Wayland surface uses Gdk resources which
8784
// need to be released on main thread by GdkCleanUpLocked().
8885
// It may be called after Unmap() to make sure
@@ -122,10 +119,6 @@ class WaylandSurface final {
122119
bool CreateViewportLocked(const WaylandSurfaceLock& aProofOfLock,
123120
bool aFollowsSizeChanges);
124121

125-
void AddReadyToDrawCallbackLocked(
126-
const WaylandSurfaceLock& aProofOfLock,
127-
const std::function<void(void)>& aInitialDrawCB);
128-
129122
// Attach WaylandBuffer which shows WaylandBuffer content
130123
// on screen.
131124
bool AttachLocked(const WaylandSurfaceLock& aSurfaceLock,
@@ -281,8 +274,7 @@ class WaylandSurface final {
281274
bool MapLocked(const WaylandSurfaceLock& aProofOfLock,
282275
wl_surface* aParentWLSurface,
283276
WaylandSurfaceLock* aParentWaylandSurfaceLock,
284-
gfx::IntPoint aSubsurfacePosition, bool aSubsurfaceDesync,
285-
bool aUseReadyToDrawCallback = true);
277+
gfx::IntPoint aSubsurfacePosition, bool aSubsurfaceDesync);
286278

287279
void SetSizeLocked(const WaylandSurfaceLock& aProofOfLock,
288280
gfx::IntSize aSizeScaled, gfx::IntSize aUnscaledSize);
@@ -304,21 +296,18 @@ class WaylandSurface final {
304296
bool HasEmulatedFrameCallbackLocked(
305297
const WaylandSurfaceLock& aProofOfLock) const;
306298

307-
void ClearReadyToDrawCallbacksLocked(const WaylandSurfaceLock& aProofOfLock);
308-
309299
void ClearScaleLocked(const WaylandSurfaceLock& aProofOfLock);
310300

311301
// Weak ref to owning widget (nsWindow or NativeLayerWayland),
312302
// used for diagnostics/logging only.
313303
void* mLoggingWidget = nullptr;
314304

315-
// WaylandSurface mapped - we have valid wl_surface where we can paint to.
305+
// mIsMapped means we're supposed to be visible
306+
// (or not if Wayland compositor decides so).
316307
mozilla::Atomic<bool, mozilla::Relaxed> mIsMapped{false};
317308

318-
// Wayland shows only subsurfaces of visible parent surfaces.
319-
// mIsReadyToDraw means our parent wl_surface has content so
320-
// this WaylandSurface can be visible on screen and get get frame callback.
321-
mozilla::Atomic<bool, mozilla::Relaxed> mIsReadyToDraw{false};
309+
// mIsVisible means we're really visible as we've got frame callback.
310+
mozilla::Atomic<bool, mozilla::Relaxed> mIsVisible{false};
322311

323312
// We used Gdk functions which needs clean up in main thread.
324313
mozilla::Atomic<bool, mozilla::Relaxed> mIsPendingGdkCleanup{false};
@@ -385,11 +374,6 @@ class WaylandSurface final {
385374
bool mBufferTransformFlippedX = false;
386375
bool mBufferTransformFlippedY = false;
387376

388-
// Frame callback registered to parent surface. When we get it we know
389-
// parent surface is ready and we can paint.
390-
wl_callback* mReadyToDrawFrameCallback = nullptr;
391-
std::vector<std::function<void(void)>> mReadyToDrawCallbacks;
392-
393377
// Frame callbacks of this surface
394378
wl_callback* mFrameCallback = nullptr;
395379

widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,7 @@ WindowSurfaceWaylandMB::WindowSurfaceWaylandMB(
156156
RefPtr<nsWindow> aWindow, GtkCompositorWidget* aCompositorWidget)
157157
: mSurfaceLock("WindowSurfaceWayland lock"),
158158
mWindow(std::move(aWindow)),
159-
mCompositorWidget(aCompositorWidget),
160-
mFrameInProcess(false),
161-
mCallbackRequested(false) {}
159+
mCompositorWidget(aCompositorWidget) {}
162160

163161
bool WindowSurfaceWaylandMB::MaybeUpdateWindowSize() {
164162
// We want to get window size from compositor widget as it matches window
@@ -189,7 +187,6 @@ already_AddRefed<DrawTarget> WindowSurfaceWaylandMB::Lock(
189187
if (mWindow->GetWindowType() == WindowType::Invisible) {
190188
return nullptr;
191189
}
192-
mFrameInProcess = true;
193190

194191
CollectPendingSurfaces(lock);
195192

@@ -281,30 +278,10 @@ void WindowSurfaceWaylandMB::Commit(
281278
// invisible window
282279
return;
283280
}
284-
mFrameInProcess = false;
285281

286282
MozContainer* container = mWindow->GetMozContainer();
287283
WaylandSurface* waylandSurface = MOZ_WL_SURFACE(container);
288284
WaylandSurfaceLock lock(waylandSurface);
289-
if (!waylandSurface->IsMapped()) {
290-
LOGWAYLAND(
291-
"WindowSurfaceWaylandMB::Commit [%p] frame queued: can't lock "
292-
"wl_surface\n",
293-
(void*)mWindow.get());
294-
if (!mCallbackRequested) {
295-
RefPtr<WindowSurfaceWaylandMB> self(this);
296-
waylandSurface->AddReadyToDrawCallbackLocked(
297-
lock, [self, aInvalidRegion]() -> void {
298-
MutexAutoLock lock(self->mSurfaceLock);
299-
if (!self->mFrameInProcess) {
300-
self->Commit(lock, aInvalidRegion);
301-
}
302-
self->mCallbackRequested = false;
303-
});
304-
mCallbackRequested = true;
305-
}
306-
return;
307-
}
308285

309286
waylandSurface->InvalidateRegionLocked(lock,
310287
aInvalidRegion.ToUnknownRegion());

0 commit comments

Comments
 (0)