20c032f2ed
mozilla-1567434, mozilla-1573813, mozilla-1574036, mozilla-1576268). - Enable multiprocess compilation.
426 lines
17 KiB
Diff
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();
|
|
|