--- a/widget/gtk/WindowSurfaceWayland.cpp
+++ b/widget/gtk/WindowSurfaceWayland.cpp
@@ -27,16 +27,19 @@
# include "Units.h"
extern mozilla::LazyLogModule gWidgetWaylandLog;
# define LOGWAYLAND(args) \
MOZ_LOG(gWidgetWaylandLog, mozilla::LogLevel::Debug, args)
#else
# define LOGWAYLAND(args)
#endif /* MOZ_LOGGING */
+// Maximal compositing timeout it miliseconds
+#define COMPOSITING_TIMEOUT 200
+
namespace mozilla {
namespace widget {
bool WindowSurfaceWayland::mUseDMABuf = false;
bool WindowSurfaceWayland::mUseDMABufInitialized = false;
/*
Wayland multi-thread rendering scheme
@@ -193,16 +196,20 @@ available and widget.wayland_dmabuf_back
*/
#define EVENT_LOOP_DELAY (1000 / 240)
#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.");
nsPrintfCString tmpname("%s/mozilla-shared-XXXXXX", tmppath);
char* filename;
int fd = -1;
@@ -337,20 +344,21 @@ void WindowBackBufferShm::Release() {
wl_buffer_destroy(mWaylandBuffer);
mWidth = mHeight = 0;
}
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),
mAttached(false) {
Create(aWidth, aHeight);
}
WindowBackBufferShm::~WindowBackBufferShm() { Release(); }
@@ -382,16 +390,19 @@ void WindowBackBuffer::Attach(wl_surface
}
void WindowBackBufferShm::Detach(wl_buffer* aBuffer) {
LOGWAYLAND(("WindowBackBufferShm::Detach [%p] wl_buffer %p ID %d\n",
(void*)this, (void*)aBuffer,
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(
class WindowBackBuffer* aSourceBuffer) {
auto sourceBuffer = static_cast<class WindowBackBufferShm*>(aSourceBuffer);
if (!IsMatchingSize(sourceBuffer)) {
Resize(sourceBuffer->mWidth, sourceBuffer->mHeight);
}
@@ -411,18 +422,18 @@ already_AddRefed<gfx::DrawTarget> Window
gfx::IntSize lockSize(mWidth, mHeight);
mIsLocked = true;
return gfxPlatform::CreateDrawTargetForData(
static_cast<unsigned char*>(mShmPool.GetImageData()), lockSize,
BUFFER_BPP * mWidth, GetSurfaceFormat());
}
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 "
"buffer [%d x %d]\n",
(void*)this, aWidth, aHeight));
}
@@ -471,16 +482,19 @@ bool WindowBackBufferDMABuf::SetImageDat
WindowBackBufferDMABuf* source =
static_cast<WindowBackBufferDMABuf*>(aSourceBuffer);
mDMAbufSurface.CopyFrom(&source->mDMAbufSurface);
return true;
}
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(); }
static void frame_callback_handler(void* data, struct wl_callback* callback,
uint32_t time) {
auto surface = reinterpret_cast<WindowSurfaceWayland*>(data);
surface->FrameCallbackHandler();
@@ -492,31 +506,32 @@ static const struct wl_callback_listener
frame_callback_handler};
WindowSurfaceWayland::WindowSurfaceWayland(nsWindow* aWindow)
: mWindow(aWindow),
mWaylandDisplay(WaylandDisplayGet()),
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()),
mNeedScaleFactorUpdate(true) {
for (int i = 0; i < BACK_BUFFER_NUM; i++) mBackupBuffer[i] = nullptr;
mRenderingCacheMode = static_cast<RenderingCacheMode>(
mWaylandDisplay->GetRenderingCacheModePref());
}
WindowSurfaceWayland::~WindowSurfaceWayland() {
- if (mPendingCommit) {
+ if (mBufferPendingCommit) {
NS_WARNING("Deleted WindowSurfaceWayland with a pending commit!");
}
if (mDelayedCommitHandle) {
// Delete reference to this to prevent WaylandBufferDelayCommitHandler()
// operate on released this. mDelayedCommitHandle itself will
// be released at WaylandBufferDelayCommitHandler().
*mDelayedCommitHandle = nullptr;
@@ -545,34 +560,34 @@ bool WindowSurfaceWayland::UseDMABufBack
return mUseDMABuf;
}
WindowBackBuffer* WindowSurfaceWayland::CreateWaylandBuffer(int aWidth,
int aHeight) {
if (UseDMABufBackend()) {
static bool sDMABufBufferCreated = false;
WindowBackBuffer* buffer =
- new WindowBackBufferDMABuf(mWaylandDisplay, aWidth, aHeight);
+ new WindowBackBufferDMABuf(this, aWidth, aHeight);
if (buffer) {
sDMABufBufferCreated = true;
return buffer;
}
// If this is the first failure and there's no dmabuf already active
// we can safely fallback to Shm. Otherwise we can't mix DMAbuf and
// SHM buffers so just fails now.
if (sDMABufBufferCreated) {
NS_WARNING("Failed to allocate DMABuf buffer!");
return nullptr;
} else {
NS_WARNING("Wayland DMABuf failed, switched back to Shm backend!");
mUseDMABuf = false;
}
}
- return new WindowBackBufferShm(mWaylandDisplay, aWidth, aHeight);
+ return new WindowBackBufferShm(this, aWidth, aHeight);
}
WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(
bool aCanSwitchBuffer) {
LOGWAYLAND(
("WindowSurfaceWayland::GetWaylandBufferToDraw [%p] Requested buffer [%d "
"x %d]\n",
(void*)this, mBufferScreenRect.width, mBufferScreenRect.height));
@@ -673,16 +688,21 @@ WindowBackBuffer* WindowSurfaceWayland::
already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockWaylandBuffer(
bool aCanSwitchBuffer) {
WindowBackBuffer* buffer = GetWaylandBufferToDraw(aCanSwitchBuffer);
LOGWAYLAND(("WindowSurfaceWayland::LockWaylandBuffer [%p] Got buffer %p\n",
(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;
}
if (mBufferNeedsClear && mWholeWindowBufferDamage) {
buffer->Clear();
mBufferNeedsClear = false;
}
@@ -724,19 +744,17 @@ static bool IsWindowFullScreenUpdate(
static bool IsPopupFullScreenUpdate(
LayoutDeviceIntRect& aScreenRect,
const LayoutDeviceIntRegion& aUpdatedRegion) {
// We know that popups can be drawn from two parts; a panel and an arrow.
// Assume we redraw whole popups when we have two rects and bounding
// box is equal to window borders.
if (aUpdatedRegion.GetNumRects() > 2) return false;
- gfx::IntRect bounds = aUpdatedRegion.GetBounds().ToUnknownRect();
- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
-
+ gfx::IntRect lockSize = aUpdatedRegion.GetBounds().ToUnknownRect();
return (aScreenRect.width == lockSize.width &&
aScreenRect.height == lockSize.height);
}
bool WindowSurfaceWayland::CanDrawToWaylandBufferDirectly(
const LayoutDeviceIntRect& aScreenRect,
const LayoutDeviceIntRegion& aUpdatedRegion) {
// whole buffer damage or no cache - we can go direct rendering safely.
@@ -751,56 +769,44 @@ bool WindowSurfaceWayland::CanDrawToWayl
return false;
}
// More than one regions can overlap and produce flickering/artifacts.
if (aUpdatedRegion.GetNumRects() > 1) {
return false;
}
- gfx::IntRect bounds = aUpdatedRegion.GetBounds().ToUnknownRect();
- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
+ gfx::IntRect lockSize = aUpdatedRegion.GetBounds().ToUnknownRect();
// There's some heuristics here. Let's enable direct rendering for large
// screen updates like video playback or page scrolling which is bigger
// than 1/3 of screen.
if (lockSize.width * 3 > aScreenRect.width &&
lockSize.height * 3 > aScreenRect.height) {
return true;
}
}
return false;
}
-/*
- There are some situations which can happen here:
-
- A) Lock() is called to whole surface. In that case we don't need
- 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)
-
- 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.
- */
already_AddRefed<gfx::DrawTarget> 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 =
mWindow->IsWaylandPopup() &&
(eTransparencyTransparent == mWindow->GetTransparencyMode());
// We have request to lock whole buffer/window.
mWholeWindowBufferDamage =
isTransparentPopup ? IsPopupFullScreenUpdate(lockedScreenRect, aRegion)
: IsWindowFullScreenUpdate(lockedScreenRect, aRegion);
@@ -809,31 +815,31 @@ already_AddRefed<gfx::DrawTarget> Window
// otherwise leave it as-is, mBufferNeedsClear can be set from previous
// (already pending) commits which are cached now.
if (mWholeWindowBufferDamage) {
mBufferNeedsClear =
mWindow->WaylandSurfaceNeedsClear() || isTransparentPopup;
}
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));
LOGWAYLAND((" IsPopupFullScreenUpdate = %d\n",
IsPopupFullScreenUpdate(lockedScreenRect, aRegion)));
LOGWAYLAND((" IsWindowFullScreenUpdate = %d\n",
IsWindowFullScreenUpdate(lockedScreenRect, aRegion)));
LOGWAYLAND((" mBufferNeedsClear = %d\n", mBufferNeedsClear));
LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
-#if DEBUG
+#if MOZ_LOGGING
if (!(mBufferScreenRect == lockedScreenRect)) {
LOGWAYLAND((" screen size changed\n"));
}
#endif
if (!(mBufferScreenRect == lockedScreenRect)) {
// Screen (window) size changed and we still have some painting pending
// for the last window size. That can happen when window is resized.
@@ -849,23 +855,30 @@ already_AddRefed<gfx::DrawTarget> Window
return nullptr;
}
mBufferScreenRect = lockedScreenRect;
}
mDrawToWaylandBufferDirectly =
CanDrawToWaylandBufferDirectly(mBufferScreenRect, aRegion);
if (mDrawToWaylandBufferDirectly) {
+ LOGWAYLAND((" Direct drawing\n"));
// If there's any pending image commit scratch them as we're going
// to redraw the whole sceen anyway.
- mDelayedImageCommits.Clear();
+ if (mWholeWindowBufferDamage) {
+ LOGWAYLAND((" Whole buffer update, clear cache.\n"));
+ mDelayedImageCommits.Clear();
+ }
RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
/* aCanSwitchBuffer */ mWholeWindowBufferDamage);
if (dt) {
+ if (!mWholeWindowBufferDamage) {
+ DrawDelayedImageCommits(dt, mWaylandBufferDamage);
+ }
return dt.forget();
}
}
// Any caching is disabled and we don't have any back buffer available.
if (mRenderingCacheMode == CACHE_NONE) {
return nullptr;
}
@@ -874,25 +887,35 @@ already_AddRefed<gfx::DrawTarget> Window
//
// 1) We don't have any front buffer available. Try indirect drawing
// to mImageSurface which is mirrored to front buffer at commit.
// 2) Only part of the screen is locked. We can't lock entire screen for
// such drawing as it produces visible artifacts.
mDrawToWaylandBufferDirectly = false;
LOGWAYLAND((" Indirect drawing.\n"));
- return LockImageSurface(lockSize);
+ return LockImageSurface(gfx::IntSize(lockSize.XMost(), lockSize.YMost()));
}
void WindowImageSurface::Draw(gfx::SourceSurface* aSurface,
gfx::DrawTarget* aDest,
const LayoutDeviceIntRegion& aRegion) {
+#ifdef MOZ_LOGGING
+ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
+ LOGWAYLAND(("WindowImageSurface::Draw\n"));
+ LOGWAYLAND((" rects num %d\n", aRegion.GetNumRects()));
+ LOGWAYLAND((" bounds [ %d, %d] -> [%d x %d]\n", bounds.x, bounds.y,
+ bounds.width, bounds.height));
+#endif
+
for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
mozilla::LayoutDeviceIntRect r = iter.Get();
gfx::Rect rect(r.ToUnknownRect());
+ LOGWAYLAND((" draw rect [%f,%f] -> [%f x %f]\n", rect.x, rect.y,
+ rect.width, rect.height));
aDest->DrawSurface(aSurface, rect, rect);
}
}
void WindowImageSurface::Draw(gfx::DrawTarget* aDest,
LayoutDeviceIntRegion& aWaylandBufferDamage) {
Draw(mSurface.get(), aDest, mUpdateRegion);
aWaylandBufferDamage.OrWith(mUpdateRegion);
@@ -903,75 +926,103 @@ WindowImageSurface::WindowImageSurface(
: mImageSurface(aImageSurface), mUpdateRegion(aUpdateRegion) {
mSurface = gfx::Factory::CreateSourceSurfaceForCairoSurface(
mImageSurface->CairoSurface(), mImageSurface->GetSize(),
mImageSurface->Format());
}
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();
}
void WindowSurfaceWayland::CacheImageSurface(
const LayoutDeviceIntRegion& aRegion) {
- LOGWAYLAND(("WindowSurfaceWayland::CacheImageSurface [%p]", (void*)this));
+#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())));
}
bool WindowSurfaceWayland::CommitImageCacheToWaylandBuffer() {
+ if (!mDelayedImageCommits.Length()) {
+ return false;
+ }
+
MOZ_ASSERT(!mDrawToWaylandBufferDirectly);
- if (mDelayedImageCommits.Length()) {
- RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
- /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
- if (!dt) {
- return false;
- }
+ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
+ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
+ if (!dt) {
+ return false;
+ }
- LOGWAYLAND(
- (" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n",
- long(mDelayedImageCommits.Length() + 1)));
+ LOGWAYLAND((" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n",
+ long(mDelayedImageCommits.Length())));
- // Draw any delayed image commits first
- DrawDelayedImageCommits(dt, mWaylandBufferDamage);
- UnlockWaylandBuffer();
- }
+ DrawDelayedImageCommits(dt, mWaylandBufferDamage);
+ UnlockWaylandBuffer();
return true;
}
static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland** aSurface) {
if (*aSurface) {
(*aSurface)->DelayedCommitHandler();
} else {
// Referenced WindowSurfaceWayland is already deleted.
// Do nothing but just release the mDelayedCommitHandle allocated at
// WindowSurfaceWayland::CommitWaylandBuffer().
free(aSurface);
}
}
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(
(" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
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) {
LOGWAYLAND((" [%p] mWindow->GetWaylandSurface() failed, delay commit.\n",
(void*)this));
// Target window is not created yet - delay the commit. This can happen only
// when the window is newly created and there's no active
@@ -1007,24 +1058,27 @@ void WindowSurfaceWayland::CommitWayland
// If our stored wl_surface does not match the actual one it means the frame
// callback is no longer active and we should release it.
wl_callback_destroy(mFrameCallback);
mFrameCallback = nullptr;
mLastCommittedSurface = nullptr;
}
if (mWholeWindowBufferDamage) {
+ LOGWAYLAND((" send whole screen damage\n"));
wl_surface_damage(waylandSurface, 0, 0, mBufferScreenRect.width,
mBufferScreenRect.height);
mWholeWindowBufferDamage = false;
mNeedScaleFactorUpdate = true;
} else {
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);
}
}
// Clear all back buffer damage as we're committing
// all requested regions.
mWaylandBufferDamage.SetEmpty();
@@ -1033,90 +1087,86 @@ void WindowSurfaceWayland::CommitWayland
if (mNeedScaleFactorUpdate || mLastCommittedSurface != waylandSurface) {
wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor());
mNeedScaleFactorUpdate = false;
}
mWaylandBuffer->Attach(waylandSurface);
mLastCommittedSurface = waylandSurface;
+ mLastCommitTime = g_get_monotonic_time() / 1000;
+
+ // Ask wl_display to start events synchronization. We're going to wait
+ // until all events are processed before next WindowSurfaceWayland::Lock()
+ // as we hope for free 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
+#ifdef MOZ_LOGGING
{
- gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
-
+ 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(
(" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
}
#endif
if (mDrawToWaylandBufferDirectly) {
MOZ_ASSERT(mWaylandBuffer->IsLocked());
// If we're not at fullscreen damage add drawing area from aInvalidRegion
if (!mWholeWindowBufferDamage) {
mWaylandBufferDamage.OrWith(aInvalidRegion);
}
UnlockWaylandBuffer();
- mPendingCommit = true;
+ mBufferPendingCommit = true;
} else {
MOZ_ASSERT(!mWaylandBuffer->IsLocked(),
"Drawing to already locked buffer?");
CacheImageSurface(aInvalidRegion);
- if (CommitImageCacheToWaylandBuffer()) {
- mPendingCommit = true;
- }
}
- if (mPendingCommit) {
- CommitWaylandBuffer();
- }
+ mBufferCommitAllowed = true;
+ CommitWaylandBuffer();
}
void WindowSurfaceWayland::FrameCallbackHandler() {
MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
MOZ_ASSERT(mFrameCallback != nullptr,
"FrameCallbackHandler() called without valid frame callback!");
MOZ_ASSERT(mLastCommittedSurface != nullptr,
"FrameCallbackHandler() called without valid wl_surface!");
LOGWAYLAND(
("WindowSurfaceWayland::FrameCallbackHandler [%p]\n", (void*)this));
wl_callback_destroy(mFrameCallback);
mFrameCallback = nullptr;
- if (mPendingCommit) {
- CommitWaylandBuffer();
- }
+ CommitWaylandBuffer();
}
void WindowSurfaceWayland::DelayedCommitHandler() {
MOZ_ASSERT(mDelayedCommitHandle != nullptr, "Missing mDelayedCommitHandle!");
LOGWAYLAND(
("WindowSurfaceWayland::DelayedCommitHandler [%p]\n", (void*)this));
*mDelayedCommitHandle = nullptr;
free(mDelayedCommitHandle);
mDelayedCommitHandle = nullptr;
- if (mPendingCommit) {
- CommitWaylandBuffer();
- }
+ CommitWaylandBuffer();
}
} // namespace widget
} // namespace mozilla