diff options
Diffstat (limited to 'mozilla-1467128.patch')
-rw-r--r-- | mozilla-1467128.patch | 359 |
1 files changed, 359 insertions, 0 deletions
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) + |