diff -up firefox-69.0/widget/gtk/mozwayland/mozwayland.h.mozilla-1580152 firefox-69.0/widget/gtk/mozwayland/mozwayland.h --- firefox-69.0/widget/gtk/mozwayland/mozwayland.h.mozilla-1580152 2019-09-16 11:11:30.081299217 +0200 +++ firefox-69.0/widget/gtk/mozwayland/mozwayland.h 2019-09-16 11:11:30.089299191 +0200 @@ -27,6 +27,9 @@ MOZ_EXPORT struct wl_proxy* wl_proxy_mar struct wl_proxy* proxy, uint32_t opcode, const struct wl_interface* interface, ...); +MOZ_EXPORT void* wl_proxy_create_wrapper(void* proxy); +MOZ_EXPORT void wl_proxy_wrapper_destroy(void* proxy_wrapper); + /* We need implement some missing functions from wayland-client-protocol.h */ #ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM diff -up firefox-69.0/widget/gtk/nsWaylandDisplay.cpp.mozilla-1580152 firefox-69.0/widget/gtk/nsWaylandDisplay.cpp --- firefox-69.0/widget/gtk/nsWaylandDisplay.cpp.mozilla-1580152 2019-09-16 11:11:30.081299217 +0200 +++ firefox-69.0/widget/gtk/nsWaylandDisplay.cpp 2019-09-16 11:11:30.089299191 +0200 @@ -243,6 +243,61 @@ bool nsWaylandDisplay::DispatchEventQueu return true; } +void nsWaylandDisplay::SyncEnd() { + wl_callback_destroy(mSyncCallback); + mSyncCallback = NULL; +} + +static void wayland_sync_callback(void* data, struct wl_callback* callback, + uint32_t time) { + auto display = static_cast(data); + display->SyncEnd(); +} + +static const struct wl_callback_listener sync_callback_listener = { + .done = wayland_sync_callback}; + +void nsWaylandDisplay::SyncBegin() { + WaitForSyncEnd(); + + // Use wl_display_sync() to synchronize wayland events. + // See dri2_wl_swap_buffers_with_damage() from MESA + // or wl_display_roundtrip_queue() from wayland-client. + struct wl_display* displayWrapper = + static_cast(wl_proxy_create_wrapper((void*)mDisplay)); + if (!displayWrapper) { + NS_WARNING("Failed to create wl_proxy wrapper!"); + return; + } + + wl_proxy_set_queue((struct wl_proxy*)displayWrapper, mEventQueue); + mSyncCallback = wl_display_sync(displayWrapper); + wl_proxy_wrapper_destroy((void*)displayWrapper); + + if (!mSyncCallback) { + NS_WARNING("Failed to create wl_display_sync callback!"); + return; + } + + wl_callback_add_listener(mSyncCallback, &sync_callback_listener, this); + wl_display_flush(mDisplay); +} + +void nsWaylandDisplay::WaitForSyncEnd() { + // We're done here + if (!mSyncCallback) { + return; + } + + while (mSyncCallback != NULL) { + if (wl_display_dispatch_queue(mDisplay, mEventQueue) == -1) { + NS_WARNING("wl_display_dispatch_queue failed!"); + SyncEnd(); + return; + } + } +} + bool nsWaylandDisplay::Matches(wl_display* aDisplay) { return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay; } @@ -305,6 +360,7 @@ nsWaylandDisplay::nsWaylandDisplay(wl_di mSubcompositor(nullptr), mSeat(nullptr), mShm(nullptr), + mSyncCallback(nullptr), mPrimarySelectionDeviceManager(nullptr), mRegistry(nullptr), mGbmDevice(nullptr), diff -up firefox-69.0/widget/gtk/nsWaylandDisplay.h.mozilla-1580152 firefox-69.0/widget/gtk/nsWaylandDisplay.h --- firefox-69.0/widget/gtk/nsWaylandDisplay.h.mozilla-1580152 2019-09-16 11:11:30.081299217 +0200 +++ firefox-69.0/widget/gtk/nsWaylandDisplay.h 2019-09-16 11:11:30.089299191 +0200 @@ -41,6 +41,11 @@ class nsWaylandDisplay { virtual ~nsWaylandDisplay(); bool DispatchEventQueue(); + + void SyncBegin(); + void SyncEnd(); + void WaitForSyncEnd(); + bool Matches(wl_display* aDisplay); MessageLoop* GetDispatcherThreadLoop() { return mDispatcherThreadLoop; } @@ -90,6 +95,7 @@ class nsWaylandDisplay { wl_subcompositor* mSubcompositor; wl_seat* mSeat; wl_shm* mShm; + wl_callback* mSyncCallback; gtk_primary_selection_device_manager* mPrimarySelectionDeviceManager; wl_registry* mRegistry; zwp_linux_dmabuf_v1* mDmabuf; diff -up firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1580152 firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp --- firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1580152 2019-09-16 11:11:30.086299200 +0200 +++ firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp 2019-09-16 11:57:35.462193492 +0200 @@ -32,6 +32,9 @@ extern mozilla::LazyLogModule gWidgetWay # define LOGWAYLAND(args) #endif /* MOZ_LOGGING */ +// Maximal compositin timeout it miliseconds +#define COMPOSITING_TIMEOUT 200 + namespace mozilla { namespace widget { @@ -198,6 +201,10 @@ available and gfx.wayland_dmabuf_backend #define BUFFER_BPP 4 gfx::SurfaceFormat WindowBackBuffer::mFormat = gfx::SurfaceFormat::B8G8R8A8; +nsWaylandDisplay* WindowBackBuffer::GetWaylandDisplay() { + return mWindowSurfaceWayland->GetWaylandDisplay(); +} + int WaylandShmPool::CreateTemporaryFile(int aSize) { const char* tmppath = getenv("XDG_RUNTIME_DIR"); MOZ_RELEASE_ASSERT(tmppath, "Missing XDG_RUNTIME_DIR env variable."); @@ -342,10 +349,11 @@ void WindowBackBufferShm::Clear() { memset(mShmPool.GetImageData(), 0, mHeight * mWidth * BUFFER_BPP); } -WindowBackBufferShm::WindowBackBufferShm(nsWaylandDisplay* aWaylandDisplay, - int aWidth, int aHeight) - : WindowBackBuffer(aWaylandDisplay), - mShmPool(aWaylandDisplay, aWidth * aHeight * BUFFER_BPP), +WindowBackBufferShm::WindowBackBufferShm( + WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, int aHeight) + : WindowBackBuffer(aWindowSurfaceWayland), + mShmPool(aWindowSurfaceWayland->GetWaylandDisplay(), + aWidth * aHeight * BUFFER_BPP), mWaylandBuffer(nullptr), mWidth(aWidth), mHeight(aHeight), @@ -387,6 +395,9 @@ void WindowBackBufferShm::Detach(wl_buff aBuffer ? wl_proxy_get_id((struct wl_proxy*)aBuffer) : -1)); mAttached = false; + + // Commit any potential cached drawings from latest Lock()/Commit() cycle. + mWindowSurfaceWayland->CommitWaylandBuffer(); } bool WindowBackBufferShm::SetImageDataFromBuffer( @@ -416,8 +427,8 @@ already_AddRefed Window } WindowBackBufferDMABuf::WindowBackBufferDMABuf( - nsWaylandDisplay* aWaylandDisplay, int aWidth, int aHeight) - : WindowBackBuffer(aWaylandDisplay) { + WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, int aHeight) + : WindowBackBuffer(aWindowSurfaceWayland) { mDMAbufSurface.Create(aWidth, aHeight); LOGWAYLAND( ("WindowBackBufferDMABuf::WindowBackBufferDMABuf [%p] Created DMABuf " @@ -475,6 +486,9 @@ bool WindowBackBufferDMABuf::SetImageDat void WindowBackBufferDMABuf::Detach(wl_buffer* aBuffer) { mDMAbufSurface.WLBufferDetach(); + + // Commit any potential cached drawings from latest Lock()/Commit() cycle. + mWindowSurfaceWayland->CommitWaylandBuffer(); } void WindowBackBufferDMABuf::Clear() { mDMAbufSurface.Clear(); } @@ -496,10 +510,11 @@ WindowSurfaceWayland::WindowSurfaceWayla mWaylandBuffer(nullptr), mFrameCallback(nullptr), mLastCommittedSurface(nullptr), - mDisplayThreadMessageLoop(MessageLoop::current()), mDelayedCommitHandle(nullptr), + mLastCommitTime(0), mDrawToWaylandBufferDirectly(true), - mPendingCommit(false), + mBufferPendingCommit(false), + mBufferCommitAllowed(false), mWholeWindowBufferDamage(false), mBufferNeedsClear(false), mIsMainThread(NS_IsMainThread()), @@ -508,7 +523,7 @@ WindowSurfaceWayland::WindowSurfaceWayla } WindowSurfaceWayland::~WindowSurfaceWayland() { - if (mPendingCommit) { + if (mBufferPendingCommit) { NS_WARNING("Deleted WindowSurfaceWayland with a pending commit!"); } @@ -547,7 +562,7 @@ WindowBackBuffer* WindowSurfaceWayland:: if (UseDMABufBackend()) { static bool sDMABufBufferCreated = false; WindowBackBuffer* buffer = - new WindowBackBufferDMABuf(mWaylandDisplay, aWidth, aHeight); + new WindowBackBufferDMABuf(this, aWidth, aHeight); if (buffer) { sDMABufBufferCreated = true; return buffer; @@ -564,7 +579,7 @@ WindowBackBuffer* WindowSurfaceWayland:: } } - return new WindowBackBufferShm(mWaylandDisplay, aWidth, aHeight); + return new WindowBackBufferShm(this, aWidth, aHeight); } WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw( @@ -675,6 +690,11 @@ already_AddRefed Window (void*)this, (void*)buffer)); if (!buffer) { + if (mLastCommitTime && (g_get_monotonic_time() / 1000) - mLastCommitTime > + COMPOSITING_TIMEOUT) { + NS_WARNING( + "Slow response from Wayland compositor, visual glitches ahead."); + } return nullptr; } @@ -724,10 +744,9 @@ static bool IsPopupFullScreenUpdate(Layo // box is equal to window borders. if (aRegion.GetNumRects() > 2) return false; - gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); - gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); - - return (screenRect.width == lockSize.width && + IntRect lockSize = aRegion.GetBounds().ToUnknownRect(); + return (lockSize.x == 0 && lockSize.y == 0 && + screenRect.width == lockSize.width && screenRect.height == lockSize.height); } @@ -738,8 +757,7 @@ static bool IsPopupFullScreenUpdate(Layo to clip/buffer the drawing and we can return wl_buffer directly for drawing. - mWaylandBuffer is available - that's an ideal situation. - - mWaylandBuffer is locked by compositor - flip buffers and draw. - - if we can't flip buffers - go B) + - mWaylandBuffer is locked by compositor - go B) B) Lock() is requested for part(s) of screen. We need to provide temporary surface to draw into and copy result (clipped) to target wl_surface. @@ -747,14 +765,17 @@ static bool IsPopupFullScreenUpdate(Layo already_AddRefed WindowSurfaceWayland::Lock( const LayoutDeviceIntRegion& aRegion) { MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); - - // Disable all commits from frame callback handler and delayed comit handler - // as we're updated by gecko compositor. - mPendingCommit = false; + + // Wait until all pending events are processed. There may be queued + // wl_buffer release event which releases our wl_buffer for further rendering. + mWaylandDisplay->WaitForSyncEnd(); + + // Disable all commits (from potential frame callback/delayed handlers) + // until next WindowSurfaceWayland::Commit() call. + mBufferCommitAllowed = false; LayoutDeviceIntRect lockedScreenRect = mWindow->GetBounds(); - gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); - gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); + gfx::IntRect lockSize = aRegion.GetBounds().ToUnknownRect(); // Are we asked for entire nsWindow to draw? bool isTransparentPopup = @@ -775,10 +796,10 @@ already_AddRefed Window } LOGWAYLAND( - ("WindowSurfaceWayland::Lock [%p] lockSize [%d x %d] windowSize [%d x " - "%d]\n", - (void*)this, lockSize.width, lockSize.height, lockedScreenRect.width, - lockedScreenRect.height)); + ("WindowSurfaceWayland::Lock [%p] [%d,%d] -> [%d x %d] rects %d " + "windowSize [%d x %d]\n", + (void*)this, lockSize.x, lockSize.y, lockSize.width, lockSize.height, + aRegion.GetNumRects(), lockedScreenRect.width, lockedScreenRect.height)); LOGWAYLAND((" nsWindow = %p\n", mWindow)); LOGWAYLAND((" isPopup = %d\n", mWindow->IsWaylandPopup())); LOGWAYLAND((" isTransparentPopup = %d\n", isTransparentPopup)); @@ -789,7 +810,7 @@ already_AddRefed Window LOGWAYLAND((" mBufferNeedsClear = %d\n", mBufferNeedsClear)); LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage)); -#if DEBUG +#if MOZ_LOGGING if (!(mBufferScreenRect == lockedScreenRect)) { LOGWAYLAND((" screen size changed\n")); } @@ -836,7 +857,7 @@ already_AddRefed Window mDrawToWaylandBufferDirectly = false; LOGWAYLAND((" Indirect drawing.\n")); - return LockImageSurface(lockSize); + return LockImageSurface(gfx::IntSize(lockSize.XMost(), lockSize.YMost())); } void WindowImageSurface::Draw(gfx::SourceSurface* aSurface, @@ -875,34 +896,42 @@ WindowImageSurface::WindowImageSurface( mImageSurface->Format()); } +void WindowSurfaceWayland::CacheImageSurface( + const LayoutDeviceIntRegion& aRegion) { +#ifdef MOZ_LOGGING + gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); + LOGWAYLAND(("WindowSurfaceWayland::CacheImageSurface [%p]\n", (void*)this)); + LOGWAYLAND((" rects num %d\n", aRegion.GetNumRects())); + LOGWAYLAND((" bounds [ %d, %d] -> [%d x %d]\n", bounds.x, bounds.y, + bounds.width, bounds.height)); +#endif + + mDelayedImageCommits.AppendElement( + WindowImageSurface(mImageSurface, aRegion)); + // mImageSurface is owned by mDelayedImageCommits + mImageSurface = nullptr; + + LOGWAYLAND( + (" There's %d cached images\n", int(mDelayedImageCommits.Length()))); +} + void WindowSurfaceWayland::DrawDelayedImageCommits( gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage) { + LOGWAYLAND( + ("WindowSurfaceWayland::DrawDelayedImageCommits [%p]\n", (void*)this)); + for (unsigned int i = 0; i < mDelayedImageCommits.Length(); i++) { mDelayedImageCommits[i].Draw(aDrawTarget, aWaylandBufferDamage); } mDelayedImageCommits.Clear(); } -bool WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer( - const LayoutDeviceIntRegion& aRegion, - LayoutDeviceIntRegion& aWaylandBufferDamage) { - MOZ_ASSERT(!mDrawToWaylandBufferDirectly); - -#ifdef DEBUG - gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); - gfx::Rect rect(bounds); - MOZ_ASSERT(!rect.IsEmpty(), "Empty drawing?"); -#endif - - LOGWAYLAND( - ("WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer [%p] " - "screenSize [%d x %d]\n", - (void*)this, mBufferScreenRect.width, mBufferScreenRect.height)); +bool WindowSurfaceWayland::CommitImageCacheToWaylandBuffer() { + if (!mDelayedImageCommits.Length()) { + return false; + } - mDelayedImageCommits.AppendElement( - WindowImageSurface(mImageSurface, aRegion)); - // mImageSurface is owned by mDelayedImageCommits - mImageSurface = nullptr; + MOZ_ASSERT(!mDrawToWaylandBufferDirectly); RefPtr dt = LockWaylandBuffer( /* aCanSwitchBuffer */ mWholeWindowBufferDamage); @@ -911,10 +940,10 @@ bool WindowSurfaceWayland::CommitImageSu } LOGWAYLAND((" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n", - long(mDelayedImageCommits.Length() + 1))); + long(mDelayedImageCommits.Length()))); // Draw any delayed image commits first - DrawDelayedImageCommits(dt, aWaylandBufferDamage); + DrawDelayedImageCommits(dt, mWaylandBufferDamage); UnlockWaylandBuffer(); return true; @@ -932,7 +961,8 @@ static void WaylandBufferDelayCommitHand } void WindowSurfaceWayland::CommitWaylandBuffer() { - MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); + MOZ_ASSERT(!mWaylandBuffer->IsAttached(), + "We can't draw to attached wayland buffer!"); LOGWAYLAND(("WindowSurfaceWayland::CommitWaylandBuffer [%p]\n", (void*)this)); LOGWAYLAND( @@ -941,6 +971,21 @@ void WindowSurfaceWayland::CommitWayland LOGWAYLAND((" mDelayedCommitHandle = %p\n", mDelayedCommitHandle)); LOGWAYLAND((" mFrameCallback = %p\n", mFrameCallback)); LOGWAYLAND((" mLastCommittedSurface = %p\n", mLastCommittedSurface)); + LOGWAYLAND((" mBufferPendingCommit = %d\n", mBufferPendingCommit)); + LOGWAYLAND((" mBufferCommitAllowed = %d\n", mBufferCommitAllowed)); + + if (!mBufferCommitAllowed) { + return; + } + + if (CommitImageCacheToWaylandBuffer()) { + mBufferPendingCommit = true; + } + + // There's nothing to do here + if (!mBufferPendingCommit) { + return; + } wl_surface* waylandSurface = mWindow->GetWaylandSurface(); if (!waylandSurface) { @@ -986,6 +1031,7 @@ void WindowSurfaceWayland::CommitWayland } if (mWholeWindowBufferDamage) { + LOGWAYLAND((" send whole screen damage\n")); wl_surface_damage(waylandSurface, 0, 0, mBufferScreenRect.width, mBufferScreenRect.height); mWholeWindowBufferDamage = false; @@ -994,6 +1040,8 @@ void WindowSurfaceWayland::CommitWayland for (auto iter = mWaylandBufferDamage.RectIter(); !iter.Done(); iter.Next()) { mozilla::LayoutDeviceIntRect r = iter.Get(); + LOGWAYLAND((" wl_surface_damage_buffer [%d, %d] -> [%d, %d]\n", r.x, + r.y, r.width, r.height)); wl_surface_damage_buffer(waylandSurface, r.x, r.y, r.width, r.height); } } @@ -1012,24 +1060,31 @@ void WindowSurfaceWayland::CommitWayland mWaylandBuffer->Attach(waylandSurface); mLastCommittedSurface = waylandSurface; + mLastCommitTime = g_get_monotonic_time() / 1000; + + // Ask wl_display to start events synchronization. We're going wait + // until all events are processed before next WindowSurfaceWayland::Lock() + // as we need freed wl_buffer there. + mWaylandDisplay->SyncBegin(); // There's no pending commit, all changes are sent to compositor. - mPendingCommit = false; + mBufferPendingCommit = false; } void WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) { MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); -#ifdef DEBUG - { - gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect(); - gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); + // Flush all waiting events explicitly as we need + // mWaylandDisplay->FlushEventQueue(); +#ifdef MOZ_LOGGING + { + gfx::IntRect lockSize = aInvalidRegion.GetBounds().ToUnknownRect(); LOGWAYLAND( - ("WindowSurfaceWayland::Commit [%p] lockSize [%d x %d] screenSize [%d " - "x %d]\n", - (void*)this, lockSize.width, lockSize.height, mBufferScreenRect.width, - mBufferScreenRect.height)); + ("WindowSurfaceWayland::Commit [%p] damage size [%d, %d] -> [%d x %d]" + "screenSize [%d x %d]\n", + (void*)this, lockSize.x, lockSize.y, lockSize.width, lockSize.height, + mBufferScreenRect.width, mBufferScreenRect.height)); LOGWAYLAND((" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly)); LOGWAYLAND( @@ -1044,21 +1099,15 @@ void WindowSurfaceWayland::Commit(const mWaylandBufferDamage.OrWith(aInvalidRegion); } UnlockWaylandBuffer(); - mPendingCommit = true; + mBufferPendingCommit = true; } else { MOZ_ASSERT(!mWaylandBuffer->IsLocked(), "Drawing to already locked buffer?"); - if (CommitImageSurfaceToWaylandBuffer(aInvalidRegion, - mWaylandBufferDamage)) { - // Our cached drawing is flushed, we can draw fullscreen again. - mDrawToWaylandBufferDirectly = true; - mPendingCommit = true; - } + CacheImageSurface(aInvalidRegion); } - if (mPendingCommit) { - CommitWaylandBuffer(); - } + mBufferCommitAllowed = true; + CommitWaylandBuffer(); } void WindowSurfaceWayland::FrameCallbackHandler() { @@ -1074,9 +1123,7 @@ void WindowSurfaceWayland::FrameCallback wl_callback_destroy(mFrameCallback); mFrameCallback = nullptr; - if (mPendingCommit) { - CommitWaylandBuffer(); - } + CommitWaylandBuffer(); } void WindowSurfaceWayland::DelayedCommitHandler() { @@ -1089,9 +1136,7 @@ void WindowSurfaceWayland::DelayedCommit free(mDelayedCommitHandle); mDelayedCommitHandle = nullptr; - if (mPendingCommit) { - CommitWaylandBuffer(); - } + CommitWaylandBuffer(); } } // namespace widget diff -up firefox-69.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1580152 firefox-69.0/widget/gtk/WindowSurfaceWayland.h --- firefox-69.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1580152 2019-09-16 11:11:30.080299221 +0200 +++ firefox-69.0/widget/gtk/WindowSurfaceWayland.h 2019-09-16 11:11:30.090299187 +0200 @@ -17,6 +17,8 @@ namespace mozilla { namespace widget { +class WindowSurfaceWayland; + // Allocates and owns shared memory for Wayland drawing surface class WaylandShmPool { public: @@ -69,20 +71,22 @@ class WindowBackBuffer { static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } - nsWaylandDisplay* GetWaylandDisplay() { return mWaylandDisplay; }; + nsWaylandDisplay* GetWaylandDisplay(); - WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay) - : mWaylandDisplay(aWaylandDisplay){}; + WindowBackBuffer(WindowSurfaceWayland* aWindowSurfaceWayland) + : mWindowSurfaceWayland(aWindowSurfaceWayland){}; virtual ~WindowBackBuffer(){}; + protected: + WindowSurfaceWayland* mWindowSurfaceWayland; + private: static gfx::SurfaceFormat mFormat; - nsWaylandDisplay* mWaylandDisplay; }; class WindowBackBufferShm : public WindowBackBuffer { public: - WindowBackBufferShm(nsWaylandDisplay* aWaylandDisplay, int aWidth, + WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, int aHeight); ~WindowBackBufferShm(); @@ -121,8 +125,8 @@ class WindowBackBufferShm : public Windo class WindowBackBufferDMABuf : public WindowBackBuffer { public: - WindowBackBufferDMABuf(nsWaylandDisplay* aWaylandDisplay, int aWidth, - int aHeight); + WindowBackBufferDMABuf(WindowSurfaceWayland* aWindowSurfaceWayland, + int aWidth, int aHeight); ~WindowBackBufferDMABuf(); bool IsAttached(); @@ -175,6 +179,9 @@ class WindowSurfaceWayland : public Wind void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; void FrameCallbackHandler(); void DelayedCommitHandler(); + void CommitWaylandBuffer(); + + nsWaylandDisplay* GetWaylandDisplay() { return mWaylandDisplay; }; private: WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight); @@ -185,10 +192,9 @@ class WindowSurfaceWayland : public Wind already_AddRefed LockImageSurface( const gfx::IntSize& aLockSize); - bool CommitImageSurfaceToWaylandBuffer( - const LayoutDeviceIntRegion& aRegion, - LayoutDeviceIntRegion& aWaylandBufferDamage); - void CommitWaylandBuffer(); + + void CacheImageSurface(const LayoutDeviceIntRegion& aRegion); + bool CommitImageCacheToWaylandBuffer(); void DrawDelayedImageCommits(gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage); @@ -205,12 +211,13 @@ class WindowSurfaceWayland : public Wind WindowBackBuffer* mBackupBuffer[BACK_BUFFER_NUM]; wl_callback* mFrameCallback; wl_surface* mLastCommittedSurface; - MessageLoop* mDisplayThreadMessageLoop; WindowSurfaceWayland** mDelayedCommitHandle; RefPtr mImageSurface; AutoTArray mDelayedImageCommits; + int64_t mLastCommitTime; bool mDrawToWaylandBufferDirectly; - bool mPendingCommit; + bool mBufferPendingCommit; + bool mBufferCommitAllowed; bool mWholeWindowBufferDamage; bool mBufferNeedsClear; bool mIsMainThread;