diff options
-rw-r--r-- | firefox.spec | 12 | ||||
-rw-r--r-- | mozilla-1441743.patch | 336 | ||||
-rw-r--r-- | mozilla-1444437.patch | 81 | ||||
-rw-r--r-- | mozilla-1465371.patch | 59 | ||||
-rw-r--r-- | mozilla-1467125.patch | 26 | ||||
-rw-r--r-- | mozilla-1467128.patch | 359 | ||||
-rw-r--r-- | mozilla-1468670.patch | 102 |
7 files changed, 975 insertions, 0 deletions
diff --git a/firefox.spec b/firefox.spec index a6f8756..8879403 100644 --- a/firefox.spec +++ b/firefox.spec @@ -181,6 +181,12 @@ Patch563: rb245262.patch Patch564: mozilla-1464808.patch Patch565: mozilla-1464823.patch Patch566: mozilla-1466473.patch +Patch567: mozilla-1444437.patch +Patch568: mozilla-1441743.patch +Patch569: mozilla-1465371.patch +Patch570: mozilla-1467125.patch +Patch571: mozilla-1468670.patch +Patch572: mozilla-1467128.patch # Debian patches Patch500: mozilla-440908.patch @@ -389,6 +395,12 @@ This package contains results of tests executed during build. %patch564 -p1 -b .mozilla-1464808 %patch565 -p1 -b .mozilla-1464823 %patch566 -p1 -b .mozilla-1466473 +%patch567 -p1 -b .mozilla-1444437 +%patch568 -p1 -b .mozilla-1441743 +%patch569 -p1 -b .mozilla-1465371 +%patch570 -p1 -b .mozilla-1467125 +%patch571 -p1 -b .mozilla-1468670 +%patch572 -p1 -b .mozilla-1467128 %endif %{__rm} -f .mozconfig diff --git a/mozilla-1441743.patch b/mozilla-1441743.patch new file mode 100644 index 0000000..59018c7 --- /dev/null +++ b/mozilla-1441743.patch @@ -0,0 +1,336 @@ +diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h +--- a/widget/gtk/WindowSurfaceWayland.h ++++ b/widget/gtk/WindowSurfaceWayland.h +@@ -3,16 +3,17 @@ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #ifndef _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H + #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H + + #include <prthread.h> ++#include "mozilla/gfx/Types.h" + + namespace mozilla { + namespace widget { + + // Our general connection to Wayland display server, + // holds our display connection and runs event loop. + class nsWaylandDisplay : public nsISupports { + NS_DECL_THREADSAFE_ISUPPORTS +@@ -61,17 +62,17 @@ private: + }; + + // Holds actual graphics data for wl_surface + class WindowBackBuffer { + public: + WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight); + ~WindowBackBuffer(); + +- already_AddRefed<gfx::DrawTarget> Lock(const LayoutDeviceIntRegion& aRegion); ++ already_AddRefed<gfx::DrawTarget> Lock(); + + void Attach(wl_surface* aSurface); + void Detach(); + bool IsAttached() { return mAttached; } + + bool Resize(int aWidth, int aHeight); + bool SetImageDataFromBackBuffer(class WindowBackBuffer* aSourceBuffer); + +@@ -107,27 +108,33 @@ public: + WindowSurfaceWayland(nsWindow *aWindow); + ~WindowSurfaceWayland(); + + already_AddRefed<gfx::DrawTarget> Lock(const LayoutDeviceIntRegion& aRegion) override; + void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; + void FrameCallbackHandler(); + + private: +- WindowBackBuffer* GetBufferToDraw(int aWidth, int aHeight); ++ WindowBackBuffer* GetFrontBufferToDraw(int aWidth, int aHeight); + void UpdateScaleFactor(); + ++ already_AddRefed<gfx::DrawTarget> LockFrontBuffer(int aWidth, int aHeight); ++ already_AddRefed<gfx::DrawTarget> LockImageSurface(const gfx::IntSize& aLockSize); ++ bool CommitImageSurface(const LayoutDeviceIntRegion& aRegion); ++ + // TODO: Do we need to hold a reference to nsWindow object? + nsWindow* mWindow; + nsWaylandDisplay* mWaylandDisplay; + WindowBackBuffer* mFrontBuffer; + WindowBackBuffer* mBackBuffer; ++ RefPtr<gfxImageSurface> mImageSurface; + wl_callback* mFrameCallback; + wl_surface* mFrameCallbackSurface; + MessageLoop* mDisplayThreadMessageLoop; ++ bool mDirectWlBufferDraw; + bool mDelayedCommit; + bool mFullScreenDamage; + bool mIsMainThread; + }; + + } // namespace widget + } // namespace mozilla + + +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -299,16 +299,17 @@ nsWaylandDisplay::Matches(wl_display *aD + } + + NS_IMPL_ISUPPORTS(nsWaylandDisplay, nsISupports); + + nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay) + : mThreadId(PR_GetCurrentThread()) + // gfx::SurfaceFormat::B8G8R8A8 is a basic Wayland format + // and is always present. ++ // TODO: Provide also format without alpha (Bug 1470126). + , mFormat(gfx::SurfaceFormat::B8G8R8A8) + , mShm(nullptr) + , mDisplay(aDisplay) + { + if (NS_IsMainThread()) { + // Use default event queue in main thread operated by Gtk+. + mEventQueue = nullptr; + } else { +@@ -530,21 +531,19 @@ WindowBackBuffer::SetImageDataFromBackBu + } + + mShmPool.SetImageDataFromPool(&aSourceBuffer->mShmPool, + aSourceBuffer->mWidth * aSourceBuffer->mHeight * BUFFER_BPP); + return true; + } + + already_AddRefed<gfx::DrawTarget> +-WindowBackBuffer::Lock(const LayoutDeviceIntRegion& aRegion) ++WindowBackBuffer::Lock() + { +- gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); +- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); +- ++ gfx::IntSize lockSize(mWidth, mHeight); + return gfxPlatform::CreateDrawTargetForData(static_cast<unsigned char*>(mShmPool.GetImageData()), + lockSize, + BUFFER_BPP * mWidth, + mWaylandDisplay->GetSurfaceFormat()); + } + + static void + frame_callback_handler(void *data, struct wl_callback *callback, uint32_t time) +@@ -560,16 +559,17 @@ static const struct wl_callback_listener + WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) + : mWindow(aWindow) + , mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay())) + , mFrontBuffer(nullptr) + , mBackBuffer(nullptr) + , mFrameCallback(nullptr) + , mFrameCallbackSurface(nullptr) + , mDisplayThreadMessageLoop(MessageLoop::current()) ++ , mDirectWlBufferDraw(true) + , mDelayedCommit(false) + , mFullScreenDamage(false) + , mIsMainThread(NS_IsMainThread()) + { + } + + WindowSurfaceWayland::~WindowSurfaceWayland() + { +@@ -598,17 +598,17 @@ WindowSurfaceWayland::UpdateScaleFactor( + { + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (waylandSurface) { + wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); + } + } + + WindowBackBuffer* +-WindowSurfaceWayland::GetBufferToDraw(int aWidth, int aHeight) ++WindowSurfaceWayland::GetFrontBufferToDraw(int aWidth, int aHeight) + { + if (!mFrontBuffer) { + mFrontBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); + mBackBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); + return mFrontBuffer; + } + + if (!mFrontBuffer->IsAttached()) { +@@ -647,46 +647,149 @@ WindowSurfaceWayland::GetBufferToDraw(in + // the new buffer and leave gecko to render new whole content. + mFrontBuffer->Resize(aWidth, aHeight); + } + + return mFrontBuffer; + } + + already_AddRefed<gfx::DrawTarget> ++WindowSurfaceWayland::LockFrontBuffer(int aWidth, int aHeight) ++{ ++ WindowBackBuffer* buffer = GetFrontBufferToDraw(aWidth, aHeight); ++ if (buffer) { ++ return buffer->Lock(); ++ } ++ ++ NS_WARNING("WindowSurfaceWayland::LockFrontBuffer(): No buffer available"); ++ return nullptr; ++} ++ ++already_AddRefed<gfx::DrawTarget> ++WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize) ++{ ++ if (!mImageSurface || mImageSurface->CairoStatus() || ++ !(aLockSize <= mImageSurface->GetSize())) { ++ mImageSurface = new gfxImageSurface(aLockSize, ++ SurfaceFormatToImageFormat(mWaylandDisplay->GetSurfaceFormat())); ++ if (mImageSurface->CairoStatus()) { ++ return nullptr; ++ } ++ } ++ ++ return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(), ++ mImageSurface->GetSize(), ++ mImageSurface->Stride(), ++ mWaylandDisplay->GetSurfaceFormat()); ++} ++ ++/* ++ 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. ++ - mFrontBuffer is available - that's an ideal situation. ++ - mFrontBuffer is locked by compositor - flip buffers and draw. ++ - if we can't flip buffers - 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()); + +- // We allocate back buffer to widget size but return only +- // portion requested by aRegion. +- LayoutDeviceIntRect rect = mWindow->GetBounds(); +- WindowBackBuffer* buffer = GetBufferToDraw(rect.width, +- rect.height); +- if (!buffer) { +- NS_WARNING("No drawing buffer available"); +- return nullptr; ++ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); ++ ++ // Are we asked for entire nsWindow to draw? ++ mDirectWlBufferDraw = (aRegion.GetNumRects() == 1 && ++ bounds.x == 0 && bounds.y == 0 && ++ lockSize.width == screenRect.width && ++ lockSize.height == screenRect.height); ++ ++ if (mDirectWlBufferDraw) { ++ RefPtr<gfx::DrawTarget> dt = LockFrontBuffer(screenRect.width, ++ screenRect.height); ++ if (dt) { ++ return dt.forget(); ++ } ++ ++ // We don't have any front buffer available. Try indirect drawing ++ // to mImageSurface which is mirrored to front buffer at commit. ++ mDirectWlBufferDraw = false; + } + +- return buffer->Lock(aRegion); ++ return LockImageSurface(lockSize); ++} ++ ++bool ++WindowSurfaceWayland::CommitImageSurface(const LayoutDeviceIntRegion& aRegion) ++{ ++ MOZ_ASSERT(!mDirectWlBufferDraw); ++ ++ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ ++ gfx::Rect rect(bounds); ++ if (rect.IsEmpty()) { ++ return false; ++ } ++ ++ RefPtr<gfx::DrawTarget> dt = LockFrontBuffer(screenRect.width, ++ screenRect.height); ++ RefPtr<gfx::SourceSurface> surf = ++ gfx::Factory::CreateSourceSurfaceForCairoSurface(mImageSurface->CairoSurface(), ++ mImageSurface->GetSize(), ++ mImageSurface->Format()); ++ if (!dt || !surf) { ++ return false; ++ } ++ ++ 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()); ++ } ++ dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); ++ } ++ ++ dt->DrawSurface(surf, rect, rect); ++ ++ if (numRects != 1) { ++ dt->PopClip(); ++ } ++ ++ return true; + } + + void + WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) + { + MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); + + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (!waylandSurface) { + // Target window is already destroyed - don't bother to render there. ++ NS_WARNING("WindowSurfaceWayland::Commit(): parent wl_surface is already hidden/deleted."); + return; + } + wl_proxy_set_queue((struct wl_proxy *)waylandSurface, + mWaylandDisplay->GetEventQueue()); + ++ if (!mDirectWlBufferDraw) { ++ // We have new content at mImageSurface - copy data to mFrontBuffer first. ++ CommitImageSurface(aInvalidRegion); ++ } ++ + if (mFullScreenDamage) { + LayoutDeviceIntRect rect = mWindow->GetBounds(); + wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height); + mFullScreenDamage = false; + } else { + for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { + const mozilla::LayoutDeviceIntRect &r = iter.Get(); + wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); +@@ -730,17 +833,17 @@ WindowSurfaceWayland::FrameCallbackHandl + mFrameCallback = nullptr; + mFrameCallbackSurface = nullptr; + } + + if (mDelayedCommit) { + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (!waylandSurface) { + // Target window is already destroyed - don't bother to render there. +- NS_WARNING("No drawing buffer available"); ++ NS_WARNING("WindowSurfaceWayland::FrameCallbackHandler(): parent wl_surface is already hidden/deleted."); + return; + } + wl_proxy_set_queue((struct wl_proxy *)waylandSurface, + mWaylandDisplay->GetEventQueue()); + + // Send pending surface to compositor and register frame callback + // for possible subsequent drawing. + mFrameCallback = wl_surface_frame(waylandSurface); diff --git a/mozilla-1444437.patch b/mozilla-1444437.patch new file mode 100644 index 0000000..ed9e05a --- /dev/null +++ b/mozilla-1444437.patch @@ -0,0 +1,81 @@ +diff -up firefox-61.0.1/widget/gtk/mozcontainer.cpp.mozilla-1444437 firefox-61.0.1/widget/gtk/mozcontainer.cpp +--- firefox-61.0.1/widget/gtk/mozcontainer.cpp.mozilla-1444437 2018-07-16 16:38:36.059138061 +0200 ++++ firefox-61.0.1/widget/gtk/mozcontainer.cpp 2018-07-16 17:04:10.127003844 +0200 +@@ -212,6 +212,7 @@ moz_container_init (MozContainer *contai + container->surface = nullptr; + container->subsurface = nullptr; + container->eglwindow = nullptr; ++ container->parent_surface_committed = false; + + GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container)); + if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { +@@ -231,6 +232,15 @@ moz_container_init (MozContainer *contai + } + + #if defined(MOZ_WAYLAND) ++static void ++moz_container_commited_handler(GdkFrameClock *clock, MozContainer *container) ++{ ++ container->parent_surface_committed = true; ++ g_signal_handler_disconnect(clock, ++ container->parent_surface_committed_handler); ++ container->parent_surface_committed_handler = 0; ++} ++ + /* We want to draw to GdkWindow owned by mContainer from Compositor thread but + * Gtk+ can be used in main thread only. So we create wayland wl_surface + * and attach it as an overlay to GdkWindow. +@@ -256,6 +266,21 @@ moz_container_map_surface(MozContainer * + if (container->subsurface && container->surface) + return true; + ++ if (!container->parent_surface_committed) { ++ if (!container->parent_surface_committed_handler) { ++ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); ++ static auto sGdkWindowGetFrameClock = ++ (GdkFrameClock *(*)(GdkWindow *)) ++ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); ++ GdkFrameClock *clock = sGdkWindowGetFrameClock(window); ++ container->parent_surface_committed_handler = ++ g_signal_connect_after(clock, "after-paint", ++ G_CALLBACK(moz_container_commited_handler), ++ container); ++ } ++ return false; ++ } ++ + if (!container->surface) { + struct wl_compositor *compositor; + compositor = sGdkWaylandDisplayGetWlCompositor(display); +@@ -298,6 +323,19 @@ moz_container_unmap_surface(MozContainer + g_clear_pointer(&container->eglwindow, wl_egl_window_destroy); + g_clear_pointer(&container->subsurface, wl_subsurface_destroy); + g_clear_pointer(&container->surface, wl_surface_destroy); ++ ++ if (container->parent_surface_committed_handler) { ++ static auto sGdkWindowGetFrameClock = ++ (GdkFrameClock *(*)(GdkWindow *)) ++ dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); ++ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); ++ GdkFrameClock *clock = sGdkWindowGetFrameClock(window); ++ ++ g_signal_handler_disconnect(clock, ++ container->parent_surface_committed_handler); ++ container->parent_surface_committed_handler = 0; ++ } ++ container->parent_surface_committed = false; + } + + #endif +diff -up firefox-61.0.1/widget/gtk/mozcontainer.h.mozilla-1444437 firefox-61.0.1/widget/gtk/mozcontainer.h +--- firefox-61.0.1/widget/gtk/mozcontainer.h.mozilla-1444437 2018-07-16 16:38:36.059138061 +0200 ++++ firefox-61.0.1/widget/gtk/mozcontainer.h 2018-07-16 16:38:36.105138588 +0200 +@@ -73,6 +73,8 @@ struct _MozContainer + struct wl_surface *surface; + struct wl_subsurface *subsurface; + struct wl_egl_window *eglwindow; ++ gboolean parent_surface_committed; ++ gulong parent_surface_committed_handler; + #endif + }; + diff --git a/mozilla-1465371.patch b/mozilla-1465371.patch new file mode 100644 index 0000000..8e4e8e1 --- /dev/null +++ b/mozilla-1465371.patch @@ -0,0 +1,59 @@ +diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp +--- a/toolkit/xre/nsAppRunner.cpp ++++ b/toolkit/xre/nsAppRunner.cpp +@@ -1700,31 +1700,25 @@ ParseRemoteCommandLine(nsCString& progra + + return REMOTE_FOUND; + } + + static RemoteResult + StartRemoteClient(const char* aDesktopStartupID, + nsCString& program, + const char* profile, +- const char* username, +- bool aIsX11Display) ++ const char* username) + { + nsAutoPtr<nsRemoteClient> client; + +- if (aIsX11Display) { +- client = new XRemoteClient(); +- } else { + #if defined(MOZ_ENABLE_DBUS) && defined(MOZ_WAYLAND) +- client = new DBusRemoteClient(); ++ client = new DBusRemoteClient(); + #else +- MOZ_ASSERT(false, "Missing remote implementation!"); +- return REMOTE_NOT_FOUND; ++ client = new XRemoteClient(); + #endif +- } + + nsresult rv = client->Init(); + if (NS_FAILED(rv)) + return REMOTE_NOT_FOUND; + + nsCString response; + bool success = false; + rv = client->SendCommandLine(program.get(), username, profile, +@@ -4070,18 +4064,17 @@ XREMain::XRE_mainStartup(bool* aExitFlag + NS_WARNING("Cannot lock XRemote start mutex"); + } + } + + // Try to remote the entire command line. If this fails, start up normally. + const char* desktopStartupIDPtr = + mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get(); + +- rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username, +- GDK_IS_X11_DISPLAY(mGdkDisplay)); ++ rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username); + if (rr == REMOTE_FOUND) { + *aExitFlag = true; + return 0; + } + if (rr == REMOTE_ARG_BAD) { + return 1; + } + } + diff --git a/mozilla-1467125.patch b/mozilla-1467125.patch new file mode 100644 index 0000000..375ac49 --- /dev/null +++ b/mozilla-1467125.patch @@ -0,0 +1,26 @@ +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -146,18 +146,19 @@ static StaticMutex gWaylandDisplaysMutex + // + // nsWaylandDisplay is our interface to wayland compositor. It provides wayland + // global objects as we need (wl_display, wl_shm) and operates wl_event_queue on + // compositor (not the main) thread. + static nsWaylandDisplay* WaylandDisplayGet(wl_display *aDisplay); + static void WaylandDisplayRelease(wl_display *aDisplay); + static void WaylandDisplayLoop(wl_display *aDisplay); + +-// TODO: is the 60pfs loop correct? +-#define EVENT_LOOP_DELAY (1000/60) ++// TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() with ++// compositor event loop. ++#define EVENT_LOOP_DELAY (1000/240) + + // Get WaylandDisplay for given wl_display and actual calling thread. + static nsWaylandDisplay* + WaylandDisplayGetLocked(wl_display *aDisplay, const StaticMutexAutoLock&) + { + nsWaylandDisplay* waylandDisplay = nullptr; + + int len = gWaylandDisplays.Count(); + diff --git a/mozilla-1467128.patch b/mozilla-1467128.patch new file mode 100644 index 0000000..75cf92c --- /dev/null +++ b/mozilla-1467128.patch @@ -0,0 +1,359 @@ +diff --git a/gfx/thebes/gfxPlatformGtk.h b/gfx/thebes/gfxPlatformGtk.h +--- a/gfx/thebes/gfxPlatformGtk.h ++++ b/gfx/thebes/gfxPlatformGtk.h +@@ -102,23 +102,42 @@ public: + #endif + + #ifdef MOZ_X11 + Display* GetCompositorDisplay() { + return mCompositorDisplay; + } + #endif // MOZ_X11 + ++#ifdef MOZ_WAYLAND ++ void SetWaylandLastVsync(uint32_t aVsyncTimestamp) { ++ mWaylandLastVsyncTimestamp = aVsyncTimestamp; ++ } ++ int64_t GetWaylandLastVsync() { ++ return mWaylandLastVsyncTimestamp; ++ } ++ void SetWaylandFrameDelay(int64_t aFrameDelay) { ++ mWaylandFrameDelay = aFrameDelay; ++ } ++ int64_t GetWaylandFrameDelay() { ++ return mWaylandFrameDelay; ++ } ++#endif ++ + protected: + bool CheckVariationFontSupport() override; + + int8_t mMaxGenericSubstitutions; + + private: + virtual void GetPlatformCMSOutputProfile(void *&mem, + size_t &size) override; + + #ifdef MOZ_X11 + Display* mCompositorDisplay; + #endif ++#ifdef MOZ_WAYLAND ++ int64_t mWaylandLastVsyncTimestamp; ++ int64_t mWaylandFrameDelay; ++#endif + }; + + #endif /* GFX_PLATFORM_GTK_H */ +diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp +--- a/gfx/thebes/gfxPlatformGtk.cpp ++++ b/gfx/thebes/gfxPlatformGtk.cpp +@@ -46,16 +46,20 @@ + #include "GLContextGLX.h" + #include "GLXLibrary.h" + + /* Undefine the Status from Xlib since it will conflict with system headers on OSX */ + #if defined(__APPLE__) && defined(Status) + #undef Status + #endif + ++#ifdef MOZ_WAYLAND ++#include <gdk/gdkwayland.h> ++#endif ++ + #endif /* MOZ_X11 */ + + #include <fontconfig/fontconfig.h> + + #include "nsMathUtils.h" + + #define GDK_PIXMAP_SIZE_MAX 32767 + +@@ -89,16 +93,22 @@ gfxPlatformGtk::gfxPlatformGtk() + #ifdef MOZ_X11 + if (gfxPlatform::IsHeadless() && GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + mCompositorDisplay = XOpenDisplay(nullptr); + MOZ_ASSERT(mCompositorDisplay, "Failed to create compositor display!"); + } else { + mCompositorDisplay = nullptr; + } + #endif // MOZ_X11 ++#ifdef MOZ_WAYLAND ++ // Wayland compositors use g_get_monotonic_time() to get timestamps. ++ mWaylandLastVsyncTimestamp = (g_get_monotonic_time() / 1000); ++ // Set default display fps to 60 ++ mWaylandFrameDelay = 1000/60; ++#endif + } + + gfxPlatformGtk::~gfxPlatformGtk() + { + #ifdef MOZ_X11 + if (mCompositorDisplay) { + XCloseDisplay(mCompositorDisplay); + } +@@ -505,26 +515,26 @@ gfxPlatformGtk::CheckVariationFontSuppor + // until at least 2.7.1. + FT_Int major, minor, patch; + FT_Library_Version(GetFTLibrary(), &major, &minor, &patch); + return major * 1000000 + minor * 1000 + patch >= 2007001; + } + + #ifdef MOZ_X11 + +-class GLXVsyncSource final : public VsyncSource ++class GtkVsyncSource final : public VsyncSource + { + public: +- GLXVsyncSource() ++ GtkVsyncSource() + { + MOZ_ASSERT(NS_IsMainThread()); + mGlobalDisplay = new GLXDisplay(); + } + +- virtual ~GLXVsyncSource() ++ virtual ~GtkVsyncSource() + { + MOZ_ASSERT(NS_IsMainThread()); + } + + virtual Display& GetGlobalDisplay() override + { + return *mGlobalDisplay; + } +@@ -536,39 +546,52 @@ public: + public: + GLXDisplay() : mGLContext(nullptr) + , mXDisplay(nullptr) + , mSetupLock("GLXVsyncSetupLock") + , mVsyncThread("GLXVsyncThread") + , mVsyncTask(nullptr) + , mVsyncEnabledLock("GLXVsyncEnabledLock") + , mVsyncEnabled(false) ++#ifdef MOZ_WAYLAND ++ , mIsWaylandDisplay(false) ++#endif + { + } + + // Sets up the display's GL context on a worker thread. + // Required as GLContexts may only be used by the creating thread. + // Returns true if setup was a success. + bool Setup() + { + MonitorAutoLock lock(mSetupLock); + MOZ_ASSERT(NS_IsMainThread()); + if (!mVsyncThread.Start()) + return false; + + RefPtr<Runnable> vsyncSetup = +- NewRunnableMethod("GLXVsyncSource::GLXDisplay::SetupGLContext", ++ NewRunnableMethod("GtkVsyncSource::GLXDisplay::SetupGLContext", + this, + &GLXDisplay::SetupGLContext); + mVsyncThread.message_loop()->PostTask(vsyncSetup.forget()); + // Wait until the setup has completed. + lock.Wait(); + return mGLContext != nullptr; + } + ++#ifdef MOZ_WAYLAND ++ bool SetupWayland() ++ { ++ MonitorAutoLock lock(mSetupLock); ++ MOZ_ASSERT(NS_IsMainThread()); ++ mIsWaylandDisplay = true; ++ return mVsyncThread.Start(); ++ } ++#endif ++ + // Called on the Vsync thread to setup the GL context. + void SetupGLContext() + { + MonitorAutoLock lock(mSetupLock); + MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!mGLContext, "GLContext already setup!"); + + // Create video sync timer on a separate Display to prevent locking the +@@ -613,29 +636,35 @@ public: + } + + lock.NotifyAll(); + } + + virtual void EnableVsync() override + { + MOZ_ASSERT(NS_IsMainThread()); ++#if !defined(MOZ_WAYLAND) + MOZ_ASSERT(mGLContext, "GLContext not setup!"); ++#endif + + MonitorAutoLock lock(mVsyncEnabledLock); + if (mVsyncEnabled) { + return; + } + mVsyncEnabled = true; + + // If the task has not nulled itself out, it hasn't yet realized + // that vsync was disabled earlier, so continue its execution. + if (!mVsyncTask) { + mVsyncTask = NewRunnableMethod( +- "GLXVsyncSource::GLXDisplay::RunVsync", this, &GLXDisplay::RunVsync); ++ "GtkVsyncSource::GLXDisplay::RunVsync", this, ++#if defined(MOZ_WAYLAND) ++ mIsWaylandDisplay ? &GLXDisplay::RunVsyncWayland : ++#endif ++ &GLXDisplay::RunVsync); + RefPtr<Runnable> addrefedTask = mVsyncTask; + mVsyncThread.message_loop()->PostTask(addrefedTask.forget()); + } + } + + virtual void DisableVsync() override + { + MonitorAutoLock lock(mVsyncEnabledLock); +@@ -650,17 +679,17 @@ public: + + virtual void Shutdown() override + { + MOZ_ASSERT(NS_IsMainThread()); + DisableVsync(); + + // Cleanup thread-specific resources before shutting down. + RefPtr<Runnable> shutdownTask = NewRunnableMethod( +- "GLXVsyncSource::GLXDisplay::Cleanup", this, &GLXDisplay::Cleanup); ++ "GtkVsyncSource::GLXDisplay::Cleanup", this, &GLXDisplay::Cleanup); + mVsyncThread.message_loop()->PostTask(shutdownTask.forget()); + + // Stop, waiting for the cleanup task to finish execution. + mVsyncThread.Stop(); + } + + private: + virtual ~GLXDisplay() +@@ -709,50 +738,96 @@ public: + } + } + + lastVsync = TimeStamp::Now(); + NotifyVsync(lastVsync); + } + } + ++#ifdef MOZ_WAYLAND ++ /* VSync on Wayland is tricky as we can get only "last VSync" event signal. ++ * That means we should draw next frame at "last Vsync + frame delay" time. ++ */ ++ void RunVsyncWayland() ++ { ++ MOZ_ASSERT(!NS_IsMainThread()); ++ ++ for (;;) { ++ { ++ MonitorAutoLock lock(mVsyncEnabledLock); ++ if (!mVsyncEnabled) { ++ mVsyncTask = nullptr; ++ return; ++ } ++ } ++ ++ gint64 lastVsync = gfxPlatformGtk::GetPlatform()->GetWaylandLastVsync(); ++ gint64 currTime = (g_get_monotonic_time() / 1000); ++ ++ gint64 remaining = gfxPlatformGtk::GetPlatform()->GetWaylandFrameDelay() - ++ (currTime - lastVsync); ++ if (remaining > 0) { ++ PlatformThread::Sleep(remaining); ++ } else { ++ // Time from last HW Vsync is longer than our frame delay, ++ // use our approximation then. ++ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(currTime); ++ } ++ ++ NotifyVsync(TimeStamp::Now()); ++ } ++ } ++#endif ++ + void Cleanup() { + MOZ_ASSERT(!NS_IsMainThread()); + + mGLContext = nullptr; +- XCloseDisplay(mXDisplay); ++ if (mXDisplay) ++ XCloseDisplay(mXDisplay); + } + + // Owned by the vsync thread. + RefPtr<gl::GLContextGLX> mGLContext; + _XDisplay* mXDisplay; + Monitor mSetupLock; + base::Thread mVsyncThread; + RefPtr<Runnable> mVsyncTask; + Monitor mVsyncEnabledLock; + bool mVsyncEnabled; ++#ifdef MOZ_WAYLAND ++ bool mIsWaylandDisplay; ++#endif + }; + private: + // We need a refcounted VsyncSource::Display to use chromium IPC runnables. + RefPtr<GLXDisplay> mGlobalDisplay; + }; + + already_AddRefed<gfx::VsyncSource> + gfxPlatformGtk::CreateHardwareVsyncSource() + { ++#ifdef MOZ_WAYLAND ++ if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { ++ RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource(); ++ VsyncSource::Display& display = vsyncSource->GetGlobalDisplay(); ++ static_cast<GtkVsyncSource::GLXDisplay&>(display).SetupWayland(); ++ return vsyncSource.forget(); ++ } ++#endif ++ + // Only use GLX vsync when the OpenGL compositor is being used. + // The extra cost of initializing a GLX context while blocking the main + // thread is not worth it when using basic composition. +- // Also don't use it on non-X11 displays. + if (gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) { +- if (GDK_IS_X11_DISPLAY(gdk_display_get_default()) && +- gl::sGLXLibrary.SupportsVideoSync()) { +- RefPtr<VsyncSource> vsyncSource = new GLXVsyncSource(); ++ if (gl::sGLXLibrary.SupportsVideoSync()) { ++ RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource(); + VsyncSource::Display& display = vsyncSource->GetGlobalDisplay(); +- if (!static_cast<GLXVsyncSource::GLXDisplay&>(display).Setup()) { ++ if (!static_cast<GtkVsyncSource::GLXDisplay&>(display).Setup()) { + NS_WARNING("Failed to setup GLContext, falling back to software vsync."); + return gfxPlatform::CreateHardwareVsyncSource(); + } + return vsyncSource.forget(); + } + NS_WARNING("SGI_video_sync unsupported. Falling back to software vsync."); + } + return gfxPlatform::CreateHardwareVsyncSource(); +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -546,16 +546,18 @@ WindowBackBuffer::Lock() + mWaylandDisplay->GetSurfaceFormat()); + } + + static void + frame_callback_handler(void *data, struct wl_callback *callback, uint32_t time) + { + auto surface = reinterpret_cast<WindowSurfaceWayland*>(data); + surface->FrameCallbackHandler(); ++ ++ gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time); + } + + static const struct wl_callback_listener frame_listener = { + frame_callback_handler + }; + + WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) + : mWindow(aWindow) + diff --git a/mozilla-1468670.patch b/mozilla-1468670.patch new file mode 100644 index 0000000..42a05e2 --- /dev/null +++ b/mozilla-1468670.patch @@ -0,0 +1,102 @@ +diff --git a/widget/gtk/nsGtkKeyUtils.h b/widget/gtk/nsGtkKeyUtils.h +--- a/widget/gtk/nsGtkKeyUtils.h ++++ b/widget/gtk/nsGtkKeyUtils.h +@@ -169,17 +169,20 @@ protected: + + bool mInitialized; + + /** + * Initializing methods. + */ + void Init(); + void InitXKBExtension(); +- void InitBySystemSettings(); ++ void InitBySystemSettingsX11(); ++#ifdef MOZ_WAYLAND ++ void InitBySystemSettingsWayland(); ++#endif + + /** + * mModifierKeys stores each hardware key information. + */ + struct ModifierKey { + guint mHardwareKeycode; + guint mMask; + + +diff --git a/widget/gtk/nsGtkKeyUtils.cpp b/widget/gtk/nsGtkKeyUtils.cpp +--- a/widget/gtk/nsGtkKeyUtils.cpp ++++ b/widget/gtk/nsGtkKeyUtils.cpp +@@ -190,17 +190,21 @@ KeymapWrapper::Init() + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, + ("%p Init, mGdkKeymap=%p", + this, mGdkKeymap)); + + mModifierKeys.Clear(); + memset(mModifierMasks, 0, sizeof(mModifierMasks)); + + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) +- InitBySystemSettings(); ++ InitBySystemSettingsX11(); ++#ifdef MOZ_WAYLAND ++ else ++ InitBySystemSettingsWayland(); ++#endif + + gdk_window_add_filter(nullptr, FilterEvents, this); + + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, + ("%p Init, CapsLock=0x%X, NumLock=0x%X, " + "ScrollLock=0x%X, Level3=0x%X, Level5=0x%X, " + "Shift=0x%X, Ctrl=0x%X, Alt=0x%X, Meta=0x%X, Super=0x%X, Hyper=0x%X", + this, +@@ -270,20 +274,20 @@ KeymapWrapper::InitXKBExtension() + return; + } + + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, + ("%p InitXKBExtension, Succeeded", this)); + } + + void +-KeymapWrapper::InitBySystemSettings() ++KeymapWrapper::InitBySystemSettingsX11() + { + MOZ_LOG(gKeymapWrapperLog, LogLevel::Info, +- ("%p InitBySystemSettings, mGdkKeymap=%p", ++ ("%p InitBySystemSettingsX11, mGdkKeymap=%p", + this, mGdkKeymap)); + + Display* display = + gdk_x11_display_get_xdisplay(gdk_display_get_default()); + + int min_keycode = 0; + int max_keycode = 0; + XDisplayKeycodes(display, &min_keycode, &max_keycode); +@@ -434,16 +438,26 @@ KeymapWrapper::InitBySystemSettings() + } + } + } + + XFreeModifiermap(xmodmap); + XFree(xkeymap); + } + ++#ifdef MOZ_WAYLAND ++void ++KeymapWrapper::InitBySystemSettingsWayland() ++{ ++ // Not implemented yet, but at least Alt modifier should be handled to save ++ // popular usage. ++ mModifierMasks[INDEX_ALT] = 1 << 3; ++} ++#endif ++ + KeymapWrapper::~KeymapWrapper() + { + gdk_window_remove_filter(nullptr, FilterEvents, this); + g_signal_handlers_disconnect_by_func(mGdkKeymap, + FuncToGpointer(OnKeysChanged), this); + g_signal_handlers_disconnect_by_func(mGdkKeymap, + FuncToGpointer(OnDirectionChanged), this); + g_object_unref(mGdkKeymap); |