Bug 1796130 [Wayland] Track and release Vsync frame callbacks so we don't get frame callback after nsWindow::Destroy() r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D160364
This commit is contained in:
stransky 2022-11-08 15:26:25 +00:00
parent ca6356c35d
commit 35f7c05de1
2 changed files with 24 additions and 13 deletions

View File

@ -38,19 +38,18 @@ namespace mozilla {
static void WaylandVsyncSourceCallbackHandler(void* aData,
struct wl_callback* aCallback,
uint32_t aTime) {
WaylandVsyncSource* context = (WaylandVsyncSource*)aData;
wl_callback_destroy(aCallback);
context->FrameCallback(aTime);
}
static void WaylandVsyncSourceCallbackHandler(void* aData, uint32_t aTime) {
WaylandVsyncSource* context = (WaylandVsyncSource*)aData;
context->FrameCallback(aTime);
RefPtr<WaylandVsyncSource> context(static_cast<WaylandVsyncSource*>(aData));
context->FrameCallback(aCallback, aTime);
}
static const struct wl_callback_listener WaylandVsyncSourceCallbackListener = {
WaylandVsyncSourceCallbackHandler};
static void NativeLayerRootWaylandVsyncCallback(void* aData, uint32_t aTime) {
RefPtr<WaylandVsyncSource> context(static_cast<WaylandVsyncSource*>(aData));
context->FrameCallback(nullptr, aTime);
}
static float GetFPS(TimeDuration aVsyncRate) {
return 1000.0 / aVsyncRate.ToMilliseconds();
}
@ -207,7 +206,7 @@ void WaylandVsyncSource::SetupFrameCallback(const MutexAutoLock& aProofOfLock) {
if (mNativeLayerRoot) {
LOG(" use mNativeLayerRoot");
mNativeLayerRoot->RequestFrameCallback(&WaylandVsyncSourceCallbackHandler,
mNativeLayerRoot->RequestFrameCallback(&NativeLayerRootWaylandVsyncCallback,
this);
} else {
MozContainerSurfaceLock lock(mContainer);
@ -222,8 +221,9 @@ void WaylandVsyncSource::SetupFrameCallback(const MutexAutoLock& aProofOfLock) {
}
LOG(" register frame callback");
wl_callback* callback = wl_surface_frame(surface);
wl_callback_add_listener(callback, &WaylandVsyncSourceCallbackListener,
MozClearPointer(mCallback, wl_callback_destroy);
mCallback = wl_surface_frame(surface);
wl_callback_add_listener(mCallback, &WaylandVsyncSourceCallbackListener,
this);
wl_surface_commit(surface);
wl_display_flush(WaylandDisplayGet()->GetDisplay());
@ -286,7 +286,7 @@ void WaylandVsyncSource::IdleCallback() {
}
}
void WaylandVsyncSource::FrameCallback(uint32_t aTime) {
void WaylandVsyncSource::FrameCallback(wl_callback* aCallback, uint32_t aTime) {
LOG("WaylandVsyncSource::FrameCallback");
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
@ -294,11 +294,20 @@ void WaylandVsyncSource::FrameCallback(uint32_t aTime) {
// This might enable vsync.
RefPtr window = mWindow;
window->NotifyOcclusionState(OcclusionState::VISIBLE);
// NotifyOcclusionState can destroy us.
if (window->IsDestroyed()) {
return;
}
}
MutexAutoLock lock(mMutex);
mCallbackRequested = false;
if (aCallback) {
MOZ_RELEASE_ASSERT(aCallback == mCallback);
MozClearPointer(mCallback, wl_callback_destroy);
}
if (!mVsyncEnabled || !mMonitorEnabled) {
// We are unwanted by either our creator or our consumer, so we just stop
// here without setting up a new frame callback.
@ -404,6 +413,7 @@ void WaylandVsyncSource::Shutdown() {
mVsyncEnabled = false;
mCallbackRequested = false;
MozClearHandleID(mIdleTimerID, g_source_remove);
MozClearPointer(mCallback, wl_callback_destroy);
}
} // namespace mozilla

View File

@ -55,7 +55,7 @@ class WaylandVsyncSource final : public gfx::VsyncSource {
void EnableMonitor();
void DisableMonitor();
void FrameCallback(uint32_t aTime);
void FrameCallback(wl_callback* aCallback, uint32_t aTime);
void IdleCallback();
TimeDuration GetVsyncRate() override;
@ -87,6 +87,7 @@ class WaylandVsyncSource final : public gfx::VsyncSource {
TimeDuration mVsyncRate MOZ_GUARDED_BY(mMutex);
TimeStamp mLastVsyncTimeStamp MOZ_GUARDED_BY(mMutex);
guint mIdleTimerID MOZ_GUARDED_BY(mMutex) = 0;
wl_callback* mCallback MOZ_GUARDED_BY(mMutex) = nullptr;
nsWindow* const mWindow; // Main thread only, except for logging.
const guint mIdleTimeout;