summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firefox.spec7
-rw-r--r--mozilla-1581748.patch574
2 files changed, 580 insertions, 1 deletions
diff --git a/firefox.spec b/firefox.spec
index 88f5fc6..3e96df4 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -94,7 +94,7 @@ ExcludeArch: ppc64le
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 69.0
-Release: 6%{?pre_tag}%{?dist}
+Release: 7%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz
@@ -168,6 +168,7 @@ Patch584: mozilla-1579794-2.patch
Patch585: mozilla-1579849.patch
Patch586: mozilla-1579823.patch
Patch587: mozilla-1580152.patch
+Patch588: mozilla-1581748.patch
# PGO/LTO patches
Patch600: pgo.patch
@@ -388,6 +389,7 @@ This package contains results of tests executed during build.
%patch422 -p1 -b .1580174-webrtc-popup
%patch586 -p1 -b .mozilla-1579823
%patch587 -p1 -b .mozilla-1580152
+%patch588 -p1 -b .mozilla-1581748
# PGO patches
%patch600 -p1 -b .pgo
@@ -964,6 +966,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Tue Sep 17 2019 Martin Stransky <stransky@redhat.com> - 69.0-7
+- Added fixes for mozbz#1581748
+
* Mon Sep 16 2019 Martin Stransky <stransky@redhat.com> - 69.0-6
- Added fixes for mozbz#1579823, mozbz#1580152
diff --git a/mozilla-1581748.patch b/mozilla-1581748.patch
new file mode 100644
index 0000000..4fbffa8
--- /dev/null
+++ b/mozilla-1581748.patch
@@ -0,0 +1,574 @@
+diff -up firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1581748 firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp
+--- firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1581748 2019-09-17 13:19:47.190908284 +0200
++++ firefox-69.0/widget/gtk/WindowSurfaceWayland.cpp 2019-09-17 13:19:47.196908262 +0200
+@@ -32,7 +32,7 @@ extern mozilla::LazyLogModule gWidgetWay
+ # define LOGWAYLAND(args)
+ #endif /* MOZ_LOGGING */
+
+-// Maximal compositin timeout it miliseconds
++// Maximal compositing timeout it miliseconds
+ #define COMPOSITING_TIMEOUT 200
+
+ namespace mozilla {
+@@ -513,13 +513,15 @@ WindowSurfaceWayland::WindowSurfaceWayla
+ mDelayedCommitHandle(nullptr),
+ mLastCommitTime(0),
+ mDrawToWaylandBufferDirectly(true),
++ mCanSwitchWaylandBuffer(true),
+ 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 = 0;
++
+ }
+
+ WindowSurfaceWayland::~WindowSurfaceWayland() {
+@@ -591,8 +593,6 @@ WindowBackBuffer* WindowSurfaceWayland::
+
+ // There's no buffer created yet, create a new one.
+ if (!mWaylandBuffer) {
+- MOZ_ASSERT(aCanSwitchBuffer && mWholeWindowBufferDamage,
+- "Created new buffer for partial drawing!");
+ LOGWAYLAND((" Created new buffer [%d x %d]\n", mBufferScreenRect.width,
+ mBufferScreenRect.height));
+
+@@ -682,9 +682,8 @@ WindowBackBuffer* WindowSurfaceWayland::
+ return mWaylandBuffer;
+ }
+
+-already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockWaylandBuffer(
+- bool aCanSwitchBuffer) {
+- WindowBackBuffer* buffer = GetWaylandBufferToDraw(aCanSwitchBuffer);
++already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockWaylandBuffer() {
++ WindowBackBuffer* buffer = GetWaylandBufferToDraw(mCanSwitchWaylandBuffer);
+
+ LOGWAYLAND(("WindowSurfaceWayland::LockWaylandBuffer [%p] Got buffer %p\n",
+ (void*)this, (void*)buffer));
+@@ -698,7 +697,9 @@ already_AddRefed<gfx::DrawTarget> Window
+ return nullptr;
+ }
+
+- if (mBufferNeedsClear && mWholeWindowBufferDamage) {
++ mCanSwitchWaylandBuffer = false;
++
++ if (mBufferNeedsClear) {
+ buffer->Clear();
+ mBufferNeedsClear = false;
+ }
+@@ -728,40 +729,30 @@ already_AddRefed<gfx::DrawTarget> Window
+ WindowBackBuffer::GetSurfaceFormat());
+ }
+
+-static bool IsWindowFullScreenUpdate(LayoutDeviceIntRect& screenRect,
+- const LayoutDeviceIntRegion& aRegion) {
+- if (aRegion.GetNumRects() > 1) return false;
+-
+- IntRect rect = aRegion.RectIter().Get().ToUnknownRect();
+- return (rect.x == 0 && rect.y == 0 && screenRect.width == rect.width &&
+- screenRect.height == rect.height);
++static bool IsWindowFullScreenUpdate(
++ LayoutDeviceIntRect& aScreenRect,
++ const LayoutDeviceIntRegion& aUpdatedRegion) {
++ if (aUpdatedRegion.GetNumRects() > 1) return false;
++
++ IntRect rect = aUpdatedRegion.RectIter().Get().ToUnknownRect();
++ return (rect.x == 0 && rect.y == 0 && aScreenRect.width == rect.width &&
++ aScreenRect.height == rect.height);
+ }
+
+-static bool IsPopupFullScreenUpdate(LayoutDeviceIntRect& screenRect,
+- const LayoutDeviceIntRegion& aRegion) {
++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 (aRegion.GetNumRects() > 2) return false;
++ if (aUpdatedRegion.GetNumRects() > 2) return false;
+
+- IntRect lockSize = aRegion.GetBounds().ToUnknownRect();
++ gfx::IntRect lockSize = aUpdatedRegion.GetBounds().ToUnknownRect();
+ return (lockSize.x == 0 && lockSize.y == 0 &&
+- screenRect.width == lockSize.width &&
+- screenRect.height == lockSize.height);
++ aScreenRect.width == lockSize.width &&
++ aScreenRect.height == lockSize.height);
+ }
+
+-/*
+- 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 - 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());
+@@ -777,22 +768,31 @@ already_AddRefed<gfx::DrawTarget> Window
+ LayoutDeviceIntRect lockedScreenRect = mWindow->GetBounds();
+ 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);
+-
+- // 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) {
++ bool windowRedraw = isTransparentPopup
++ ? IsPopupFullScreenUpdate(lockedScreenRect, aRegion)
++ : IsWindowFullScreenUpdate(lockedScreenRect, aRegion);
++ if (windowRedraw) {
++ // 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.
+ mBufferNeedsClear =
+ mWindow->WaylandSurfaceNeedsClear() || isTransparentPopup;
++
++ // Store info that we can switch WaylandBuffer when we flush
++ // mImageSurface / mDelayedImageCommits. Don't clear it - it's cleared
++ // at LockWaylandBuffer() when we actualy switch the buffer.
++ mCanSwitchWaylandBuffer = windowRedraw;
++
++ // We do full buffer repaint so clear our cached drawings.
++ mDelayedImageCommits.Clear();
++ mWaylandBufferDamage.SetEmpty();
++
++ // Also do scale factor update for whole window updates just to be sure.
++ mNeedScaleFactorUpdate = true;
+ }
+
+ LOGWAYLAND(
+@@ -808,7 +808,7 @@ already_AddRefed<gfx::DrawTarget> Window
+ LOGWAYLAND((" IsWindowFullScreenUpdate = %d\n",
+ IsWindowFullScreenUpdate(lockedScreenRect, aRegion)));
+ LOGWAYLAND((" mBufferNeedsClear = %d\n", mBufferNeedsClear));
+- LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
++ LOGWAYLAND((" windowRedraw = %d\n", windowRedraw));
+
+ #if MOZ_LOGGING
+ if (!(mBufferScreenRect == lockedScreenRect)) {
+@@ -822,8 +822,9 @@ already_AddRefed<gfx::DrawTarget> Window
+ // We can't commit them any more as they're for former window size, so
+ // scratch them.
+ mDelayedImageCommits.Clear();
++ mWaylandBufferDamage.SetEmpty();
+
+- if (!mWholeWindowBufferDamage) {
++ if (!windowRedraw) {
+ 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
+@@ -833,52 +834,56 @@ already_AddRefed<gfx::DrawTarget> Window
+ mBufferScreenRect = lockedScreenRect;
+ }
+
+- 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();
++ mDrawToWaylandBufferDirectly =
++ (windowRedraw || mRenderingCacheMode != CACHE_ALL);
+
+- RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
+- /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
++ if (mDrawToWaylandBufferDirectly) {
++ LOGWAYLAND((" Direct drawing\n"));
++ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer();
+ if (dt) {
++ if (!windowRedraw) {
++ DrawDelayedImageCommits(dt, mWaylandBufferDamage);
++ }
+ return dt.forget();
+ }
+ }
+
+- // 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.
++ // Any caching is disabled and we don't have any back buffer available.
++ if (mRenderingCacheMode == CACHE_NONE) {
++ return nullptr;
++ }
++
++ // We do indirect drawing because there isn't any front buffer available.
++ // Do indirect drawing to mImageSurface which is commited to wayland
++ // wl_buffer by DrawDelayedImageCommits() later.
+ mDrawToWaylandBufferDirectly = false;
+
+ LOGWAYLAND((" Indirect drawing.\n"));
+ return LockImageSurface(gfx::IntSize(lockSize.XMost(), lockSize.YMost()));
+ }
+
++bool WindowImageSurface::OverlapsSurface(
++ class WindowImageSurface& aBottomSurface) {
++ return mUpdateRegion.Contains(aBottomSurface.mUpdateRegion);
++}
++
+ void WindowImageSurface::Draw(gfx::SourceSurface* aSurface,
+ gfx::DrawTarget* aDest,
+ const LayoutDeviceIntRegion& aRegion) {
+- uint32_t numRects = aRegion.GetNumRects();
+- if (numRects != 1) {
+- AutoTArray<IntRect, 32> rects;
+- rects.SetCapacity(numRects);
+- for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
+- rects.AppendElement(iter.Get().ToUnknownRect());
+- }
+- aDest->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
+- }
+-
++#ifdef MOZ_LOGGING
+ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
+- gfx::Rect rect(bounds);
+- aDest->DrawSurface(aSurface, rect, rect);
++ 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
+
+- if (numRects != 1) {
+- aDest->PopClip();
++ 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);
+ }
+ }
+
+@@ -896,6 +901,18 @@ WindowImageSurface::WindowImageSurface(
+ mImageSurface->Format());
+ }
+
++void WindowSurfaceWayland::DrawDelayedImageCommits(
++ gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage) {
++ LOGWAYLAND(
++ ("WindowSurfaceWayland::DrawDelayedImageCommits [%p]\n", (void*)this));
++ MOZ_ASSERT(mDelayedImageCommits.Length() > 0, "Nothing to draw?");
++
++ for (unsigned int i = 0; i < mDelayedImageCommits.Length(); i++) {
++ mDelayedImageCommits[i].Draw(aDrawTarget, aWaylandBufferDamage);
++ }
++ mDelayedImageCommits.Clear();
++}
++
+ void WindowSurfaceWayland::CacheImageSurface(
+ const LayoutDeviceIntRegion& aRegion) {
+ #ifdef MOZ_LOGGING
+@@ -906,8 +923,26 @@ void WindowSurfaceWayland::CacheImageSur
+ bounds.width, bounds.height));
+ #endif
+
+- mDelayedImageCommits.AppendElement(
+- WindowImageSurface(mImageSurface, aRegion));
++ WindowImageSurface surf = WindowImageSurface(mImageSurface, aRegion);
++
++ if (mDelayedImageCommits.Length()) {
++ int lastSurf = mDelayedImageCommits.Length() - 1;
++ if (surf.OverlapsSurface(mDelayedImageCommits[lastSurf])) {
++#ifdef MOZ_LOGGING
++ {
++ gfx::IntRect size = mDelayedImageCommits[lastSurf]
++ .GetUpdateRegion()
++ ->GetBounds()
++ .ToUnknownRect();
++ LOGWAYLAND((" removing [ %d, %d] -> [%d x %d]\n", size.x, size.y,
++ size.width, size.height));
++ }
++#endif
++ mDelayedImageCommits.RemoveElementAt(lastSurf);
++ }
++ }
++
++ mDelayedImageCommits.AppendElement(surf);
+ // mImageSurface is owned by mDelayedImageCommits
+ mImageSurface = nullptr;
+
+@@ -915,17 +950,6 @@ void WindowSurfaceWayland::CacheImageSur
+ (" 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::CommitImageCacheToWaylandBuffer() {
+ if (!mDelayedImageCommits.Length()) {
+ return false;
+@@ -933,8 +957,7 @@ bool WindowSurfaceWayland::CommitImageCa
+
+ MOZ_ASSERT(!mDrawToWaylandBufferDirectly);
+
+- RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
+- /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
++ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer();
+ if (!dt) {
+ return false;
+ }
+@@ -942,7 +965,6 @@ bool WindowSurfaceWayland::CommitImageCa
+ LOGWAYLAND((" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n",
+ long(mDelayedImageCommits.Length())));
+
+- // Draw any delayed image commits first
+ DrawDelayedImageCommits(dt, mWaylandBufferDamage);
+ UnlockWaylandBuffer();
+
+@@ -967,7 +989,7 @@ void WindowSurfaceWayland::CommitWayland
+ LOGWAYLAND(("WindowSurfaceWayland::CommitWaylandBuffer [%p]\n", (void*)this));
+ LOGWAYLAND(
+ (" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
+- LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
++ LOGWAYLAND((" mCanSwitchWaylandBuffer = %d\n", mCanSwitchWaylandBuffer));
+ LOGWAYLAND((" mDelayedCommitHandle = %p\n", mDelayedCommitHandle));
+ LOGWAYLAND((" mFrameCallback = %p\n", mFrameCallback));
+ LOGWAYLAND((" mLastCommittedSurface = %p\n", mLastCommittedSurface));
+@@ -1030,20 +1052,11 @@ void WindowSurfaceWayland::CommitWayland
+ 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);
+- }
++ 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
+@@ -1062,9 +1075,9 @@ void WindowSurfaceWayland::CommitWayland
+ mLastCommittedSurface = waylandSurface;
+ mLastCommitTime = g_get_monotonic_time() / 1000;
+
+- // Ask wl_display to start events synchronization. We're going wait
++ // Ask wl_display to start events synchronization. We're going to wait
+ // until all events are processed before next WindowSurfaceWayland::Lock()
+- // as we need freed wl_buffer there.
++ // as we hope for free wl_buffer there.
+ mWaylandDisplay->SyncBegin();
+
+ // There's no pending commit, all changes are sent to compositor.
+@@ -1074,9 +1087,6 @@ void WindowSurfaceWayland::CommitWayland
+ void WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) {
+ MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
+
+- // Flush all waiting events explicitly as we need
+- // mWaylandDisplay->FlushEventQueue();
+-
+ #ifdef MOZ_LOGGING
+ {
+ gfx::IntRect lockSize = aInvalidRegion.GetBounds().ToUnknownRect();
+@@ -1087,17 +1097,12 @@ void WindowSurfaceWayland::Commit(const
+ 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);
+- }
++ mWaylandBufferDamage.OrWith(aInvalidRegion);
+ UnlockWaylandBuffer();
+ mBufferPendingCommit = true;
+ } else {
+diff -up firefox-69.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1581748 firefox-69.0/widget/gtk/WindowSurfaceWayland.h
+--- firefox-69.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1581748 2019-09-17 13:19:47.191908280 +0200
++++ firefox-69.0/widget/gtk/WindowSurfaceWayland.h 2019-09-17 13:19:47.197908258 +0200
+@@ -161,6 +161,10 @@ class WindowImageSurface {
+ WindowImageSurface(gfxImageSurface* aImageSurface,
+ const LayoutDeviceIntRegion& aUpdateRegion);
+
++ bool OverlapsSurface(class WindowImageSurface& aBottomSurface);
++
++ const LayoutDeviceIntRegion* GetUpdateRegion() { return &mUpdateRegion; };
++
+ private:
+ RefPtr<gfx::SourceSurface> mSurface;
+ RefPtr<gfxImageSurface> mImageSurface;
+@@ -174,20 +178,59 @@ class WindowSurfaceWayland : public Wind
+ explicit WindowSurfaceWayland(nsWindow* aWindow);
+ ~WindowSurfaceWayland();
+
++ // Lock() / Commit() are called by gecko when Firefox
++ // wants to display something. Lock() returns a DrawTarget
++ // where gecko paints. When gecko is done it calls Commit()
++ // and we try to send the DrawTarget (backed by wl_buffer)
++ // to wayland compositor.
++ //
++ // If we fail (wayland compositor is busy,
++ // wl_surface is not created yet) we queue the painting
++ // and we send it to wayland compositor in FrameCallbackHandler()/
++ // DelayedCommitHandler/CommitWaylandBuffer().
+ already_AddRefed<gfx::DrawTarget> Lock(
+ const LayoutDeviceIntRegion& aRegion) override;
+ void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final;
++
++ // It's called from wayland compositor when there's the right
++ // time to send wl_buffer to display. It's no-op if there's no
++ // queued commits.
+ void FrameCallbackHandler();
++
++ // When a new window is created we may not have a valid wl_surface
++ // for drawing (Gtk haven't created it yet). All commits are queued
++ // and DelayedCommitHandler() is called by timer when wl_surface is ready
++ // for drawing.
+ void DelayedCommitHandler();
++
++ // Try to commit all queued drawings to Wayland compositor. This is usually
++ // called from other routines but can be used to explicitly flush
++ // all drawings as we do when wl_buffer is released
++ // (see WindowBackBufferShm::Detach() for instance).
+ void CommitWaylandBuffer();
+
+ nsWaylandDisplay* GetWaylandDisplay() { return mWaylandDisplay; };
+
++ // Image cache mode can be set by widget.wayland_cache_mode
++ typedef enum {
++ // Cache and clip all drawings, default. It's slowest
++ // but also without any rendered artifacts.
++ CACHE_ALL = 0,
++ // Cache drawing only when back buffer is missing. May produce
++ // some rendering artifacts and flickering when partial screen update
++ // is rendered.
++ CACHE_MISSING = 1,
++ // Don't cache anything, draw only when back buffer is available.
++ // Suitable for fullscreen content only like fullscreen video playback and
++ // may work well with dmabuf backend.
++ CACHE_NONE = 2
++ } RenderingCacheMode;
++
+ private:
+ WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight);
+ WindowBackBuffer* GetWaylandBufferToDraw(bool aCanSwitchBuffer);
+
+- already_AddRefed<gfx::DrawTarget> LockWaylandBuffer(bool aCanSwitchBuffer);
++ already_AddRefed<gfx::DrawTarget> LockWaylandBuffer();
+ void UnlockWaylandBuffer();
+
+ already_AddRefed<gfx::DrawTarget> LockImageSurface(
+@@ -206,23 +249,71 @@ class WindowSurfaceWayland : public Wind
+ // mBufferScreenRect is window size when our wayland buffer was allocated.
+ LayoutDeviceIntRect mBufferScreenRect;
+ nsWaylandDisplay* mWaylandDisplay;
++
++ // Actual buffer (backed by wl_buffer) where all drawings go into.
++ // Drawn areas are stored at mWaylandBufferDamage and if there's
++ // any uncommited drawings which needs to be send to wayland compositor
++ // the mBufferPendingCommit is set.
+ WindowBackBuffer* mWaylandBuffer;
+- LayoutDeviceIntRegion mWaylandBufferDamage;
+ WindowBackBuffer* mBackupBuffer[BACK_BUFFER_NUM];
++ LayoutDeviceIntRegion mWaylandBufferDamage;
++
++ // After every commit to wayland compositor a frame callback is requested.
++ // Any next commit to wayland compositor will happen when frame callback
++ // comes from wayland compositor back as it's the best time to do the commit.
+ wl_callback* mFrameCallback;
+ wl_surface* mLastCommittedSurface;
++
++ // Registered reference to pending DelayedCommitHandler() call.
+ WindowSurfaceWayland** mDelayedCommitHandle;
++
++ // Cached drawings. If we can't get WaylandBuffer (wl_buffer) at
++ // WindowSurfaceWayland::Lock() we direct gecko rendering to
++ // mImageSurface.
++ // If we can't get WaylandBuffer at WindowSurfaceWayland::Commit()
++ // time, mImageSurface is moved to mDelayedImageCommits which
++ // holds all cached drawings.
++ // mDelayedImageCommits can be drawn by FrameCallbackHandler(),
++ // DelayedCommitHandler() or when WaylandBuffer is detached.
+ RefPtr<gfxImageSurface> mImageSurface;
+ AutoTArray<WindowImageSurface, 30> mDelayedImageCommits;
++
+ int64_t mLastCommitTime;
++
++ // Indicates that we don't have any cached drawings at mDelayedImageCommits
++ // and WindowSurfaceWayland::Lock() returned WaylandBuffer to gecko
++ // to draw into.
+ bool mDrawToWaylandBufferDirectly;
++
++ // Set when our cached drawings (mDelayedImageCommits) contains
++ // full screen damage. That means we can safely switch WaylandBuffer
++ // at LockWaylandBuffer().
++ bool mCanSwitchWaylandBuffer;
++
++ // Set when actual WaylandBuffer contains drawings which are not send to
++ // wayland compositor yet.
+ bool mBufferPendingCommit;
++
++ // We can't send WaylandBuffer (wl_buffer) to compositor when gecko
++ // is rendering into it (i.e. between WindowSurfaceWayland::Lock() /
++ // WindowSurfaceWayland::Commit()).
++ // Thus we use mBufferCommitAllowed to disable commit by callbacks
++ // (FrameCallbackHandler(), DelayedCommitHandler())
+ bool mBufferCommitAllowed;
+- bool mWholeWindowBufferDamage;
++
++ // We need to clear WaylandBuffer when entire transparent window is repainted.
++ // This typically apply to popup windows.
+ bool mBufferNeedsClear;
++
+ bool mIsMainThread;
++
++ // When new WaylandBuffer (wl_buffer) is send to wayland compositor
++ // (buffer switch or resize) we also need to set its scale factor.
+ bool mNeedScaleFactorUpdate;
+
++ // Image caching strategy, see RenderingCacheMode for details.
++ RenderingCacheMode mRenderingCacheMode;
++
+ static bool UseDMABufBackend();
+ static bool mUseDMABufInitialized;
+ static bool mUseDMABuf;
bgstack15