зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1555899 - [Wayland] Don't wait to fullscreen update as it can block forever, r=jhorak"
- Don't block all drawing until whole screen was painted, clear the screen and allow partial drawing instead. - Detect window resize and allow partial drawing directly to wayland buffer in this case. - Remove backbuffer copy - wait to buffer release instead. Depends on D33910 Differential Revision: https://phabricator.services.mozilla.com/D33911 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6b29386225
Коммит
355ef12f87
|
@ -500,8 +500,7 @@ WindowSurfaceWayland::WindowSurfaceWayland(nsWindow* aWindow)
|
|||
mPendingCommit(false),
|
||||
mWaylandBufferFullScreenDamage(false),
|
||||
mIsMainThread(NS_IsMainThread()),
|
||||
mNeedScaleFactorUpdate(true),
|
||||
mWaitToFullScreenUpdate(true) {
|
||||
mNeedScaleFactorUpdate(true) {
|
||||
for (int i = 0; i < BACK_BUFFER_NUM; i++) mBackupBuffer[i] = nullptr;
|
||||
}
|
||||
|
||||
|
@ -571,37 +570,69 @@ WindowBackBuffer* WindowSurfaceWayland::CreateWaylandBuffer(int aWidth,
|
|||
}
|
||||
|
||||
WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(
|
||||
int aWidth, int aHeight, bool aFullScreenUpdate, bool aNoBackBufferCopy) {
|
||||
int aWidth, int aHeight, bool aFullScreenUpdate) {
|
||||
LOGWAYLAND(("%s [%p] Requested buffer [%d x %d]\n", __PRETTY_FUNCTION__,
|
||||
(void*)this, aWidth, aHeight));
|
||||
|
||||
// There's no buffer created yet, create a new one.
|
||||
if (!mWaylandBuffer) {
|
||||
MOZ_ASSERT(aFullScreenUpdate, "Created new buffer for partial drawing!");
|
||||
LOGWAYLAND(("%s [%p] Created new buffer [%d x %d]\n", __PRETTY_FUNCTION__,
|
||||
(void*)this, aWidth, aHeight));
|
||||
|
||||
mWaylandBuffer = CreateWaylandBuffer(aWidth, aHeight);
|
||||
mWaitToFullScreenUpdate = true;
|
||||
|
||||
LOGWAYLAND((" mWaitToFullScreenUpdate = %d\n", mWaitToFullScreenUpdate));
|
||||
mWaylandBufferFullScreenDamage = true;
|
||||
mNeedScaleFactorUpdate = true;
|
||||
return mWaylandBuffer;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mWaylandBuffer->IsAttached()) {
|
||||
LOGWAYLAND(("%s [%p] Buffer %p is attached, need to find a new one.\n",
|
||||
__PRETTY_FUNCTION__, (void*)this, mWaylandBuffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reuse existing buffer
|
||||
if (!mWaylandBuffer->IsAttached()) {
|
||||
if (!mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) {
|
||||
mWaylandBuffer->Resize(aWidth, aHeight);
|
||||
// There's a chance that scale factor has been changed
|
||||
// when buffer size changed
|
||||
mWaitToFullScreenUpdate = true;
|
||||
}
|
||||
LOGWAYLAND(("%s [%p] Reuse buffer [%d x %d]\n", __PRETTY_FUNCTION__,
|
||||
(void*)this, aWidth, aHeight));
|
||||
LOGWAYLAND((" mWaitToFullScreenUpdate = %d\n", mWaitToFullScreenUpdate));
|
||||
LOGWAYLAND(
|
||||
("%s [%p] Use recent buffer.\n", __PRETTY_FUNCTION__, (void*)this));
|
||||
|
||||
if (mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) {
|
||||
LOGWAYLAND(("%s [%p] Size is ok, use the buffer [%d x %d]\n",
|
||||
__PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
|
||||
return mWaylandBuffer;
|
||||
}
|
||||
|
||||
if (!aFullScreenUpdate) {
|
||||
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));
|
||||
|
||||
mWaylandBuffer->Resize(aWidth, aHeight);
|
||||
// There's a chance that scale factor has been changed
|
||||
// when buffer size changed
|
||||
mWaylandBufferFullScreenDamage = true;
|
||||
mNeedScaleFactorUpdate = true;
|
||||
return mWaylandBuffer;
|
||||
}
|
||||
|
||||
// Front buffer is used by compositor, select a back buffer
|
||||
if (!aFullScreenUpdate) {
|
||||
NS_WARNING(
|
||||
"We can't create a new Wayland buffer for non-fullscreen updates!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Front buffer is used by compositor, select or create a new back buffer
|
||||
int availableBuffer;
|
||||
for (availableBuffer = 0; availableBuffer < BACK_BUFFER_NUM;
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -618,56 +649,38 @@ WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool bufferFlip = mWaylandBuffer->IsMatchingSize(aWidth, aHeight);
|
||||
if (bufferFlip && aNoBackBufferCopy && !aFullScreenUpdate) {
|
||||
LOGWAYLAND(("%s [%p] Delayed hard copy from old buffer [%d x %d]\n",
|
||||
__PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WindowBackBuffer* lastWaylandBuffer = mWaylandBuffer;
|
||||
mWaylandBuffer = mBackupBuffer[availableBuffer];
|
||||
mBackupBuffer[availableBuffer] = lastWaylandBuffer;
|
||||
|
||||
if (bufferFlip) {
|
||||
// Former front buffer has the same size as a requested one.
|
||||
// Gecko may expect a content already drawn on screen so copy
|
||||
// existing data to the new buffer if we don't do fullscreen redraw.
|
||||
if (!aFullScreenUpdate) {
|
||||
LOGWAYLAND(("%s [%p] Copy from old buffer [%d x %d]\n",
|
||||
__PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
|
||||
mWaylandBuffer->SetImageDataFromBuffer(lastWaylandBuffer);
|
||||
}
|
||||
// When buffer switches we need to damage whole screen
|
||||
// (https://bugzilla.redhat.com/show_bug.cgi?id=1418260)
|
||||
mWaylandBufferFullScreenDamage = true;
|
||||
} else {
|
||||
LOGWAYLAND(("%s [%p] Buffer flip new back %p new front %p \n",
|
||||
__PRETTY_FUNCTION__, (void*)this, (void*)lastWaylandBuffer,
|
||||
(void*)mWaylandBuffer));
|
||||
|
||||
mWaylandBufferFullScreenDamage = true;
|
||||
mNeedScaleFactorUpdate = true;
|
||||
|
||||
bool bufferNeedsResize = !mWaylandBuffer->IsMatchingSize(aWidth, aHeight);
|
||||
if (bufferNeedsResize) {
|
||||
LOGWAYLAND(("%s [%p] Resize buffer to [%d x %d]\n", __PRETTY_FUNCTION__,
|
||||
(void*)this, aWidth, aHeight));
|
||||
// Former buffer has different size from the new request. Only resize
|
||||
// the new buffer and leave gecko to render new whole content.
|
||||
mWaylandBuffer->Resize(aWidth, aHeight);
|
||||
mWaitToFullScreenUpdate = true;
|
||||
LOGWAYLAND((" mWaitToFullScreenUpdate = %d\n", mWaitToFullScreenUpdate));
|
||||
}
|
||||
|
||||
return mWaylandBuffer;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockWaylandBuffer(
|
||||
int aWidth, int aHeight, bool aClearBuffer, bool aFullScreenUpdate,
|
||||
bool aNoBackBufferCopy) {
|
||||
WindowBackBuffer* buffer = GetWaylandBufferToDraw(
|
||||
aWidth, aHeight, aFullScreenUpdate, aNoBackBufferCopy);
|
||||
int aWidth, int aHeight, bool aClearBuffer, bool aFullScreenUpdate) {
|
||||
WindowBackBuffer* buffer =
|
||||
GetWaylandBufferToDraw(aWidth, aHeight, aFullScreenUpdate);
|
||||
|
||||
LOGWAYLAND(("%s [%p] Got buffer %p\n", __PRETTY_FUNCTION__, (void*)this,
|
||||
(void*)buffer));
|
||||
|
||||
if (!buffer) {
|
||||
if (!aNoBackBufferCopy) {
|
||||
NS_WARNING(
|
||||
"WindowSurfaceWayland::LockWaylandBuffer(): No buffer available");
|
||||
}
|
||||
NS_WARNING(
|
||||
"WindowSurfaceWayland::LockWaylandBuffer(): No buffer available");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -769,23 +782,26 @@ already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::Lock(
|
|||
LOGWAYLAND((" needsClear = %d\n", needsClear));
|
||||
LOGWAYLAND(
|
||||
(" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
|
||||
LOGWAYLAND((" mWaitToFullScreenUpdate = %d\n", mWaitToFullScreenUpdate));
|
||||
|
||||
// Allow full screen allocation and clear
|
||||
// when window size changed.
|
||||
bool bufferRedraw = !(screenRect == mLastScreenRect);
|
||||
if (bufferRedraw) {
|
||||
mDrawToWaylandBufferDirectly = true;
|
||||
needsClear = true;
|
||||
}
|
||||
|
||||
if (mDrawToWaylandBufferDirectly) {
|
||||
// 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, /* aNoBackBufferCopy */ true);
|
||||
RefPtr<gfx::DrawTarget> dt =
|
||||
LockWaylandBuffer(screenRect.width, screenRect.height, needsClear,
|
||||
/* aFullScreenUpdate */ true);
|
||||
if (dt) {
|
||||
// When we have a request to update whole screen at once
|
||||
// (surface was created, resized or changed somehow)
|
||||
// we also need update scale factor of the screen.
|
||||
if (mWaitToFullScreenUpdate) {
|
||||
mWaitToFullScreenUpdate = false;
|
||||
mNeedScaleFactorUpdate = true;
|
||||
if (bufferRedraw) {
|
||||
mLastScreenRect = screenRect;
|
||||
}
|
||||
return dt.forget();
|
||||
}
|
||||
|
@ -795,7 +811,7 @@ already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::Lock(
|
|||
mDrawToWaylandBufferDirectly = false;
|
||||
}
|
||||
|
||||
LOGWAYLAND((" Indirect drawing!\n"));
|
||||
LOGWAYLAND((" Indirect drawing.\n"));
|
||||
return LockImageSurface(lockSize);
|
||||
}
|
||||
|
||||
|
@ -864,19 +880,28 @@ bool WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer(
|
|||
return false;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
|
||||
screenRect.width, screenRect.height, /* needs clear*/ false,
|
||||
/* fullscreenDrawing */ false, /* aNoBackBufferCopy */ true);
|
||||
// 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);
|
||||
if (dt) {
|
||||
LOGWAYLAND(
|
||||
(" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n",
|
||||
mDelayedImageCommits.Length() + 1));
|
||||
|
||||
// Draw any delayed image commits first
|
||||
DrawDelayedImageCommits(dt, aWaylandBufferDamage);
|
||||
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",
|
||||
|
@ -912,7 +937,6 @@ void WindowSurfaceWayland::CommitWaylandBuffer() {
|
|||
MOZ_ASSERT(mPendingCommit, "Committing empty surface!");
|
||||
|
||||
LOGWAYLAND(("%s [%p]\n", __PRETTY_FUNCTION__, (void*)this));
|
||||
LOGWAYLAND((" mWaitToFullScreenUpdate = %d\n", mWaitToFullScreenUpdate));
|
||||
LOGWAYLAND(
|
||||
(" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
|
||||
LOGWAYLAND((" mWaylandBufferFullScreenDamage = %d\n",
|
||||
|
@ -921,24 +945,23 @@ void WindowSurfaceWayland::CommitWaylandBuffer() {
|
|||
LOGWAYLAND((" mFrameCallback = %p\n", mFrameCallback));
|
||||
LOGWAYLAND((" mLastCommittedSurface = %p\n", mLastCommittedSurface));
|
||||
|
||||
if (mWaitToFullScreenUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mDrawToWaylandBufferDirectly) {
|
||||
// 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 */ false,
|
||||
/* fullscreenInvalidate */ false,
|
||||
/* aNoBackBufferCopy */ true);
|
||||
/* needsClear */ bufferRedraw,
|
||||
/* full screen update */ bufferRedraw);
|
||||
if (dt) {
|
||||
LOGWAYLAND(("%s [%p] flushed indirect drawing\n", __PRETTY_FUNCTION__,
|
||||
(void*)this));
|
||||
DrawDelayedImageCommits(dt, mWaylandBufferDamage);
|
||||
UnlockWaylandBuffer();
|
||||
mDrawToWaylandBufferDirectly = true;
|
||||
if (bufferRedraw) {
|
||||
mLastScreenRect = screenRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1058,7 @@ void WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) {
|
|||
|
||||
LOGWAYLAND(("%s [%p] lockSize [%d x %d] screenSize [%d x %d]\n",
|
||||
__PRETTY_FUNCTION__, (void*)this, lockSize.width,
|
||||
lockSize.height, screenRect.width, lockSize.height));
|
||||
lockSize.height, screenRect.width, screenRect.height));
|
||||
LOGWAYLAND((" mDrawToWaylandBufferDirectly = %d\n",
|
||||
mDrawToWaylandBufferDirectly));
|
||||
LOGWAYLAND((" mWaylandBufferFullScreenDamage = %d\n",
|
||||
|
|
|
@ -182,13 +182,11 @@ class WindowSurfaceWayland : public WindowSurface {
|
|||
private:
|
||||
WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight);
|
||||
WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight,
|
||||
bool aFullScreenUpdate,
|
||||
bool aNoBackBufferCopy);
|
||||
bool aFullScreenUpdate);
|
||||
|
||||
already_AddRefed<gfx::DrawTarget> LockWaylandBuffer(int aWidth, int aHeight,
|
||||
bool aClearBuffer,
|
||||
bool aFullScreenUpdate,
|
||||
bool aNoBackBufferCopy);
|
||||
bool aFullScreenUpdate);
|
||||
void UnlockWaylandBuffer();
|
||||
|
||||
already_AddRefed<gfx::DrawTarget> LockImageSurface(
|
||||
|
@ -204,6 +202,7 @@ class WindowSurfaceWayland : public WindowSurface {
|
|||
|
||||
// TODO: Do we need to hold a reference to nsWindow object?
|
||||
nsWindow* mWindow;
|
||||
LayoutDeviceIntRect mLastScreenRect;
|
||||
nsWaylandDisplay* mWaylandDisplay;
|
||||
WindowBackBuffer* mWaylandBuffer;
|
||||
LayoutDeviceIntRegion mWaylandBufferDamage;
|
||||
|
@ -219,7 +218,6 @@ class WindowSurfaceWayland : public WindowSurface {
|
|||
bool mWaylandBufferFullScreenDamage;
|
||||
bool mIsMainThread;
|
||||
bool mNeedScaleFactorUpdate;
|
||||
bool mWaitToFullScreenUpdate;
|
||||
|
||||
static bool UseDMABufBackend();
|
||||
static bool mUseDMABufInitialized;
|
||||
|
|
Загрузка…
Ссылка в новой задаче