From 36345da5139b4ffba1e6529abf1240fc80b42c1d Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Wed, 11 Sep 2019 08:35:24 +0200 Subject: [PATCH] Added fix for mozbz#1579794 - Flickering on video playback on 4k/HiDPI displays --- firefox.spec | 10 ++- mozilla-1579794-1.patch | 134 ++++++++++++++++++++++++++++++++ mozilla-1579794-2.patch | 166 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 mozilla-1579794-1.patch create mode 100644 mozilla-1579794-2.patch diff --git a/firefox.spec b/firefox.spec index 99767c0..e23bf3b 100644 --- a/firefox.spec +++ b/firefox.spec @@ -94,7 +94,7 @@ ExcludeArch: ppc64le Summary: Mozilla Firefox Web browser Name: firefox Version: 69.0 -Release: 3%{?pre_tag}%{?dist} +Release: 4%{?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 @@ -162,6 +162,8 @@ Patch579: mozilla-1567434-2.patch Patch580: mozilla-1573813.patch Patch581: mozilla-1574036.patch Patch582: mozilla-1576268.patch +Patch583: mozilla-1579794-1.patch +Patch584: mozilla-1579794-2.patch # PGO/LTO patches Patch600: pgo.patch @@ -376,6 +378,8 @@ This package contains results of tests executed during build. %patch580 -p1 -b .mozilla-1573813 %patch581 -p1 -b .mozilla-1574036 %patch582 -p1 -b .mozilla-1576268 +%patch583 -p1 -b .mozilla-1579794-1 +%patch584 -p1 -b .mozilla-1579794-2 # PGO patches %patch600 -p1 -b .pgo @@ -952,6 +956,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Wed Sep 11 2019 Martin Stransky - 69.0-4 +- Added fix for mozbz#1579794 - Flickering on video playback on + 4k/HiDPI displays. + * Mon Sep 9 2019 Martin Stransky - 69.0-3 - Added fix for mozbz#1579023 diff --git a/mozilla-1579794-1.patch b/mozilla-1579794-1.patch new file mode 100644 index 0000000..60c8cab --- /dev/null +++ b/mozilla-1579794-1.patch @@ -0,0 +1,134 @@ +diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h +--- a/widget/gtk/WindowSurfaceWayland.h ++++ b/widget/gtk/WindowSurfaceWayland.h +@@ -154,11 +154,12 @@ + void Draw(gfx::DrawTarget* aDest, + LayoutDeviceIntRegion& aWaylandBufferDamage); + +- WindowImageSurface(gfx::SourceSurface* aSurface, ++ WindowImageSurface(gfxImageSurface* aImageSurface, + const LayoutDeviceIntRegion& aUpdateRegion); + + private: + RefPtr mSurface; ++ RefPtr mImageSurface; + const LayoutDeviceIntRegion mUpdateRegion; + }; + +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -890,8 +890,12 @@ + } + + WindowImageSurface::WindowImageSurface( +- gfx::SourceSurface* aSurface, const LayoutDeviceIntRegion& aUpdateRegion) +- : mSurface(aSurface), mUpdateRegion(aUpdateRegion){}; ++ gfxImageSurface* aImageSurface, const LayoutDeviceIntRegion& aUpdateRegion) ++ : mImageSurface(aImageSurface), mUpdateRegion(aUpdateRegion) { ++ mSurface = gfx::Factory::CreateSourceSurfaceForCairoSurface( ++ mImageSurface->CairoSurface(), mImageSurface->GetSize(), ++ mImageSurface->Format()); ++} + + void WindowSurfaceWayland::DrawDelayedImageCommits( + gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage) { +@@ -915,36 +919,24 @@ + LOGWAYLAND(("%s [%p] screenSize [%d x %d]\n", __PRETTY_FUNCTION__, + (void*)this, mBufferScreenRect.width, mBufferScreenRect.height)); + +- RefPtr surf = +- gfx::Factory::CreateSourceSurfaceForCairoSurface( +- mImageSurface->CairoSurface(), mImageSurface->GetSize(), +- mImageSurface->Format()); +- if (!surf) { +- NS_WARNING("Failed to create source cairo surface!"); +- return false; +- } ++ mDelayedImageCommits.AppendElement( ++ WindowImageSurface(mImageSurface, aRegion)); ++ // mImageSurface is owned by mDelayedImageCommits ++ mImageSurface = nullptr; + + RefPtr dt = LockWaylandBuffer( + /* aCanSwitchBuffer */ mWholeWindowBufferDamage); +- if (dt) { +- LOGWAYLAND( +- (" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n", +- long(mDelayedImageCommits.Length() + 1))); +- +- // 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(); +- } else { +- mDelayedImageCommits.AppendElement(WindowImageSurface(surf, aRegion)); +- LOGWAYLAND((" Added WindowImageSurfaces, cached surfaces %ld\n", +- long(mDelayedImageCommits.Length()))); ++ if (!dt) { + return false; + } + ++ LOGWAYLAND((" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n", ++ long(mDelayedImageCommits.Length() + 1))); ++ ++ // Draw any delayed image commits first ++ DrawDelayedImageCommits(dt, aWaylandBufferDamage); ++ UnlockWaylandBuffer(); ++ + return true; + } + +@@ -980,23 +972,6 @@ + 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. +- RefPtr dt = LockWaylandBuffer( +- /* aCanSwitchBuffer */ mWholeWindowBufferDamage); +- +- if (dt) { +- LOGWAYLAND(("%s [%p] flushed indirect drawing\n", __PRETTY_FUNCTION__, +- (void*)this)); +- DrawDelayedImageCommits(dt, mWaylandBufferDamage); +- UnlockWaylandBuffer(); +- mDrawToWaylandBufferDirectly = true; +- } +- } +- + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (!waylandSurface) { + LOGWAYLAND(("%s [%p] mWindow->GetWaylandSurface() failed, delay commit.\n", +@@ -1105,6 +1080,7 @@ + mWaylandBufferDamage.OrWith(aInvalidRegion); + } + UnlockWaylandBuffer(); ++ mPendingCommit = true; + } else { + MOZ_ASSERT(!mWaylandBuffer->IsLocked(), + "Drawing to already locked buffer?"); +@@ -1112,12 +1088,13 @@ + mWaylandBufferDamage)) { + // Our cached drawing is flushed, we can draw fullscreen again. + mDrawToWaylandBufferDirectly = true; ++ mPendingCommit = true; + } + } + +- // We're ready to commit. +- mPendingCommit = true; +- CommitWaylandBuffer(); ++ if (mPendingCommit) { ++ CommitWaylandBuffer(); ++ } + } + + void WindowSurfaceWayland::FrameCallbackHandler() { + diff --git a/mozilla-1579794-2.patch b/mozilla-1579794-2.patch new file mode 100644 index 0000000..a8c249b --- /dev/null +++ b/mozilla-1579794-2.patch @@ -0,0 +1,166 @@ +diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h +--- a/widget/gtk/WindowSurfaceWayland.h ++++ b/widget/gtk/WindowSurfaceWayland.h +@@ -204,7 +204,6 @@ + const LayoutDeviceIntRegion& aRegion, + LayoutDeviceIntRegion& aWaylandBufferDamage); + void CommitWaylandBuffer(); +- void CalcRectScale(LayoutDeviceIntRect& aRect, int scale); + + void DrawDelayedImageCommits(gfx::DrawTarget* aDrawTarget, + LayoutDeviceIntRegion& aWaylandBufferDamage); +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -951,16 +951,6 @@ + } + } + +-void WindowSurfaceWayland::CalcRectScale(LayoutDeviceIntRect& aRect, +- int aScale) { +- aRect.x = aRect.x / aScale; +- aRect.y = aRect.y / aScale; +- +- // We don't need exact damage size - just safely cover the round errors. +- aRect.width = (aRect.width / aScale) + 2; +- aRect.height = (aRect.height / aScale) + 2; +-} +- + void WindowSurfaceWayland::CommitWaylandBuffer() { + MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); + +@@ -1022,16 +1012,10 @@ + mWholeWindowBufferDamage = false; + mNeedScaleFactorUpdate = true; + } else { +- gint scaleFactor = mWindow->GdkScaleFactor(); + for (auto iter = mWaylandBufferDamage.RectIter(); !iter.Done(); + iter.Next()) { + mozilla::LayoutDeviceIntRect r = iter.Get(); +- // We need to remove the scale factor because the wl_surface_damage +- // also multiplies by current scale factor. +- if (scaleFactor > 1) { +- CalcRectScale(r, scaleFactor); +- } +- wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); ++ wl_surface_damage_buffer(waylandSurface, r.x, r.y, r.width, r.height); + } + } + +diff --git a/widget/gtk/mozcontainer.cpp b/widget/gtk/mozcontainer.cpp +--- a/widget/gtk/mozcontainer.cpp ++++ b/widget/gtk/mozcontainer.cpp +@@ -578,16 +578,12 @@ + return nullptr; + } + GdkDisplay* display = gtk_widget_get_display(GTK_WIDGET(container)); ++ nsWaylandDisplay* waylandDisplay = WaylandDisplayGet(display); + + // Available as of GTK 3.8+ +- static auto sGdkWaylandDisplayGetWlCompositor = +- (wl_compositor * (*)(GdkDisplay*)) +- dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor"); +- struct wl_compositor* compositor = +- sGdkWaylandDisplayGetWlCompositor(display); ++ struct wl_compositor* compositor = waylandDisplay->GetCompositor(); + container->surface = wl_compositor_create_surface(compositor); + +- nsWaylandDisplay* waylandDisplay = WaylandDisplayGet(display); + container->subsurface = wl_subcompositor_get_subsurface( + waylandDisplay->GetSubcompositor(), container->surface, + moz_container_get_gtk_container_surface(container)); +diff --git a/widget/gtk/mozwayland/mozwayland.h b/widget/gtk/mozwayland/mozwayland.h +--- a/widget/gtk/mozwayland/mozwayland.h ++++ b/widget/gtk/mozwayland/mozwayland.h +@@ -108,6 +108,17 @@ + } + #endif + ++#ifndef WL_SURFACE_DAMAGE_BUFFER ++# define WL_SURFACE_DAMAGE_BUFFER 9 ++ ++static inline void wl_surface_damage_buffer(struct wl_surface* wl_surface, ++ int32_t x, int32_t y, int32_t width, ++ int32_t height) { ++ wl_proxy_marshal((struct wl_proxy*)wl_surface, WL_SURFACE_DAMAGE_BUFFER, x, y, ++ width, height); ++} ++#endif ++ + #ifdef __cplusplus + } + #endif +diff --git a/widget/gtk/mozwayland/mozwayland.c b/widget/gtk/mozwayland/mozwayland.c +--- a/widget/gtk/mozwayland/mozwayland.c ++++ b/widget/gtk/mozwayland/mozwayland.c +@@ -30,6 +30,7 @@ + const struct wl_interface wl_seat_interface; + const struct wl_interface wl_surface_interface; + const struct wl_interface wl_subsurface_interface; ++const struct wl_interface wl_compositor_interface; + const struct wl_interface wl_subcompositor_interface; + #pragma GCC visibility pop + +diff --git a/widget/gtk/nsWaylandDisplay.h b/widget/gtk/nsWaylandDisplay.h +--- a/widget/gtk/nsWaylandDisplay.h ++++ b/widget/gtk/nsWaylandDisplay.h +@@ -45,6 +45,7 @@ + MessageLoop* GetDispatcherThreadLoop() { return mDispatcherThreadLoop; } + wl_display* GetDisplay() { return mDisplay; }; + wl_event_queue* GetEventQueue() { return mEventQueue; }; ++ wl_compositor* GetCompositor(void) { return mCompositor; }; + wl_subcompositor* GetSubcompositor(void) { return mSubcompositor; }; + wl_data_device_manager* GetDataDeviceManager(void) { + return mDataDeviceManager; +@@ -56,6 +57,7 @@ + }; + + void SetShm(wl_shm* aShm); ++ void SetCompositor(wl_compositor* aCompositor); + void SetSubcompositor(wl_subcompositor* aSubcompositor); + void SetDataDeviceManager(wl_data_device_manager* aDataDeviceManager); + void SetSeat(wl_seat* aSeat); +@@ -88,6 +90,7 @@ + wl_display* mDisplay; + wl_event_queue* mEventQueue; + wl_data_device_manager* mDataDeviceManager; ++ wl_compositor* mCompositor; + wl_subcompositor* mSubcompositor; + wl_seat* mSeat; + wl_shm* mShm; +diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp +--- a/widget/gtk/nsWaylandDisplay.cpp ++++ b/widget/gtk/nsWaylandDisplay.cpp +@@ -116,6 +116,10 @@ + + void nsWaylandDisplay::SetShm(wl_shm* aShm) { mShm = aShm; } + ++void nsWaylandDisplay::SetCompositor(wl_compositor* aCompositor) { ++ mCompositor = aCompositor; ++} ++ + void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) { + mSubcompositor = aSubcompositor; + } +@@ -223,6 +227,12 @@ + wl_proxy_set_queue((struct wl_proxy*)primary_selection_device_manager, + display->GetEventQueue()); + display->SetPrimarySelectionDeviceManager(primary_selection_device_manager); ++ } else if (strcmp(interface, "wl_compositor") == 0) { ++ // Requested wl_compositor version 4 as we need wl_surface_damage_buffer(). ++ auto compositor = static_cast( ++ wl_registry_bind(registry, id, &wl_compositor_interface, 4)); ++ wl_proxy_set_queue((struct wl_proxy*)compositor, display->GetEventQueue()); ++ display->SetCompositor(compositor); + } else if (strcmp(interface, "wl_subcompositor") == 0) { + auto subcompositor = static_cast( + wl_registry_bind(registry, id, &wl_subcompositor_interface, 1)); +@@ -306,6 +316,7 @@ + mDisplay(aDisplay), + mEventQueue(nullptr), + mDataDeviceManager(nullptr), ++ mCompositor(nullptr), + mSubcompositor(nullptr), + mSeat(nullptr), + mShm(nullptr), +