firefox/mozilla-1574036.patch

426 lines
17 KiB
Diff

diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h
--- a/widget/gtk/WindowSurfaceWayland.h
+++ b/widget/gtk/WindowSurfaceWayland.h
@@ -177,12 +177,9 @@
private:
WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight);
- WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight,
- bool aFullScreenUpdate);
+ WindowBackBuffer* GetWaylandBufferToDraw(bool aCanSwitchBuffer);
- already_AddRefed<gfx::DrawTarget> LockWaylandBuffer(int aWidth, int aHeight,
- bool aClearBuffer,
- bool aFullScreenUpdate);
+ already_AddRefed<gfx::DrawTarget> LockWaylandBuffer(bool aCanSwitchBuffer);
void UnlockWaylandBuffer();
already_AddRefed<gfx::DrawTarget> LockImageSurface(
@@ -198,7 +195,10 @@
// TODO: Do we need to hold a reference to nsWindow object?
nsWindow* mWindow;
- LayoutDeviceIntRect mLastScreenRect;
+ // Buffer screen rects helps us understand if we operate on
+ // the same window size as we're called on WindowSurfaceWayland::Lock().
+ // mBufferScreenRect is window size when our wayland buffer was allocated.
+ LayoutDeviceIntRect mBufferScreenRect;
nsWaylandDisplay* mWaylandDisplay;
WindowBackBuffer* mWaylandBuffer;
LayoutDeviceIntRegion mWaylandBufferDamage;
@@ -211,7 +211,8 @@
AutoTArray<WindowImageSurface, 30> mDelayedImageCommits;
bool mDrawToWaylandBufferDirectly;
bool mPendingCommit;
- bool mWaylandBufferFullScreenDamage;
+ bool mWholeWindowBufferDamage;
+ bool mBufferNeedsClear;
bool mIsMainThread;
bool mNeedScaleFactorUpdate;
diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
--- a/widget/gtk/WindowSurfaceWayland.cpp
+++ b/widget/gtk/WindowSurfaceWayland.cpp
@@ -499,7 +499,8 @@
mDelayedCommitHandle(nullptr),
mDrawToWaylandBufferDirectly(true),
mPendingCommit(false),
- mWaylandBufferFullScreenDamage(false),
+ mWholeWindowBufferDamage(false),
+ mBufferNeedsClear(false),
mIsMainThread(NS_IsMainThread()),
mNeedScaleFactorUpdate(true) {
for (int i = 0; i < BACK_BUFFER_NUM; i++) mBackupBuffer[i] = nullptr;
@@ -565,18 +566,20 @@
}
WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(
- int aWidth, int aHeight, bool aFullScreenUpdate) {
+ bool aCanSwitchBuffer) {
LOGWAYLAND(("%s [%p] Requested buffer [%d x %d]\n", __PRETTY_FUNCTION__,
- (void*)this, aWidth, aHeight));
+ (void*)this, mBufferScreenRect.width, mBufferScreenRect.height));
// There's no buffer created yet, create a new one.
if (!mWaylandBuffer) {
- MOZ_ASSERT(aFullScreenUpdate, "Created new buffer for partial drawing!");
+ MOZ_ASSERT(aCanSwitchBuffer && mWholeWindowBufferDamage,
+ "Created new buffer for partial drawing!");
LOGWAYLAND(("%s [%p] Created new buffer [%d x %d]\n", __PRETTY_FUNCTION__,
- (void*)this, aWidth, aHeight));
+ (void*)this, mBufferScreenRect.width,
+ mBufferScreenRect.height));
- mWaylandBuffer = CreateWaylandBuffer(aWidth, aHeight);
- mWaylandBufferFullScreenDamage = true;
+ mWaylandBuffer =
+ CreateWaylandBuffer(mBufferScreenRect.width, mBufferScreenRect.height);
mNeedScaleFactorUpdate = true;
return mWaylandBuffer;
}
@@ -593,29 +596,31 @@
LOGWAYLAND(
("%s [%p] Use recent buffer.\n", __PRETTY_FUNCTION__, (void*)this));
- if (mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) {
+ if (mWaylandBuffer->IsMatchingSize(mBufferScreenRect.width,
+ mBufferScreenRect.height)) {
LOGWAYLAND(("%s [%p] Size is ok, use the buffer [%d x %d]\n",
- __PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
+ __PRETTY_FUNCTION__, (void*)this, mBufferScreenRect.width,
+ mBufferScreenRect.height));
return mWaylandBuffer;
}
- if (!aFullScreenUpdate) {
+ if (!aCanSwitchBuffer) {
NS_WARNING("We can't resize Wayland buffer for non-fullscreen updates!");
return nullptr;
}
LOGWAYLAND(("%s [%p] Reuse buffer with resize [%d x %d]\n",
- __PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
+ __PRETTY_FUNCTION__, (void*)this, mBufferScreenRect.width,
+ mBufferScreenRect.height));
- mWaylandBuffer->Resize(aWidth, aHeight);
+ mWaylandBuffer->Resize(mBufferScreenRect.width, mBufferScreenRect.height);
// There's a chance that scale factor has been changed
// when buffer size changed
- mWaylandBufferFullScreenDamage = true;
mNeedScaleFactorUpdate = true;
return mWaylandBuffer;
}
- if (!aFullScreenUpdate) {
+ if (!aCanSwitchBuffer) {
return nullptr;
}
@@ -625,8 +630,10 @@
availableBuffer++) {
if (!mBackupBuffer[availableBuffer]) {
LOGWAYLAND(("%s [%p] Created new buffer [%d x %d]\n", __PRETTY_FUNCTION__,
- (void*)this, aWidth, aHeight));
- mBackupBuffer[availableBuffer] = CreateWaylandBuffer(aWidth, aHeight);
+ (void*)this, mBufferScreenRect.width,
+ mBufferScreenRect.height));
+ mBackupBuffer[availableBuffer] = CreateWaylandBuffer(
+ mBufferScreenRect.width, mBufferScreenRect.height);
break;
}
@@ -650,23 +657,23 @@
__PRETTY_FUNCTION__, (void*)this, (void*)lastWaylandBuffer,
(void*)mWaylandBuffer));
- mWaylandBufferFullScreenDamage = true;
mNeedScaleFactorUpdate = true;
- bool bufferNeedsResize = !mWaylandBuffer->IsMatchingSize(aWidth, aHeight);
+ bool bufferNeedsResize = !mWaylandBuffer->IsMatchingSize(
+ mBufferScreenRect.width, mBufferScreenRect.height);
if (bufferNeedsResize) {
LOGWAYLAND(("%s [%p] Resize buffer to [%d x %d]\n", __PRETTY_FUNCTION__,
- (void*)this, aWidth, aHeight));
- mWaylandBuffer->Resize(aWidth, aHeight);
+ (void*)this, mBufferScreenRect.width,
+ mBufferScreenRect.height));
+ mWaylandBuffer->Resize(mBufferScreenRect.width, mBufferScreenRect.height);
}
return mWaylandBuffer;
}
already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockWaylandBuffer(
- int aWidth, int aHeight, bool aClearBuffer, bool aFullScreenUpdate) {
- WindowBackBuffer* buffer =
- GetWaylandBufferToDraw(aWidth, aHeight, aFullScreenUpdate);
+ bool aCanSwitchBuffer) {
+ WindowBackBuffer* buffer = GetWaylandBufferToDraw(aCanSwitchBuffer);
LOGWAYLAND(("%s [%p] Got buffer %p\n", __PRETTY_FUNCTION__, (void*)this,
(void*)buffer));
@@ -675,8 +682,9 @@
return nullptr;
}
- if (aClearBuffer) {
+ if (mBufferNeedsClear && mWholeWindowBufferDamage) {
buffer->Clear();
+ mBufferNeedsClear = false;
}
return buffer->Lock();
@@ -744,7 +752,7 @@
const LayoutDeviceIntRegion& aRegion) {
MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
+ LayoutDeviceIntRect lockedScreenRect = mWindow->GetBounds();
gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
@@ -753,54 +761,77 @@
mWindow->IsWaylandPopup() &&
(eTransparencyTransparent == mWindow->GetTransparencyMode());
- mDrawToWaylandBufferDirectly =
- isTransparentPopup ? IsPopupFullScreenUpdate(screenRect, aRegion)
- : IsWindowFullScreenUpdate(screenRect, aRegion);
+ // We have request to lock whole buffer/window.
+ mWholeWindowBufferDamage =
+ isTransparentPopup ? IsPopupFullScreenUpdate(lockedScreenRect, aRegion)
+ : IsWindowFullScreenUpdate(lockedScreenRect, aRegion);
- bool needsClear = mWindow->WaylandSurfaceNeedsClear() ||
- (isTransparentPopup && mDrawToWaylandBufferDirectly);
+ // Clear buffer when we (re)draw new transparent popup 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(("%s [%p] lockSize [%d x %d] windowSize [%d x %d]\n",
__PRETTY_FUNCTION__, (void*)this, lockSize.width, lockSize.height,
- screenRect.width, screenRect.height));
+ 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(screenRect, aRegion)));
+ IsPopupFullScreenUpdate(lockedScreenRect, aRegion)));
LOGWAYLAND((" IsWindowFullScreenUpdate = %d\n",
- IsWindowFullScreenUpdate(screenRect, aRegion)));
- LOGWAYLAND((" needsClear = %d\n", needsClear));
- LOGWAYLAND(
- (" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
+ IsWindowFullScreenUpdate(lockedScreenRect, aRegion)));
+ LOGWAYLAND((" mBufferNeedsClear = %d\n", mBufferNeedsClear));
+ LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
+
+#if DEBUG
+ if (!(mBufferScreenRect == lockedScreenRect)) {
+ LOGWAYLAND((" screen size changed\n"));
+ }
+#endif
- // Allow full screen allocation and clear
- // when window size changed.
- bool bufferRedraw = !(screenRect == mLastScreenRect);
- if (bufferRedraw) {
- mDrawToWaylandBufferDirectly = true;
- needsClear = true;
+ 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.
+ // We can't commit them any more as they're for former window size, so
+ // scratch them.
+ mDelayedImageCommits.Clear();
+
+ if (!mWholeWindowBufferDamage) {
+ NS_WARNING("Partial screen update when window is resized!");
+ // This should not happen. Screen size changed but we got only
+ // partal screen update instead of whole screen. Discard this painting
+ // as it produces artifacts.
+ return nullptr;
+ }
+ mBufferScreenRect = lockedScreenRect;
}
- if (mDrawToWaylandBufferDirectly) {
+ if (mWholeWindowBufferDamage) {
+ // We can lock/commit entire buffer direcly.
+ mDrawToWaylandBufferDirectly = true;
+
// If there's any pending image commit scratch them as we're going
// to redraw the whole sceen anyway.
mDelayedImageCommits.Clear();
- RefPtr<gfx::DrawTarget> dt =
- LockWaylandBuffer(screenRect.width, screenRect.height, needsClear,
- /* aFullScreenUpdate */ true);
+ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
+ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
if (dt) {
- if (bufferRedraw) {
- mLastScreenRect = screenRect;
- }
return dt.forget();
}
+ }
- // We don't have any front buffer available. Try indirect drawing
- // to mImageSurface which is mirrored to front buffer at commit.
- mDrawToWaylandBufferDirectly = false;
- }
+ // We do indirect drawing due to:
+ //
+ // 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);
@@ -851,16 +882,14 @@
LayoutDeviceIntRegion& aWaylandBufferDamage) {
MOZ_ASSERT(!mDrawToWaylandBufferDirectly);
- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
+#ifdef DEBUG
gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
-
gfx::Rect rect(bounds);
- if (rect.IsEmpty()) {
- return false;
- }
+ MOZ_ASSERT(!rect.IsEmpty(), "Empty drawing?");
+#endif
LOGWAYLAND(("%s [%p] screenSize [%d x %d]\n", __PRETTY_FUNCTION__,
- (void*)this, screenRect.width, screenRect.height));
+ (void*)this, mBufferScreenRect.width, mBufferScreenRect.height));
RefPtr<gfx::SourceSurface> surf =
gfx::Factory::CreateSourceSurfaceForCairoSurface(
@@ -871,13 +900,8 @@
return false;
}
- // Allow full screen allocation and clear
- // when window size changed.
- bool bufferRedraw = !(screenRect == mLastScreenRect);
- RefPtr<gfx::DrawTarget> dt =
- LockWaylandBuffer(screenRect.width, screenRect.height,
- /* needs clear*/ bufferRedraw,
- /* aFullScreenUpdate */ bufferRedraw);
+ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
+ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
if (dt) {
LOGWAYLAND(
(" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n",
@@ -885,14 +909,11 @@
// Draw any delayed image commits first
DrawDelayedImageCommits(dt, aWaylandBufferDamage);
+ // Draw image from recent WindowSurfaceWayland::Lock().
WindowImageSurface::Draw(surf, dt, aRegion);
// Submit all drawing to final Wayland buffer upload
aWaylandBufferDamage.OrWith(aRegion);
UnlockWaylandBuffer();
-
- if (bufferRedraw) {
- mLastScreenRect = screenRect;
- }
} else {
mDelayedImageCommits.AppendElement(WindowImageSurface(surf, aRegion));
LOGWAYLAND((" Added WindowImageSurfaces, cached surfaces %ld\n",
@@ -930,29 +951,25 @@
LOGWAYLAND(("%s [%p]\n", __PRETTY_FUNCTION__, (void*)this));
LOGWAYLAND(
(" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
- LOGWAYLAND((" mWaylandBufferFullScreenDamage = %d\n",
- mWaylandBufferFullScreenDamage));
+ LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
LOGWAYLAND((" mDelayedCommitHandle = %p\n", mDelayedCommitHandle));
LOGWAYLAND((" mFrameCallback = %p\n", mFrameCallback));
LOGWAYLAND((" mLastCommittedSurface = %p\n", mLastCommittedSurface));
if (!mDrawToWaylandBufferDirectly) {
+ MOZ_ASSERT(mDelayedImageCommits.Length(),
+ "Indirect drawing without any image?");
+
// There's some cached drawings - try to flush them now.
- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
- bool bufferRedraw = !(screenRect == mLastScreenRect);
- RefPtr<gfx::DrawTarget> dt =
- LockWaylandBuffer(screenRect.width, screenRect.height,
- /* needsClear */ bufferRedraw,
- /* full screen update */ bufferRedraw);
+ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
+ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
+
if (dt) {
LOGWAYLAND(("%s [%p] flushed indirect drawing\n", __PRETTY_FUNCTION__,
(void*)this));
DrawDelayedImageCommits(dt, mWaylandBufferDamage);
UnlockWaylandBuffer();
mDrawToWaylandBufferDirectly = true;
- if (bufferRedraw) {
- mLastScreenRect = screenRect;
- }
}
}
@@ -1000,10 +1017,10 @@
mLastCommittedSurface = nullptr;
}
- if (mWaylandBufferFullScreenDamage) {
- LayoutDeviceIntRect rect = mWindow->GetBounds();
- wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height);
- mWaylandBufferFullScreenDamage = false;
+ if (mWholeWindowBufferDamage) {
+ wl_surface_damage(waylandSurface, 0, 0, mBufferScreenRect.width,
+ mBufferScreenRect.height);
+ mWholeWindowBufferDamage = false;
mNeedScaleFactorUpdate = true;
} else {
gint scaleFactor = mWindow->GdkScaleFactor();
@@ -1043,24 +1060,24 @@
#ifdef DEBUG
{
- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
LOGWAYLAND(("%s [%p] lockSize [%d x %d] screenSize [%d x %d]\n",
__PRETTY_FUNCTION__, (void*)this, lockSize.width,
- lockSize.height, screenRect.width, screenRect.height));
+ lockSize.height, mBufferScreenRect.width,
+ mBufferScreenRect.height));
LOGWAYLAND((" mDrawToWaylandBufferDirectly = %d\n",
mDrawToWaylandBufferDirectly));
- LOGWAYLAND((" mWaylandBufferFullScreenDamage = %d\n",
- mWaylandBufferFullScreenDamage));
+ 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 (!mWaylandBufferFullScreenDamage) {
+ if (!mWholeWindowBufferDamage) {
mWaylandBufferDamage.OrWith(aInvalidRegion);
}
UnlockWaylandBuffer();