From 9ccabf9ffb1a906a42dcaebb1d05fcf0cb03b339 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 27 May 2019 15:07:37 +0200 Subject: removed mozbz#1552590 fix --- firefox.spec | 9 +- mozilla-1467127.patch | 256 ++++ mozilla-1552590.patch | 4048 ++++++++++++++++++++++++++----------------------- 3 files changed, 2381 insertions(+), 1932 deletions(-) create mode 100644 mozilla-1467127.patch diff --git a/firefox.spec b/firefox.spec index eb2c5c0..c4c847c 100644 --- a/firefox.spec +++ b/firefox.spec @@ -99,7 +99,7 @@ ExcludeArch: s390x Summary: Mozilla Firefox Web browser Name: firefox Version: 67.0 -Release: 5%{?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 @@ -163,6 +163,7 @@ Patch579: mozilla-1468911.patch Patch580: mozilla-1539471.patch Patch581: mozilla-1517205.patch Patch582: mozilla-1508378.patch +Patch583: mozilla-1467127.patch Patch584: mozilla-1552590.patch # PGO/LTO patches @@ -378,7 +379,8 @@ This package contains results of tests executed during build. %patch580 -p1 -b .mozilla-1539471 %patch581 -p1 -b .mozilla-1517205 %patch582 -p1 -b .mozilla-1508378 -%patch584 -p1 -b .mozilla-1552590 +#%patch583 -p1 -b .mozilla-1467127 +#%patch584 -p1 -b .mozilla-1552590 # PGO patches %patch600 -p1 -b .pgo @@ -936,9 +938,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog -* Thu May 27 2019 Martin Stransky - 67.0-5 -- Added mozbz#1552590 fix. - * Thu May 23 2019 Martin Stransky - 67.0-4 - Added wayland buffer optimization (mozilla#1553747). diff --git a/mozilla-1467127.patch b/mozilla-1467127.patch new file mode 100644 index 0000000..69a8903 --- /dev/null +++ b/mozilla-1467127.patch @@ -0,0 +1,256 @@ +diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp +--- a/gfx/thebes/gfxPlatform.cpp ++++ b/gfx/thebes/gfxPlatform.cpp +@@ -70,6 +70,10 @@ + # include "mozilla/gfx/DeviceManagerDx.h" + #endif + ++#ifdef MOZ_WAYLAND ++# include "mozilla/widget/nsWaylandDisplayShutdown.h" ++#endif ++ + #include "nsGkAtoms.h" + #include "gfxPlatformFontList.h" + #include "gfxContext.h" +@@ -1276,6 +1280,9 @@ + layers::PaintThread::Shutdown(); + } + } else if (XRE_IsParentProcess()) { ++#ifdef MOZ_WAYLAND ++ widget::WaylandDisplayShutdown(); ++#endif + gfx::VRManagerChild::ShutDown(); + layers::CompositorManagerChild::Shutdown(); + layers::ImageBridgeChild::ShutDown(); +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -144,6 +144,8 @@ + (wl_buffer/wl_surface). + */ + ++#define EVENT_LOOP_DELAY (1000 / 240) ++ + #define BUFFER_BPP 4 + gfx::SurfaceFormat WindowBackBuffer::mFormat = gfx::SurfaceFormat::B8G8R8A8; + +diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build +--- a/widget/gtk/moz.build ++++ b/widget/gtk/moz.build +@@ -101,6 +101,9 @@ + 'nsWaylandDisplay.cpp', + 'WindowSurfaceWayland.cpp', + ] ++ EXPORTS.mozilla.widget += [ ++ 'nsWaylandDisplayShutdown.h' ++ ] + + if CONFIG['ACCESSIBILITY']: + UNIFIED_SOURCES += [ +diff --git a/widget/gtk/nsAppShell.cpp b/widget/gtk/nsAppShell.cpp +--- a/widget/gtk/nsAppShell.cpp ++++ b/widget/gtk/nsAppShell.cpp +@@ -27,6 +27,9 @@ + #include "ScreenHelperGTK.h" + #include "HeadlessScreenHelper.h" + #include "mozilla/widget/ScreenManager.h" ++#ifdef MOZ_WAYLAND ++# include "nsWaylandDisplay.h" ++#endif + + using mozilla::LazyLogModule; + using mozilla::Unused; +@@ -267,5 +270,9 @@ + } + + bool nsAppShell::ProcessNextNativeEvent(bool mayWait) { +- return g_main_context_iteration(nullptr, mayWait); ++ bool ret = g_main_context_iteration(nullptr, mayWait); ++#ifdef MOZ_WAYLAND ++ WaylandDispatchDisplays(); ++#endif ++ return ret; + } +diff --git a/widget/gtk/nsWaylandDisplay.h b/widget/gtk/nsWaylandDisplay.h +--- a/widget/gtk/nsWaylandDisplay.h ++++ b/widget/gtk/nsWaylandDisplay.h +@@ -14,10 +14,6 @@ + namespace mozilla { + namespace widget { + +-// TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() +-// with compositor event loop. +-#define EVENT_LOOP_DELAY (1000 / 240) +- + // Our general connection to Wayland display server, + // holds our display connection and runs event loop. + class nsWaylandDisplay { +@@ -25,9 +21,10 @@ + explicit nsWaylandDisplay(wl_display* aDisplay); + virtual ~nsWaylandDisplay(); + +- bool DisplayLoop(); ++ bool DispatchEventQueue(); + bool Matches(wl_display* aDisplay); + ++ MessageLoop* GetDispatcherThreadLoop() { return mDispatcherThreadLoop; } + wl_display* GetDisplay() { return mDisplay; }; + wl_event_queue* GetEventQueue() { return mEventQueue; }; + wl_subcompositor* GetSubcompositor(void) { return mSubcompositor; }; +@@ -47,7 +44,10 @@ + void SetPrimarySelectionDeviceManager( + gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager); + ++ void Shutdown(); ++ + private: ++ MessageLoop* mDispatcherThreadLoop; + PRThread* mThreadId; + wl_display* mDisplay; + wl_event_queue* mEventQueue; +@@ -59,6 +59,7 @@ + wl_registry* mRegistry; + }; + ++void WaylandDispatchDisplays(); + nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr); + + } // namespace widget +diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp +--- a/widget/gtk/nsWaylandDisplay.cpp ++++ b/widget/gtk/nsWaylandDisplay.cpp +@@ -21,6 +21,15 @@ + static nsWaylandDisplay *gWaylandDisplays[MAX_DISPLAY_CONNECTIONS]; + static StaticMutex gWaylandDisplaysMutex; + ++void WaylandDisplayShutdown() { ++ StaticMutexAutoLock lock(gWaylandDisplaysMutex); ++ for (auto &display : gWaylandDisplays) { ++ if (display) { ++ display->Shutdown(); ++ } ++ } ++} ++ + static void ReleaseDisplaysAtExit() { + for (int i = 0; i < MAX_DISPLAY_CONNECTIONS; i++) { + delete gWaylandDisplays[i]; +@@ -28,6 +37,10 @@ + } + } + ++static void DispatchDisplay(nsWaylandDisplay *aDisplay) { ++ aDisplay->DispatchEventQueue(); ++} ++ + // Each thread which is using wayland connection (wl_display) has to operate + // its own wl_event_queue. Main Firefox thread wl_event_queue is handled + // by Gtk main loop, other threads/wl_event_queue has to be handled by us. +@@ -35,7 +48,15 @@ + // 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 void WaylandDisplayLoop(wl_display *aDisplay); ++void WaylandDispatchDisplays() { ++ StaticMutexAutoLock lock(gWaylandDisplaysMutex); ++ for (auto &display : gWaylandDisplays) { ++ if (display && display->GetDispatcherThreadLoop()) { ++ display->GetDispatcherThreadLoop()->PostTask(NewRunnableFunction( ++ "WaylandDisplayDispatch", &DispatchDisplay, display)); ++ } ++ } ++} + + // Get WaylandDisplay for given wl_display and actual calling thread. + static nsWaylandDisplay *WaylandDisplayGetLocked(GdkDisplay *aGdkDisplay, +@@ -73,27 +94,6 @@ + return WaylandDisplayGetLocked(aGdkDisplay, lock); + } + +-static void WaylandDisplayLoopLocked(wl_display *aDisplay, +- const StaticMutexAutoLock &) { +- for (auto &display : gWaylandDisplays) { +- if (display && display->Matches(aDisplay)) { +- if (display->DisplayLoop()) { +- MessageLoop::current()->PostDelayedTask( +- NewRunnableFunction("WaylandDisplayLoop", &WaylandDisplayLoop, +- aDisplay), +- EVENT_LOOP_DELAY); +- } +- break; +- } +- } +-} +- +-static void WaylandDisplayLoop(wl_display *aDisplay) { +- MOZ_ASSERT(!NS_IsMainThread()); +- StaticMutexAutoLock lock(gWaylandDisplaysMutex); +- WaylandDisplayLoopLocked(aDisplay, lock); +-} +- + void nsWaylandDisplay::SetShm(wl_shm *aShm) { mShm = aShm; } + + void nsWaylandDisplay::SetSubcompositor(wl_subcompositor *aSubcompositor) { +@@ -158,7 +158,7 @@ + static const struct wl_registry_listener registry_listener = { + global_registry_handler, global_registry_remover}; + +-bool nsWaylandDisplay::DisplayLoop() { ++bool nsWaylandDisplay::DispatchEventQueue() { + wl_display_dispatch_queue_pending(mDisplay, mEventQueue); + return true; + } +@@ -168,7 +168,8 @@ + } + + nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay) +- : mThreadId(PR_GetCurrentThread()), ++ : mDispatcherThreadLoop(nullptr), ++ mThreadId(PR_GetCurrentThread()), + mDisplay(aDisplay), + mEventQueue(nullptr), + mDataDeviceManager(nullptr), +@@ -186,15 +187,16 @@ + wl_display_roundtrip(mDisplay); + wl_display_roundtrip(mDisplay); + } else { ++ mDispatcherThreadLoop = MessageLoop::current(); + mEventQueue = wl_display_create_queue(mDisplay); +- MessageLoop::current()->PostTask(NewRunnableFunction( +- "WaylandDisplayLoop", &WaylandDisplayLoop, mDisplay)); + wl_proxy_set_queue((struct wl_proxy *)mRegistry, mEventQueue); + wl_display_roundtrip_queue(mDisplay, mEventQueue); + wl_display_roundtrip_queue(mDisplay, mEventQueue); + } + } + ++void nsWaylandDisplay::Shutdown() { mDispatcherThreadLoop = nullptr; } ++ + nsWaylandDisplay::~nsWaylandDisplay() { + // Owned by Gtk+, we don't need to release + mDisplay = nullptr; +diff --git a/widget/gtk/nsWaylandDisplayShutdown.h b/widget/gtk/nsWaylandDisplayShutdown.h +new file mode 100644 +--- /dev/null ++++ b/widget/gtk/nsWaylandDisplayShutdown.h +@@ -0,0 +1,19 @@ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: ++ */ ++/* 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 __MOZ_WAYLAND_DISPLAY_SHUTDOWN_H__ ++#define __MOZ_WAYLAND_DISPLAY_SHUTDOWN_H__ ++ ++namespace mozilla { ++namespace widget { ++ ++void WaylandDisplayShutdown(); ++ ++} // namespace widget ++} // namespace mozilla ++ ++#endif // __MOZ_WAYLAND_DISPLAY_SHUTDOWN_H__ + diff --git a/mozilla-1552590.patch b/mozilla-1552590.patch index 4726c20..58d5b18 100644 --- a/mozilla-1552590.patch +++ b/mozilla-1552590.patch @@ -1,25 +1,13 @@ -diff -up firefox-67.0/gfx/2d/moz.build.mozilla-1552590 firefox-67.0/gfx/2d/moz.build ---- firefox-67.0/gfx/2d/moz.build.mozilla-1552590 2019-05-17 02:34:18.000000000 +0200 -+++ firefox-67.0/gfx/2d/moz.build 2019-05-27 12:15:32.030414339 +0200 -@@ -260,3 +260,15 @@ if CONFIG['MOZ_ENABLE_SKIA_GPU']: - LOCAL_INCLUDES += [ - '/gfx/skia/skia/src/gpu', - ] -+ -+#if CONFIG['MOZ_WAYLAND'] and CONFIG['HAVE_LIBDRM']: -+if CONFIG['HAVE_LIBDRM']: -+ SOURCES += [ -+ 'WaylandDMABufSurface.cpp', -+ ] -+ EXPORTS.mozilla.gfx += [ -+ 'WaylandDMABufSurface.h', -+ ] -+ CFLAGS += CONFIG['TK_CFLAGS'] -+ CXXFLAGS += CONFIG['TK_CFLAGS'] -+ -diff -up firefox-67.0/gfx/2d/WaylandDMABufSurface.cpp.mozilla-1552590 firefox-67.0/gfx/2d/WaylandDMABufSurface.cpp ---- firefox-67.0/gfx/2d/WaylandDMABufSurface.cpp.mozilla-1552590 2019-05-27 12:15:32.030414339 +0200 -+++ firefox-67.0/gfx/2d/WaylandDMABufSurface.cpp 2019-05-27 12:15:32.030414339 +0200 +changeset: 474982:24c0dda573b3 +parent: 474915:839cdad764d7 +user: Martin Stransky +date: Fri May 17 11:24:33 2019 +0200 +summary: Implement dmabuf surfaces + +diff --git a/gfx/2d/WaylandDMABufSurface.cpp b/gfx/2d/WaylandDMABufSurface.cpp +new file mode 100644 +--- /dev/null ++++ b/gfx/2d/WaylandDMABufSurface.cpp @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ @@ -295,9 +283,10 @@ diff -up firefox-67.0/gfx/2d/WaylandDMABufSurface.cpp.mozilla-1552590 firefox-67 + memset(destData, 0, GetHeight() * destStride); + Unmap(); +} -diff -up firefox-67.0/gfx/2d/WaylandDMABufSurface.h.mozilla-1552590 firefox-67.0/gfx/2d/WaylandDMABufSurface.h ---- firefox-67.0/gfx/2d/WaylandDMABufSurface.h.mozilla-1552590 2019-05-27 12:15:32.030414339 +0200 -+++ firefox-67.0/gfx/2d/WaylandDMABufSurface.h 2019-05-27 12:15:32.030414339 +0200 +diff --git a/gfx/2d/WaylandDMABufSurface.h b/gfx/2d/WaylandDMABufSurface.h +new file mode 100644 +--- /dev/null ++++ b/gfx/2d/WaylandDMABufSurface.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ @@ -372,10 +361,39 @@ diff -up firefox-67.0/gfx/2d/WaylandDMABufSurface.h.mozilla-1552590 firefox-67.0 +}; + +#endif -diff -up firefox-67.0/modules/libpref/init/all.js.mozilla-1552590 firefox-67.0/modules/libpref/init/all.js ---- firefox-67.0/modules/libpref/init/all.js.mozilla-1552590 2019-05-17 02:33:43.000000000 +0200 -+++ firefox-67.0/modules/libpref/init/all.js 2019-05-27 12:15:32.031414339 +0200 -@@ -5138,6 +5138,11 @@ pref("widget.chrome.allow-gtk-dark-theme +diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build +--- a/gfx/2d/moz.build ++++ b/gfx/2d/moz.build +@@ -255,8 +255,20 @@ if CONFIG['MOZ_ENABLE_SKIA']: + '/gfx/skia/skia/include/private', + '/gfx/skia/skia/src/core', + '/gfx/skia/skia/src/image', + ] + if CONFIG['MOZ_ENABLE_SKIA_GPU']: + LOCAL_INCLUDES += [ + '/gfx/skia/skia/src/gpu', + ] ++ ++#if CONFIG['MOZ_WAYLAND'] and CONFIG['HAVE_LIBDRM']: ++if CONFIG['HAVE_LIBDRM']: ++ SOURCES += [ ++ 'WaylandDMABufSurface.cpp', ++ ] ++ EXPORTS.mozilla.gfx += [ ++ 'WaylandDMABufSurface.h', ++ ] ++ CFLAGS += CONFIG['TK_CFLAGS'] ++ CXXFLAGS += CONFIG['TK_CFLAGS'] ++ +diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js +--- a/modules/libpref/init/all.js ++++ b/modules/libpref/init/all.js +@@ -5091,16 +5091,21 @@ pref("gfx.apitrace.enabled",false); + + #ifdef MOZ_X11 + #ifdef MOZ_WIDGET_GTK + pref("gfx.xrender.enabled",false); + pref("widget.chrome.allow-gtk-dark-theme", false); pref("widget.content.allow-gtk-dark-theme", false); #endif #endif @@ -387,10 +405,20 @@ diff -up firefox-67.0/modules/libpref/init/all.js.mozilla-1552590 firefox-67.0/m pref("widget.window-transforms.disabled", false); -diff -up firefox-67.0/toolkit/moz.configure.mozilla-1552590 firefox-67.0/toolkit/moz.configure ---- firefox-67.0/toolkit/moz.configure.mozilla-1552590 2019-05-27 12:15:31.992414348 +0200 -+++ firefox-67.0/toolkit/moz.configure 2019-05-27 12:15:32.031414339 +0200 -@@ -265,6 +265,14 @@ def wayland_headers(wayland, toolkit_gtk + #ifdef XP_WIN + // Whether to disable the automatic detection and use of direct2d. + pref("gfx.direct2d.disabled", false); + + // Whether to attempt to enable Direct2D regardless of automatic detection or +diff --git a/toolkit/moz.configure b/toolkit/moz.configure +--- a/toolkit/moz.configure ++++ b/toolkit/moz.configure +@@ -260,16 +260,24 @@ def wayland_headers(wayland, toolkit_gtk + if toolkit_gtk and artifacts: + return True + return wayland + + set_config('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True)) set_define('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True)) @@ -405,2103 +433,2269 @@ diff -up firefox-67.0/toolkit/moz.configure.mozilla-1552590 firefox-67.0/toolkit # GL Provider # ============================================================== option('--with-gl-provider', nargs=1, help='Set GL provider backend type') -diff -up firefox-67.0/widget/gtk/moz.build.mozilla-1552590 firefox-67.0/widget/gtk/moz.build ---- firefox-67.0/widget/gtk/moz.build.mozilla-1552590 2019-05-17 02:34:02.000000000 +0200 -+++ firefox-67.0/widget/gtk/moz.build 2019-05-27 12:15:32.031414339 +0200 -@@ -101,6 +101,9 @@ if CONFIG['MOZ_WAYLAND']: - 'nsWaylandDisplay.cpp', - 'WindowSurfaceWayland.cpp', - ] -+ EXPORTS.mozilla.widget += [ -+ 'nsWaylandDisplay.h', -+ ] - if CONFIG['ACCESSIBILITY']: - UNIFIED_SOURCES += [ -diff -up firefox-67.0/widget/gtk/mozcontainer.cpp.mozilla-1552590 firefox-67.0/widget/gtk/mozcontainer.cpp ---- firefox-67.0/widget/gtk/mozcontainer.cpp.mozilla-1552590 2019-05-27 12:15:32.026414340 +0200 -+++ firefox-67.0/widget/gtk/mozcontainer.cpp 2019-05-27 12:15:32.031414339 +0200 -@@ -567,7 +567,7 @@ struct wl_surface *moz_container_get_wl_ - moz_container_get_scale(container)); - - wl_surface_commit(container->surface); -- wl_display_flush(waylandDisplay->GetDisplay()); -+ wl_display_flush(waylandDisplay->GetDisplay()); - } + @depends('--with-gl-provider') + def gl_provider(value): + if value: + return value[0] +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -30,16 +30,19 @@ extern mozilla::LazyLogModule gWidgetWay + MOZ_LOG(gWidgetWaylandLog, mozilla::LogLevel::Debug, args) + #else + # define LOGWAYLAND(args) + #endif /* MOZ_LOGGING */ - return container->surface; -@@ -596,9 +596,13 @@ gboolean moz_container_has_wl_egl_window + namespace mozilla { + namespace widget { - gboolean moz_container_surface_needs_clear(MozContainer *container) { - gboolean state = container->surface_needs_clear; -- container->surface_needs_clear = false; - return state; - } -+ -+void moz_container_surface_cleared(MozContainer* container) { -+ container->surface_needs_clear = false; -+} ++bool WindowSurfaceWayland::mUseDMABuf = false; ++bool WindowSurfaceWayland::mUseDMABufInitialized = false; + - #endif + /* + Wayland multi-thread rendering scheme - void moz_container_force_default_visual(MozContainer *container) { -diff -up firefox-67.0/widget/gtk/mozcontainer.h.mozilla-1552590 firefox-67.0/widget/gtk/mozcontainer.h ---- firefox-67.0/widget/gtk/mozcontainer.h.mozilla-1552590 2019-05-27 12:15:32.021414342 +0200 -+++ firefox-67.0/widget/gtk/mozcontainer.h 2019-05-27 12:15:32.031414339 +0200 -@@ -101,6 +101,7 @@ struct wl_egl_window *moz_container_get_ + Every rendering thread (main thread, compositor thread) contains its own + nsWaylandDisplay object connected to Wayland compositor (Mutter, Weston, etc.) - gboolean moz_container_has_wl_egl_window(MozContainer *container); - gboolean moz_container_surface_needs_clear(MozContainer *container); -+void moz_container_surface_cleared(MozContainer* container); - void moz_container_scale_changed(MozContainer *container, - GtkAllocation *aAllocation); - void moz_container_set_initial_draw_callback( -diff -up firefox-67.0/widget/gtk/mozwayland/moz.build.mozilla-1552590 firefox-67.0/widget/gtk/mozwayland/moz.build ---- firefox-67.0/widget/gtk/mozwayland/moz.build.mozilla-1552590 2019-05-17 02:35:09.000000000 +0200 -+++ firefox-67.0/widget/gtk/mozwayland/moz.build 2019-05-27 12:15:32.031414339 +0200 -@@ -7,7 +7,11 @@ - SOURCES += [ - 'mozwayland.c', - ] -+EXPORTS.mozilla.widget += [ -+ 'mozwayland.h', -+] + WindowSurfaceWayland implements WindowSurface class and draws nsWindow by + WindowSurface interface (Lock, Commit) to screen through nsWaylandDisplay. +@@ -255,120 +258,183 @@ WaylandShmPool::~WaylandShmPool() { - SharedLibrary('mozwayland') + static void buffer_release(void* data, wl_buffer* buffer) { + auto surface = reinterpret_cast(data); + surface->Detach(buffer); + } - CFLAGS += CONFIG['TK_CFLAGS'] -+ -diff -up firefox-67.0/widget/gtk/nsWaylandDisplay.cpp.mozilla-1552590 firefox-67.0/widget/gtk/nsWaylandDisplay.cpp ---- firefox-67.0/widget/gtk/nsWaylandDisplay.cpp.mozilla-1552590 2019-05-27 12:15:32.027414340 +0200 -+++ firefox-67.0/widget/gtk/nsWaylandDisplay.cpp 2019-05-27 13:41:39.335407884 +0200 -@@ -7,10 +7,6 @@ + static const struct wl_buffer_listener buffer_listener = {buffer_release}; - #include "nsWaylandDisplay.h" +-void WindowBackBuffer::Create(int aWidth, int aHeight) { ++void WindowBackBufferShm::Create(int aWidth, int aHeight) { + MOZ_ASSERT(!IsAttached(), "We can't resize attached buffers."); --#include "base/message_loop.h" // for MessageLoop --#include "base/task.h" // for NewRunnableMethod, etc --#include "mozilla/StaticMutex.h" -- - namespace mozilla { - namespace widget { + int newBufferSize = aWidth * aHeight * BUFFER_BPP; + mShmPool.Resize(newBufferSize); -@@ -58,7 +54,7 @@ static nsWaylandDisplay *WaylandDisplayG - return nullptr; + mWaylandBuffer = + wl_shm_pool_create_buffer(mShmPool.GetShmPool(), 0, aWidth, aHeight, + aWidth * BUFFER_BPP, WL_SHM_FORMAT_ARGB8888); + wl_proxy_set_queue((struct wl_proxy*)mWaylandBuffer, +- mWaylandDisplay->GetEventQueue()); ++ GetWaylandDisplay()->GetEventQueue()); + wl_buffer_add_listener(mWaylandBuffer, &buffer_listener, this); + + mWidth = aWidth; + mHeight = aHeight; + + LOGWAYLAND(( + "%s [%p] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, (void*)this, + (void*)mWaylandBuffer, + mWaylandBuffer ? wl_proxy_get_id((struct wl_proxy*)mWaylandBuffer) : -1)); } --nsWaylandDisplay *WaylandDisplayGet(GdkDisplay *aGdkDisplay) { -+nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay) { - if (!aGdkDisplay) { - aGdkDisplay = gdk_display_get_default(); - } -@@ -90,84 +86,193 @@ static void WaylandDisplayLoopLocked(wl_ +-void WindowBackBuffer::Release() { ++void WindowBackBufferShm::Release() { + LOGWAYLAND(("%s [%p]\n", __PRETTY_FUNCTION__, (void*)this)); - static void WaylandDisplayLoop(wl_display *aDisplay) { - MOZ_ASSERT(!NS_IsMainThread()); -+ - StaticMutexAutoLock lock(gWaylandDisplaysMutex); - WaylandDisplayLoopLocked(aDisplay, lock); + wl_buffer_destroy(mWaylandBuffer); + mWidth = mHeight = 0; + } + +-void WindowBackBuffer::Clear() { ++void WindowBackBufferShm::Clear() { + memset(mShmPool.GetImageData(), 0, mHeight * mWidth * BUFFER_BPP); + } + +-WindowBackBuffer::WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay, +- int aWidth, int aHeight) +- : mShmPool(aWaylandDisplay, aWidth * aHeight * BUFFER_BPP), ++WindowBackBufferShm::WindowBackBufferShm(nsWaylandDisplay* aWaylandDisplay, ++ int aWidth, int aHeight) ++ : WindowBackBuffer(aWaylandDisplay), ++ mShmPool(aWaylandDisplay, aWidth * aHeight * BUFFER_BPP), + mWaylandBuffer(nullptr), + mWidth(aWidth), + mHeight(aHeight), +- mAttached(false), +- mWaylandDisplay(aWaylandDisplay) { ++ mAttached(false) { + Create(aWidth, aHeight); + } + +-WindowBackBuffer::~WindowBackBuffer() { Release(); } ++WindowBackBufferShm::~WindowBackBufferShm() { Release(); } + +-bool WindowBackBuffer::Resize(int aWidth, int aHeight) { ++bool WindowBackBufferShm::Resize(int aWidth, int aHeight) { + if (aWidth == mWidth && aHeight == mHeight) return true; + + LOGWAYLAND( + ("%s [%p] %d %d\n", __PRETTY_FUNCTION__, (void*)this, aWidth, aHeight)); + + Release(); + Create(aWidth, aHeight); + + return (mWaylandBuffer != nullptr); } --void nsWaylandDisplay::SetShm(wl_shm *aShm) { mShm = aShm; } -+void nsWaylandDisplay::SetShm(wl_shm* aShm) { mShm = aShm; } + void WindowBackBuffer::Attach(wl_surface* aSurface) { +- LOGWAYLAND(( +- "%s [%p] wl_surface %p ID %d wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, +- (void*)this, (void*)aSurface, +- aSurface ? wl_proxy_get_id((struct wl_proxy*)aSurface) : -1, +- (void*)mWaylandBuffer, +- mWaylandBuffer ? wl_proxy_get_id((struct wl_proxy*)mWaylandBuffer) : -1)); ++ LOGWAYLAND( ++ ("%s [%p] wl_surface %p ID %d wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, ++ (void*)this, (void*)aSurface, ++ aSurface ? wl_proxy_get_id((struct wl_proxy*)aSurface) : -1, ++ (void*)GetWlBuffer(), ++ GetWlBuffer() ? wl_proxy_get_id((struct wl_proxy*)GetWlBuffer()) : -1)); --void nsWaylandDisplay::SetSubcompositor(wl_subcompositor *aSubcompositor) { -+void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) { - mSubcompositor = aSubcompositor; +- wl_surface_attach(aSurface, mWaylandBuffer, 0, 0); ++ wl_surface_attach(aSurface, GetWlBuffer(), 0, 0); + wl_surface_commit(aSurface); +- wl_display_flush(mWaylandDisplay->GetDisplay()); +- mAttached = true; ++ wl_display_flush(GetWaylandDisplay()->GetDisplay()); ++ SetAttached(); } - void nsWaylandDisplay::SetDataDeviceManager( -- wl_data_device_manager *aDataDeviceManager) { -+ wl_data_device_manager* aDataDeviceManager) { - mDataDeviceManager = aDataDeviceManager; +-void WindowBackBuffer::Detach(wl_buffer* aBuffer) { ++void WindowBackBufferShm::Detach(wl_buffer* aBuffer) { + LOGWAYLAND(("%s [%p] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, (void*)this, + (void*)aBuffer, + aBuffer ? wl_proxy_get_id((struct wl_proxy*)aBuffer) : -1)); + + mAttached = false; } --void nsWaylandDisplay::SetSeat(wl_seat *aSeat) { mSeat = aSeat; } -+void nsWaylandDisplay::SetSeat(wl_seat* aSeat) { mSeat = aSeat; } +-bool WindowBackBuffer::SetImageDataFromBuffer( ++bool WindowBackBufferShm::SetImageDataFromBuffer( + class WindowBackBuffer* aSourceBuffer) { +- if (!IsMatchingSize(aSourceBuffer)) { +- Resize(aSourceBuffer->mWidth, aSourceBuffer->mHeight); ++ auto sourceBuffer = static_cast(aSourceBuffer); ++ if (!IsMatchingSize(sourceBuffer)) { ++ Resize(sourceBuffer->mWidth, sourceBuffer->mHeight); + } - void nsWaylandDisplay::SetPrimarySelectionDeviceManager( -- gtk_primary_selection_device_manager *aPrimarySelectionDeviceManager) { -+ gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager) { - mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager; + mShmPool.SetImageDataFromPool( +- &aSourceBuffer->mShmPool, +- aSourceBuffer->mWidth * aSourceBuffer->mHeight * BUFFER_BPP); ++ &sourceBuffer->mShmPool, ++ sourceBuffer->mWidth * sourceBuffer->mHeight * BUFFER_BPP); + return true; } --static void global_registry_handler(void *data, wl_registry *registry, -- uint32_t id, const char *interface, -+#ifdef HAVE_LIBDRM -+void nsWaylandDisplay::SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf) { -+ mDmabuf = aDmabuf; +-already_AddRefed WindowBackBuffer::Lock() { ++already_AddRefed WindowBackBufferShm::Lock() { + LOGWAYLAND(( + "%s [%p] [%d x %d] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, + (void*)this, mWidth, mHeight, (void*)mWaylandBuffer, + mWaylandBuffer ? wl_proxy_get_id((struct wl_proxy*)mWaylandBuffer) : -1)); + + gfx::IntSize lockSize(mWidth, mHeight); + return gfxPlatform::CreateDrawTargetForData( + static_cast(mShmPool.GetImageData()), lockSize, +- BUFFER_BPP * mWidth, mFormat); ++ BUFFER_BPP * mWidth, GetSurfaceFormat()); +} + -+GbmFormat* nsWaylandDisplay::GetGbmFormat(bool aHasAlpha) { -+ GbmFormat* format = aHasAlpha ? &mARGBFormat : &mXRGBFormat; -+ return format->mIsSupported ? format : nullptr; ++#ifdef HAVE_LIBDRM ++WindowBackBufferDMABuf::WindowBackBufferDMABuf( ++ nsWaylandDisplay* aWaylandDisplay, int aWidth, int aHeight) ++ : WindowBackBuffer(aWaylandDisplay) { ++ mDMAbufSurface.Create(aWidth, aHeight); +} + -+void nsWaylandDisplay::AddFormatModifier(bool aHasAlpha, int aFormat, -+ uint32_t mModifierHi, -+ uint32_t mModifierLo) { -+ GbmFormat* format = aHasAlpha ? &mARGBFormat : &mXRGBFormat; -+ format->mIsSupported = true; -+ format->mHasAlpha = aHasAlpha; -+ format->mFormat = aFormat; -+ format->mModifiersCount++; -+ format->mModifiers = -+ (uint64_t*)realloc(format->mModifiers, -+ format->mModifiersCount * sizeof(*format->mModifiers)); -+ format->mModifiers[format->mModifiersCount - 1] = -+ ((uint64_t)mModifierHi << 32) | mModifierLo; -+} ++WindowBackBufferDMABuf::~WindowBackBufferDMABuf() { mDMAbufSurface.Release(); } + -+static void dmabuf_modifiers(void* data, -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf, -+ uint32_t format, uint32_t modifier_hi, -+ uint32_t modifier_lo) { -+ auto display = reinterpret_cast(data); -+ switch (format) { -+ case DRM_FORMAT_ARGB8888: -+ display->AddFormatModifier(true, format, modifier_hi, modifier_lo); -+ break; -+ case DRM_FORMAT_XRGB8888: -+ display->AddFormatModifier(false, format, modifier_hi, modifier_lo); -+ break; -+ default: -+ break; -+ } -+} ++already_AddRefed WindowBackBufferDMABuf::Lock() { ++ LOGWAYLAND( ++ ("%s [%p] [%d x %d] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, ++ (void*)this, GetWidth(), GetHeight(), (void*)GetWlBuffer(), ++ GetWlBuffer() ? wl_proxy_get_id((struct wl_proxy*)GetWlBuffer()) : -1)); + -+static void dmabuf_format(void* data, -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf, -+ uint32_t format) { -+ // XXX: deprecated ++ uint32_t stride; ++ void* pixels = mDMAbufSurface.Map(&stride); ++ gfx::IntSize lockSize(GetWidth(), GetHeight()); ++ return gfxPlatform::CreateDrawTargetForData( ++ static_cast(pixels), lockSize, stride, ++ GetSurfaceFormat()); +} + -+static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { -+ dmabuf_format, dmabuf_modifiers}; -+#endif ++void WindowBackBufferDMABuf::Unlock() { mDMAbufSurface.Unmap(); } + -+static void global_registry_handler(void* data, wl_registry* registry, -+ uint32_t id, const char* interface, - uint32_t version) { -- auto display = reinterpret_cast(data); -- if (!display) -- return; -+ auto display = reinterpret_cast(data); -+ if (!display) return; ++bool WindowBackBufferDMABuf::IsAttached() { ++ return mDMAbufSurface.WLBufferIsAttached(); + } - if (strcmp(interface, "wl_shm") == 0) { -- auto shm = static_cast( -+ auto shm = static_cast( - wl_registry_bind(registry, id, &wl_shm_interface, 1)); -- wl_proxy_set_queue((struct wl_proxy *)shm, display->GetEventQueue()); -+ wl_proxy_set_queue((struct wl_proxy*)shm, display->GetEventQueue()); - display->SetShm(shm); - } else if (strcmp(interface, "wl_data_device_manager") == 0) { - int data_device_manager_version = MIN(version, 3); -- auto data_device_manager = static_cast( -+ auto data_device_manager = static_cast( - wl_registry_bind(registry, id, &wl_data_device_manager_interface, - data_device_manager_version)); -- wl_proxy_set_queue((struct wl_proxy *)data_device_manager, -+ wl_proxy_set_queue((struct wl_proxy*)data_device_manager, - display->GetEventQueue()); - display->SetDataDeviceManager(data_device_manager); - } else if (strcmp(interface, "wl_seat") == 0) { -- auto seat = static_cast( -+ auto seat = static_cast( - wl_registry_bind(registry, id, &wl_seat_interface, 1)); -- wl_proxy_set_queue((struct wl_proxy *)seat, display->GetEventQueue()); -+ wl_proxy_set_queue((struct wl_proxy*)seat, display->GetEventQueue()); - display->SetSeat(seat); - } else if (strcmp(interface, "gtk_primary_selection_device_manager") == 0) { - auto primary_selection_device_manager = -- static_cast(wl_registry_bind( -+ static_cast(wl_registry_bind( - registry, id, >k_primary_selection_device_manager_interface, 1)); -- wl_proxy_set_queue((struct wl_proxy *)primary_selection_device_manager, -+ wl_proxy_set_queue((struct wl_proxy*)primary_selection_device_manager, - display->GetEventQueue()); - display->SetPrimarySelectionDeviceManager(primary_selection_device_manager); - } else if (strcmp(interface, "wl_subcompositor") == 0) { -- auto subcompositor = static_cast( -+ auto subcompositor = static_cast( - wl_registry_bind(registry, id, &wl_subcompositor_interface, 1)); -- wl_proxy_set_queue((struct wl_proxy *)subcompositor, -+ wl_proxy_set_queue((struct wl_proxy*)subcompositor, - display->GetEventQueue()); - display->SetSubcompositor(subcompositor); - } -+#ifdef HAVE_LIBDRM -+ else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version > 2) { -+ auto dmabuf = static_cast( -+ wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 3)); -+ display->SetDmabuf(dmabuf); -+ zwp_linux_dmabuf_v1_add_listener(dmabuf, &dmabuf_listener, data); -+ } -+#endif - } - --static void global_registry_remover(void *data, wl_registry *registry, -+static void global_registry_remover(void* data, wl_registry* registry, - uint32_t id) {} - - static const struct wl_registry_listener registry_listener = { - global_registry_handler, global_registry_remover}; - --bool nsWaylandDisplay::DisplayLoop() { -+bool nsWaylandDisplay::DispatchEventQueue() { - wl_display_dispatch_queue_pending(mDisplay, mEventQueue); - return true; - } - --bool nsWaylandDisplay::Matches(wl_display *aDisplay) { -+bool nsWaylandDisplay::Matches(wl_display* aDisplay) { - return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay; - } - -+#ifdef HAVE_LIBDRM -+bool nsWaylandDisplay::ConfigureGbm() { -+ if (!nsGbmLib::IsAvailable()) { -+ return false; -+ } ++void WindowBackBufferDMABuf::SetAttached() { ++ return mDMAbufSurface.WLBufferSetAttached(); ++} + -+ // TODO -+ const char* drm_render_node = getenv("MOZ_WAYLAND_DRM_DEVICE"); -+ if (!drm_render_node) { -+ drm_render_node = "/dev/dri/renderD128"; -+ } ++int WindowBackBufferDMABuf::GetWidth() { return mDMAbufSurface.GetWidth(); } + -+ mGbmFd = open(drm_render_node, O_RDWR); -+ if (mGbmFd < 0) { -+ NS_WARNING( -+ nsPrintfCString("Failed to open drm render node %s\n", drm_render_node) -+ .get()); -+ return false; -+ } ++int WindowBackBufferDMABuf::GetHeight() { return mDMAbufSurface.GetHeight(); } + -+ mGbmDevice = nsGbmLib::CreateDevice(mGbmFd); -+ if (mGbmDevice == nullptr) { -+ NS_WARNING(nsPrintfCString("Failed to create drm render device %s\n", -+ drm_render_node) -+ .get()); -+ close(mGbmFd); -+ return false; -+ } ++wl_buffer* WindowBackBufferDMABuf::GetWlBuffer() { ++ return mDMAbufSurface.GetWLBuffer(); ++} + -+ return true; ++bool WindowBackBufferDMABuf::IsLocked() { return mDMAbufSurface.IsMapped(); } ++ ++bool WindowBackBufferDMABuf::Resize(int aWidth, int aHeight) { ++ return mDMAbufSurface.Resize(aWidth, aHeight); +} + -+gbm_device* nsWaylandDisplay::GetGbmDevice() { -+ if (!mGdmConfigured) { -+ ConfigureGbm(); -+ mGdmConfigured = true; -+ } -+ return mGbmDevice; ++bool WindowBackBufferDMABuf::SetImageDataFromBuffer( ++ class WindowBackBuffer* aSourceBuffer) { ++ WindowBackBufferDMABuf* source = ++ static_cast(aSourceBuffer); ++ mDMAbufSurface.CopyFrom(&source->mDMAbufSurface); ++ return true; +} + -+int nsWaylandDisplay::GetGbmDeviceFd() { -+ if (!mGdmConfigured) { -+ ConfigureGbm(); -+ mGdmConfigured = true; -+ } -+ return mGbmFd; ++void WindowBackBufferDMABuf::Detach(wl_buffer* aBuffer) { ++ mDMAbufSurface.WLBufferDetach(); +} -+#endif + - nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay) - : mThreadId(PR_GetCurrentThread()), - mDisplay(aDisplay), -@@ -177,7 +282,17 @@ nsWaylandDisplay::nsWaylandDisplay(wl_di - mSeat(nullptr), - mShm(nullptr), - mPrimarySelectionDeviceManager(nullptr), -- mRegistry(nullptr) { -+ mRegistry(nullptr) -+#ifdef HAVE_LIBDRM -+ , -+ mGbmDevice(nullptr), -+ mGbmFd(-1), -+ mGdmConfigured(false), -+ mExplicitSync(false), -+ mXRGBFormat({false, false, -1, nullptr, 0}), -+ mARGBFormat({false, false, -1, nullptr, 0}) ++void WindowBackBufferDMABuf::Clear() { mDMAbufSurface.Clear(); } +#endif -+{ - mRegistry = wl_display_get_registry(mDisplay); - wl_registry_add_listener(mRegistry, ®istry_listener, this); ++ + static void frame_callback_handler(void* data, struct wl_callback* callback, + uint32_t time) { + auto surface = reinterpret_cast(data); + surface->FrameCallbackHandler(); -@@ -190,7 +305,7 @@ nsWaylandDisplay::nsWaylandDisplay(wl_di - mEventQueue = wl_display_create_queue(mDisplay); - MessageLoop::current()->PostTask(NewRunnableFunction( - "WaylandDisplayLoop", &WaylandDisplayLoop, mDisplay)); -- wl_proxy_set_queue((struct wl_proxy *)mRegistry, mEventQueue); -+ wl_proxy_set_queue((struct wl_proxy*)mRegistry, mEventQueue); - wl_display_roundtrip_queue(mDisplay, mEventQueue); - wl_display_roundtrip_queue(mDisplay, mEventQueue); - } -@@ -209,5 +324,79 @@ nsWaylandDisplay::~nsWaylandDisplay() { + gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time); + } + +@@ -412,23 +478,60 @@ WindowSurfaceWayland::~WindowSurfaceWayl + + for (int i = 0; i < BACK_BUFFER_NUM; i++) { + if (mBackupBuffer[i]) { + delete mBackupBuffer[i]; + } } } +-WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(int aWidth, +- int aHeight) { ++bool WindowSurfaceWayland::UseDMABufBackend() { ++ if (!mUseDMABufInitialized) { +#ifdef HAVE_LIBDRM -+void* nsGbmLib::sGbmLibHandle = nullptr; -+void* nsGbmLib::sXf86DrmLibHandle = nullptr; -+bool nsGbmLib::sLibLoaded = false; -+CreateDeviceFunc nsGbmLib::sCreateDevice; -+CreateFunc nsGbmLib::sCreate; -+CreateWithModifiersFunc nsGbmLib::sCreateWithModifiers; -+GetModifierFunc nsGbmLib::sGetModifier; -+GetStrideFunc nsGbmLib::sGetStride; -+GetFdFunc nsGbmLib::sGetFd; -+DestroyFunc nsGbmLib::sDestroy; -+MapFunc nsGbmLib::sMap; -+UnmapFunc nsGbmLib::sUnmap; -+GetPlaneCountFunc nsGbmLib::sGetPlaneCount; -+GetHandleForPlaneFunc nsGbmLib::sGetHandleForPlane; -+GetStrideForPlaneFunc nsGbmLib::sGetStrideForPlane; -+GetOffsetFunc nsGbmLib::sGetOffset; -+DrmPrimeHandleToFDFunc nsGbmLib::sDrmPrimeHandleToFD; -+ -+bool nsGbmLib::IsAvailable() { -+ if (!Load()) { -+ return false; -+ } -+ return sCreateDevice != nullptr && sCreate != nullptr && -+ sCreateWithModifiers != nullptr && sGetModifier != nullptr && -+ sGetStride != nullptr && sGetFd != nullptr && sDestroy != nullptr && -+ sMap != nullptr && sUnmap != nullptr; -+} -+ -+bool nsGbmLib::IsModifierAvailable() { -+ if (!Load()) { -+ return false; ++ if (WaylandDMABufSurface::IsAvailable()) { ++ mUseDMABuf = ++ Preferences::GetBool("gfx.wayland_dmabuf_backend.enabled", false); ++ } ++#endif ++ mUseDMABufInitialized = true; + } -+ return sDrmPrimeHandleToFD != nullptr; ++ return mUseDMABuf; +} + -+bool nsGbmLib::Load() { -+ if (!sGbmLibHandle && !sLibLoaded) { -+ sLibLoaded = true; -+ -+ sGbmLibHandle = dlopen("libgbm.so", RTLD_LAZY | RTLD_LOCAL); -+ if (!sGbmLibHandle) { -+ return false; ++WindowBackBuffer* WindowSurfaceWayland::CreateWaylandBuffer(int aWidth, ++ int aHeight) { ++ if (UseDMABufBackend()) { ++ static bool sDMABufBufferCreated = false; ++ WindowBackBuffer* buffer = ++ new WindowBackBufferDMABuf(mWaylandDisplay, aWidth, aHeight); ++ if (buffer) { ++ sDMABufBufferCreated = true; ++ return buffer; + } -+ -+ sCreateDevice = (CreateDeviceFunc)dlsym(sGbmLibHandle, "gbm_create_device"); -+ sCreate = (CreateFunc)dlsym(sGbmLibHandle, "gbm_bo_create"); -+ sCreateWithModifiers = (CreateWithModifiersFunc)dlsym( -+ sGbmLibHandle, "gbm_bo_create_with_modifiers"); -+ sGetModifier = (GetModifierFunc)dlsym(sGbmLibHandle, "gbm_bo_get_modifier"); -+ sGetStride = (GetStrideFunc)dlsym(sGbmLibHandle, "gbm_bo_get_stride"); -+ sGetFd = (GetFdFunc)dlsym(sGbmLibHandle, "gbm_bo_get_fd"); -+ sDestroy = (DestroyFunc)dlsym(sGbmLibHandle, "gbm_bo_destroy"); -+ sMap = (MapFunc)dlsym(sGbmLibHandle, "gbm_bo_map"); -+ sUnmap = (UnmapFunc)dlsym(sGbmLibHandle, "gbm_bo_unmap"); -+ sGetPlaneCount = -+ (GetPlaneCountFunc)dlsym(sGbmLibHandle, "gbm_bo_get_plane_count"); -+ sGetHandleForPlane = (GetHandleForPlaneFunc)dlsym( -+ sGbmLibHandle, "gbm_bo_get_handle_for_plane"); -+ sGetStrideForPlane = (GetStrideForPlaneFunc)dlsym( -+ sGbmLibHandle, "gbm_bo_get_stride_for_plane"); -+ sGetOffset = (GetOffsetFunc)dlsym(sGbmLibHandle, "gbm_bo_get_offset"); -+ -+ sXf86DrmLibHandle = dlopen("libdrm.so", RTLD_LAZY | RTLD_LOCAL); -+ if (sXf86DrmLibHandle) { -+ sDrmPrimeHandleToFD = (DrmPrimeHandleToFDFunc)dlsym(sXf86DrmLibHandle, -+ "drmPrimeHandleToFD"); ++ // If this is the first failure and there's no dmabuf already active ++ // we can safely fallback to Shm. Otherwise we can't mix DMAbuf and ++ // SHM buffers so just fails now. ++ if (sDMABufBufferCreated) { ++ NS_WARNING("Failed to allocate DMABuf buffer!"); ++ return nullptr; ++ } else { ++ NS_WARNING("Wayland DMABuf failed, switched back to Shm backend!"); ++ mUseDMABuf = false; + } + } -+ -+ return sGbmLibHandle; ++ return new WindowBackBufferShm(mWaylandDisplay, aWidth, aHeight); +} -+#endif + - } // namespace widget - } // namespace mozilla -diff -up firefox-67.0/widget/gtk/nsWaylandDisplay.h.mozilla-1552590 firefox-67.0/widget/gtk/nsWaylandDisplay.h ---- firefox-67.0/widget/gtk/nsWaylandDisplay.h.mozilla-1552590 2019-05-27 12:15:32.027414340 +0200 -+++ firefox-67.0/widget/gtk/nsWaylandDisplay.h 2019-05-27 13:38:56.012798548 +0200 -@@ -5,19 +5,38 @@ - * 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/. */ ++WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw( ++ int aWidth, int aHeight, bool aFullScreenUpdate, bool aNoBackBufferCopy) { + if (!mWaylandBuffer) { + LOGWAYLAND(("%s [%p] Create [%d x %d]\n", __PRETTY_FUNCTION__, (void*)this, + aWidth, aHeight)); --#ifndef __MOZ_WAYLAND_REGISTRY_H__ --#define __MOZ_WAYLAND_REGISTRY_H__ -+#ifndef __MOZ_WAYLAND_DISPLAY_H__ -+#define __MOZ_WAYLAND_DISPLAY_H__ +- mWaylandBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); ++ mWaylandBuffer = CreateWaylandBuffer(aWidth, aHeight); + mWaitToFullScreenUpdate = true; + return mWaylandBuffer; + } --#include "mozwayland/mozwayland.h" --#include "wayland/gtk-primary-selection-client-protocol.h" -+#include "mozilla/widget/mozwayland.h" -+#include "mozilla/widget/gtk-primary-selection-client-protocol.h" + if (!mWaylandBuffer->IsAttached()) { + if (!mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) { + mWaylandBuffer->Resize(aWidth, aHeight); + // There's a chance that scale factor has been changed +@@ -444,75 +547,89 @@ WindowBackBuffer* WindowSurfaceWayland:: + MOZ_ASSERT(!mPendingCommit, + "Uncommitted buffer switch, screen artifacts ahead."); --namespace mozilla { --namespace widget { -+#include "base/message_loop.h" // for MessageLoop -+#include "base/task.h" // for NewRunnableMethod, etc -+#include "mozilla/StaticMutex.h" -+ -+#ifdef HAVE_LIBDRM -+# include -+# include -+# include -+# include "mozilla/widget/linux-dmabuf-unstable-v1-client-protocol.h" -+#endif + // Front buffer is used by compositor, select a back buffer + int availableBuffer; + for (availableBuffer = 0; availableBuffer < BACK_BUFFER_NUM; + availableBuffer++) { + if (!mBackupBuffer[availableBuffer]) { +- mBackupBuffer[availableBuffer] = +- new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); ++ mBackupBuffer[availableBuffer] = CreateWaylandBuffer(aWidth, aHeight); + break; + } - // TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() - // with compositor event loop. - #define EVENT_LOOP_DELAY (1000 / 240) + if (!mBackupBuffer[availableBuffer]->IsAttached()) { + break; + } + } -+namespace mozilla { -+namespace widget { -+ -+struct GbmFormat { -+ bool mIsSupported; -+ bool mHasAlpha; -+ int mFormat; -+ uint64_t* mModifiers; -+ int mModifiersCount; -+}; + if (MOZ_UNLIKELY(availableBuffer == BACK_BUFFER_NUM)) { + LOGWAYLAND(("%s [%p] No drawing buffer available!\n", __PRETTY_FUNCTION__, + (void*)this)); + NS_WARNING("No drawing buffer available"); + 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; ++ } + - // Our general connection to Wayland display server, - // holds our display connection and runs event loop. - class nsWaylandDisplay { -@@ -26,6 +45,7 @@ class nsWaylandDisplay { - virtual ~nsWaylandDisplay(); + WindowBackBuffer* lastWaylandBuffer = mWaylandBuffer; + mWaylandBuffer = mBackupBuffer[availableBuffer]; + mBackupBuffer[availableBuffer] = lastWaylandBuffer; - bool DisplayLoop(); -+ bool DispatchEventQueue(); - bool Matches(wl_display* aDisplay); +- if (lastWaylandBuffer->IsMatchingSize(aWidth, aHeight)) { +- LOGWAYLAND(("%s [%p] Copy from old buffer [%d x %d]\n", __PRETTY_FUNCTION__, +- (void*)this, aWidth, aHeight)); ++ 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. +- mWaylandBuffer->SetImageDataFromBuffer(lastWaylandBuffer); ++ // 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] Resize 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; + } - wl_display* GetDisplay() { return mDisplay; }; -@@ -47,7 +67,22 @@ class nsWaylandDisplay { - void SetPrimarySelectionDeviceManager( - gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager); + return mWaylandBuffer; + } --private: -+#ifdef HAVE_LIBDRM -+ void SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf); -+ zwp_linux_dmabuf_v1* GetDmabuf() { return mDmabuf; }; -+ gbm_device* GetGbmDevice(); -+ int GetGbmDeviceFd(); -+ bool IsExplicitSyncEnabled() { return mExplicitSync; } -+ GbmFormat* GetGbmFormat(bool aHasAlpha); -+ void AddFormatModifier(bool aHasAlpha, int aFormat, uint32_t mModifierHi, -+ uint32_t mModifierLo); -+#endif + already_AddRefed WindowSurfaceWayland::LockWaylandBuffer( +- int aWidth, int aHeight, bool aClearBuffer) { +- WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight); ++ int aWidth, int aHeight, bool aClearBuffer, bool aFullScreenUpdate, ++ bool aNoBackBufferCopy) { ++ WindowBackBuffer* buffer = GetWaylandBufferToDraw( ++ aWidth, aHeight, aFullScreenUpdate, aNoBackBufferCopy); + if (!buffer) { +- NS_WARNING( +- "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); ++ if (!aNoBackBufferCopy) { ++ NS_WARNING( ++ "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); ++ } + return nullptr; + } + + if (aClearBuffer) { + buffer->Clear(); + } + + return buffer->Lock(); + } + ++void WindowSurfaceWayland::UnlockWaylandBuffer() { mWaylandBuffer->Unlock(); } + -+ private: -+#ifdef HAVE_LIBDRM -+ bool ConfigureGbm(); -+#endif + already_AddRefed WindowSurfaceWayland::LockImageSurface( + const gfx::IntSize& aLockSize) { + if (!mImageSurface || mImageSurface->CairoStatus() || + !(aLockSize <= mImageSurface->GetSize())) { + mImageSurface = new gfxImageSurface( + aLockSize, + SurfaceFormatToImageFormat(WindowBackBuffer::GetSurfaceFormat())); + if (mImageSurface->CairoStatus()) { +@@ -552,20 +669,28 @@ already_AddRefed Window + + // Are we asked for entire nsWindow to draw? + mDrawToWaylandBufferDirectly = + (aRegion.GetNumRects() == 1 && bounds.x == 0 && bounds.y == 0 && + lockSize.width == screenRect.width && + lockSize.height == screenRect.height); + + if (mDrawToWaylandBufferDirectly) { +- RefPtr dt = +- LockWaylandBuffer(screenRect.width, screenRect.height, +- mWindow->WaylandSurfaceNeedsClear()); ++ // If there's any pending image commit scratch them as we're going ++ // to redraw the whole sceen anyway. ++ mDelayedImageCommits.Clear(); + - PRThread* mThreadId; - wl_display* mDisplay; - wl_event_queue* mEventQueue; -@@ -56,12 +91,113 @@ private: - wl_seat* mSeat; - wl_shm* mShm; - gtk_primary_selection_device_manager* mPrimarySelectionDeviceManager; -- wl_registry *mRegistry; -+ wl_registry* mRegistry; -+#ifdef HAVE_LIBDRM -+ zwp_linux_dmabuf_v1* mDmabuf; -+ gbm_device* mGbmDevice; -+ int mGbmFd; -+ bool mGdmConfigured; -+ bool mExplicitSync; -+ GbmFormat mXRGBFormat; -+ GbmFormat mARGBFormat; -+#endif - }; ++ bool needsClear = mWindow->WaylandSurfaceNeedsClear(); ++ RefPtr dt = LockWaylandBuffer( ++ screenRect.width, screenRect.height, needsClear, ++ /* aFullScreenUpdate */ true, /* aNoBackBufferCopy */ true); + if (dt) { ++ if (needsClear) { ++ mWindow->WaylandSurfaceCleared(); ++ } + // 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; + } + return dt.forget(); +@@ -574,52 +699,94 @@ already_AddRefed Window + // We don't have any front buffer available. Try indirect drawing + // to mImageSurface which is mirrored to front buffer at commit. + mDrawToWaylandBufferDirectly = false; + } -+void WaylandDispatchDisplays(); - nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr); + return LockImageSurface(lockSize); + } -+#ifdef HAVE_LIBDRM -+typedef struct gbm_device* (*CreateDeviceFunc)(int); -+typedef struct gbm_bo* (*CreateFunc)(struct gbm_device*, uint32_t, uint32_t, -+ uint32_t, uint32_t); -+typedef struct gbm_bo* (*CreateFunc)(struct gbm_device*, uint32_t, uint32_t, -+ uint32_t, uint32_t); -+typedef struct gbm_bo* (*CreateWithModifiersFunc)(struct gbm_device*, uint32_t, -+ uint32_t, uint32_t, -+ const uint64_t*, -+ const unsigned int); -+typedef uint64_t (*GetModifierFunc)(struct gbm_bo*); -+typedef uint32_t (*GetStrideFunc)(struct gbm_bo*); -+typedef int (*GetFdFunc)(struct gbm_bo*); -+typedef void (*DestroyFunc)(struct gbm_bo*); -+typedef void* (*MapFunc)(struct gbm_bo*, uint32_t, uint32_t, uint32_t, uint32_t, -+ uint32_t, uint32_t*, void**); -+typedef void (*UnmapFunc)(struct gbm_bo*, void*); -+typedef int (*GetPlaneCountFunc)(struct gbm_bo*); -+typedef union gbm_bo_handle (*GetHandleForPlaneFunc)(struct gbm_bo*, int); -+typedef uint32_t (*GetStrideForPlaneFunc)(struct gbm_bo*, int); -+typedef uint32_t (*GetOffsetFunc)(struct gbm_bo*, int); -+ -+typedef int (*DrmPrimeHandleToFDFunc)(int, uint32_t, uint32_t, int*); ++void WindowImageSurface::Draw(gfx::SourceSurface* aSurface, ++ gfx::DrawTarget* aDest, ++ const LayoutDeviceIntRegion& aRegion) { ++ uint32_t numRects = aRegion.GetNumRects(); ++ if (numRects != 1) { ++ AutoTArray rects; ++ rects.SetCapacity(numRects); ++ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { ++ rects.AppendElement(iter.Get().ToUnknownRect()); ++ } ++ aDest->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); ++ } + -+class nsGbmLib { -+ public: -+ static bool Load(); -+ static bool IsAvailable(); -+ static bool IsModifierAvailable(); ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ gfx::Rect rect(bounds); ++ aDest->DrawSurface(aSurface, rect, rect); + -+ static struct gbm_device* CreateDevice(int fd) { return sCreateDevice(fd); }; -+ static struct gbm_bo* Create(struct gbm_device* gbm, uint32_t width, -+ uint32_t height, uint32_t format, -+ uint32_t flags) { -+ return sCreate(gbm, width, height, format, flags); -+ } -+ static void Destroy(struct gbm_bo* bo) { sDestroy(bo); } -+ static uint32_t GetStride(struct gbm_bo* bo) { return sGetStride(bo); } -+ static int GetFd(struct gbm_bo* bo) { return sGetFd(bo); } -+ static void* Map(struct gbm_bo* bo, uint32_t x, uint32_t y, uint32_t width, -+ uint32_t height, uint32_t flags, uint32_t* stride, -+ void** map_data) { -+ return sMap(bo, x, y, width, height, flags, stride, map_data); -+ } -+ static void Unmap(struct gbm_bo* bo, void* map_data) { sUnmap(bo, map_data); } -+ static struct gbm_bo* CreateWithModifiers(struct gbm_device* gbm, -+ uint32_t width, uint32_t height, -+ uint32_t format, -+ const uint64_t* modifiers, -+ const unsigned int count) { -+ return sCreateWithModifiers(gbm, width, height, format, modifiers, count); -+ } -+ static uint64_t GetModifier(struct gbm_bo* bo) { return sGetModifier(bo); } -+ static int GetPlaneCount(struct gbm_bo* bo) { return sGetPlaneCount(bo); } -+ static union gbm_bo_handle GetHandleForPlane(struct gbm_bo* bo, int plane) { -+ return sGetHandleForPlane(bo, plane); -+ } -+ static uint32_t GetStrideForPlane(struct gbm_bo* bo, int plane) { -+ return sGetStrideForPlane(bo, plane); -+ } -+ static uint32_t GetOffset(struct gbm_bo* bo, int plane) { -+ return sGetOffset(bo, plane); ++ if (numRects != 1) { ++ aDest->PopClip(); + } ++} + -+ static int DrmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, -+ int* prime_fd) { -+ return sDrmPrimeHandleToFD(fd, handle, flags, prime_fd); -+ } ++void WindowImageSurface::Draw(gfx::DrawTarget* aDest, ++ LayoutDeviceIntRegion& aWaylandBufferDamage) { ++ Draw(mSurface.get(), aDest, mUpdateRegion); ++ aWaylandBufferDamage.OrWith(mUpdateRegion); ++} + -+ private: -+ static CreateDeviceFunc sCreateDevice; -+ static CreateFunc sCreate; -+ static CreateWithModifiersFunc sCreateWithModifiers; -+ static GetModifierFunc sGetModifier; -+ static GetStrideFunc sGetStride; -+ static GetFdFunc sGetFd; -+ static DestroyFunc sDestroy; -+ static MapFunc sMap; -+ static UnmapFunc sUnmap; -+ static GetPlaneCountFunc sGetPlaneCount; -+ static GetHandleForPlaneFunc sGetHandleForPlane; -+ static GetStrideForPlaneFunc sGetStrideForPlane; -+ static GetOffsetFunc sGetOffset; -+ static DrmPrimeHandleToFDFunc sDrmPrimeHandleToFD; ++WindowImageSurface::WindowImageSurface( ++ gfx::SourceSurface* aSurface, const LayoutDeviceIntRegion& aUpdateRegion) ++ : mSurface(aSurface), mUpdateRegion(aUpdateRegion){}; + -+ static void* sGbmLibHandle; -+ static void* sXf86DrmLibHandle; -+ static bool sLibLoaded; -+}; -+#endif ++void WindowSurfaceWayland::DrawDelayedImageCommits( ++ gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage) { ++ for (unsigned int i = 0; i < mDelayedImageCommits.Length(); i++) { ++ mDelayedImageCommits[i].Draw(aDrawTarget, aWaylandBufferDamage); ++ } ++ mDelayedImageCommits.Clear(); ++} + - } // namespace widget - } // namespace mozilla + bool WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer( +- const LayoutDeviceIntRegion& aRegion) { ++ const LayoutDeviceIntRegion& aRegion, ++ LayoutDeviceIntRegion& aWaylandBufferDamage) { + MOZ_ASSERT(!mDrawToWaylandBufferDirectly); --#endif // __MOZ_WAYLAND_REGISTRY_H__ -+#endif // __MOZ_WAYLAND_DISPLAY_H__ -diff -up firefox-67.0/widget/gtk/nsWindow.cpp.mozilla-1552590 firefox-67.0/widget/gtk/nsWindow.cpp ---- firefox-67.0/widget/gtk/nsWindow.cpp.mozilla-1552590 2019-05-27 12:15:32.025414340 +0200 -+++ firefox-67.0/widget/gtk/nsWindow.cpp 2019-05-27 12:15:32.032414339 +0200 -@@ -6785,11 +6785,14 @@ bool nsWindow::WaylandSurfaceNeedsClear( - if (mContainer) { - return moz_container_surface_needs_clear(MOZ_CONTAINER(mContainer)); + LayoutDeviceIntRect screenRect = mWindow->GetBounds(); + gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); + + gfx::Rect rect(bounds); + if (rect.IsEmpty()) { + return false; } -- -- NS_WARNING( -- "nsWindow::WaylandSurfaceNeedsClear(): We don't have any mContainer!"); - return false; + +- RefPtr dt = LockWaylandBuffer( +- screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear()); + RefPtr surf = + gfx::Factory::CreateSourceSurfaceForCairoSurface( + mImageSurface->CairoSurface(), mImageSurface->GetSize(), + mImageSurface->Format()); +- if (!dt || !surf) { ++ if (!surf) { + return false; + } + +- uint32_t numRects = aRegion.GetNumRects(); +- if (numRects != 1) { +- AutoTArray rects; +- rects.SetCapacity(numRects); +- for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { +- rects.AppendElement(iter.Get().ToUnknownRect()); ++ bool needsClear = mWindow->WaylandSurfaceNeedsClear(); ++ RefPtr dt = LockWaylandBuffer( ++ screenRect.width, screenRect.height, needsClear, ++ /* fullscreenDrawing */ false, /* aNoBackBufferCopy */ true); ++ if (dt) { ++ if (needsClear) { ++ mWindow->WaylandSurfaceCleared(); + } +- dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); +- } +- +- dt->DrawSurface(surf, rect, rect); +- +- if (numRects != 1) { +- dt->PopClip(); ++ // 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(); ++ } else { ++ mDelayedImageCommits.AppendElement(WindowImageSurface(surf, aRegion)); ++ return false; + } + + return true; } -+ -+void nsWindow::WaylandSurfaceCleared() { -+ if (mContainer) { -+ return moz_container_surface_cleared(MOZ_CONTAINER(mContainer)); + + static void WaylandBufferDelayCommitHandler(WindowSurfaceWayland** aSurface) { + if (*aSurface) { + (*aSurface)->DelayedCommitHandler(); +@@ -643,16 +810,34 @@ void WindowSurfaceWayland::CalcRectScale + + void WindowSurfaceWayland::CommitWaylandBuffer() { + MOZ_ASSERT(mPendingCommit, "Committing empty surface!"); + + if (mWaitToFullScreenUpdate) { + return; + } + ++ if (!mDrawToWaylandBufferDirectly) { ++ // There's some cached drawings - try to flush them now. ++ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); ++ bool needsClear = mWindow->WaylandSurfaceNeedsClear(); ++ RefPtr dt = ++ LockWaylandBuffer(screenRect.width, screenRect.height, needsClear, ++ /* fullscreenInvalidate */ false, ++ /* aNoBackBufferCopy */ true); ++ if (dt) { ++ if (needsClear) { ++ mWindow->WaylandSurfaceCleared(); ++ } ++ DrawDelayedImageCommits(dt, mWaylandBufferDamage); ++ UnlockWaylandBuffer(); ++ mDrawToWaylandBufferDirectly = true; ++ } + } -+} - #endif ++ + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (!waylandSurface) { + // Target window is not created yet - delay the commit. This can happen only + // when the window is newly created and there's no active + // frame callback pending. + MOZ_ASSERT(!mFrameCallback || waylandSurface != mLastCommittedSurface, + "Missing wayland surface at frame callback!"); - #ifdef MOZ_X11 -diff -up firefox-67.0/widget/gtk/nsWindow.h.mozilla-1552590 firefox-67.0/widget/gtk/nsWindow.h ---- firefox-67.0/widget/gtk/nsWindow.h.mozilla-1552590 2019-05-27 12:15:32.025414340 +0200 -+++ firefox-67.0/widget/gtk/nsWindow.h 2019-05-27 12:15:32.033414339 +0200 -@@ -345,6 +345,7 @@ class nsWindow final : public nsBaseWidg - wl_display* GetWaylandDisplay(); - wl_surface* GetWaylandSurface(); - bool WaylandSurfaceNeedsClear(); -+ void WaylandSurfaceCleared(); +@@ -735,24 +920,31 @@ void WindowSurfaceWayland::Commit(const + gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); + + LOGWAYLAND(("%s [%p] lockSize [%d x %d] screenSize [%d x %d]\n", + __PRETTY_FUNCTION__, (void*)this, lockSize.width, + lockSize.height, screenRect.width, lockSize.height)); + } #endif - virtual void GetCompositorWidgetInitData( - mozilla::widget::CompositorWidgetInitData* aInitData) override; -diff -up firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h.mozilla-1552590 firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h ---- firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h.mozilla-1552590 2019-05-27 12:15:32.033414339 +0200 -+++ firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h 2019-05-27 12:15:32.033414339 +0200 -@@ -0,0 +1,650 @@ -+/* Generated by wayland-scanner 1.17.0 */ + +- // We have new content at mImageSurface - copy data to mWaylandBuffer first. +- if (!mDrawToWaylandBufferDirectly) { +- CommitImageSurfaceToWaylandBuffer(aInvalidRegion); +- } +- +- // If we're not at fullscreen damage add drawing area from aInvalidRegion +- if (!mWaylandBufferFullScreenDamage) { +- mWaylandBufferDamage.OrWith(aInvalidRegion); ++ if (mDrawToWaylandBufferDirectly) { ++ MOZ_ASSERT(mWaylandBuffer->IsLocked()); ++ // If we're not at fullscreen damage add drawing area from aInvalidRegion ++ if (!mWaylandBufferFullScreenDamage) { ++ mWaylandBufferDamage.OrWith(aInvalidRegion); ++ } ++ UnlockWaylandBuffer(); ++ } else { ++ MOZ_ASSERT(!mWaylandBuffer->IsLocked(), ++ "Drawing to already locked buffer?"); ++ if (CommitImageSurfaceToWaylandBuffer(aInvalidRegion, ++ mWaylandBufferDamage)) { ++ // Our cached drawing is flushed, we can draw fullscreen again. ++ mDrawToWaylandBufferDirectly = true; ++ } + } + + // We're ready to commit. + mPendingCommit = true; + CommitWaylandBuffer(); + } + + void WindowSurfaceWayland::FrameCallbackHandler() { +diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h +--- a/widget/gtk/WindowSurfaceWayland.h ++++ b/widget/gtk/WindowSurfaceWayland.h +@@ -5,16 +5,19 @@ + * 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 + #include "mozilla/gfx/Types.h" + #include "nsWaylandDisplay.h" ++#ifdef HAVE_LIBDRM ++# include "mozilla/gfx/WaylandDMABufSurface.h" ++#endif + + #define BACK_BUFFER_NUM 2 + + namespace mozilla { + namespace widget { + + // Allocates and owns shared memory for Wayland drawing surface + class WaylandShmPool { +@@ -35,94 +38,192 @@ class WaylandShmPool { + int mShmPoolFd; + int mAllocatedSize; + void* mImageData; + }; + + // Holds actual graphics data for wl_surface + class WindowBackBuffer { + public: +- WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight); +- ~WindowBackBuffer(); ++ virtual already_AddRefed Lock() = 0; ++ virtual void Unlock(){}; ++ virtual bool IsLocked() { return false; }; + -+#ifndef LINUX_DMABUF_UNSTABLE_V1_CLIENT_PROTOCOL_H -+#define LINUX_DMABUF_UNSTABLE_V1_CLIENT_PROTOCOL_H ++ void Attach(wl_surface* aSurface); ++ virtual void Detach(wl_buffer* aBuffer) = 0; ++ virtual bool IsAttached() = 0; + -+#include -+#include -+#include "wayland-client.h" ++ virtual void Clear() = 0; ++ virtual bool Resize(int aWidth, int aHeight) = 0; + -+#ifdef __cplusplus -+extern "C" { -+#endif ++ virtual int GetWidth() = 0; ++ virtual int GetHeight() = 0; ++ virtual wl_buffer* GetWlBuffer() = 0; ++ virtual void SetAttached() = 0; + -+/** -+ * @page page_linux_dmabuf_unstable_v1 The linux_dmabuf_unstable_v1 protocol -+ * @section page_ifaces_linux_dmabuf_unstable_v1 Interfaces -+ * - @subpage page_iface_zwp_linux_dmabuf_v1 - factory for creating dmabuf-based -+ * wl_buffers -+ * - @subpage page_iface_zwp_linux_buffer_params_v1 - parameters for creating a -+ * dmabuf-based wl_buffer -+ * @section page_copyright_linux_dmabuf_unstable_v1 Copyright -+ *
-+ *
-+ * Copyright © 2014, 2015 Collabora, Ltd.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ * DEALINGS IN THE SOFTWARE.
-+ * 
-+ */ -+struct wl_buffer; -+struct zwp_linux_buffer_params_v1; -+struct zwp_linux_dmabuf_v1; ++ virtual bool SetImageDataFromBuffer( ++ class WindowBackBuffer* aSourceBuffer) = 0; + -+/** -+ * @page page_iface_zwp_linux_dmabuf_v1 zwp_linux_dmabuf_v1 -+ * @section page_iface_zwp_linux_dmabuf_v1_desc Description -+ * -+ * Following the interfaces from: -+ * https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt -+ * and the Linux DRM sub-system's AddFb2 ioctl. -+ * -+ * This interface offers ways to create generic dmabuf-based -+ * wl_buffers. Immediately after a client binds to this interface, -+ * the set of supported formats and format modifiers is sent with -+ * 'format' and 'modifier' events. -+ * -+ * The following are required from clients: -+ * -+ * - Clients must ensure that either all data in the dma-buf is -+ * coherent for all subsequent read access or that coherency is -+ * correctly handled by the underlying kernel-side dma-buf -+ * implementation. -+ * -+ * - Don't make any more attachments after sending the buffer to the -+ * compositor. Making more attachments later increases the risk of -+ * the compositor not being able to use (re-import) an existing -+ * dmabuf-based wl_buffer. -+ * -+ * The underlying graphics stack must ensure the following: -+ * -+ * - The dmabuf file descriptors relayed to the server will stay valid -+ * for the whole lifetime of the wl_buffer. This means the server may -+ * at any time use those fds to import the dmabuf into any kernel -+ * sub-system that might accept it. -+ * -+ * To create a wl_buffer from one or more dmabufs, a client creates a -+ * zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params -+ * request. All planes required by the intended format are added with -+ * the 'add' request. Finally, a 'create' or 'create_immed' request is -+ * issued, which has the following outcome depending on the import success. -+ * -+ * The 'create' request, -+ * - on success, triggers a 'created' event which provides the final -+ * wl_buffer to the client. -+ * - on failure, triggers a 'failed' event to convey that the server -+ * cannot use the dmabufs received from the client. -+ * -+ * For the 'create_immed' request, -+ * - on success, the server immediately imports the added dmabufs to -+ * create a wl_buffer. No event is sent from the server in this case. -+ * - on failure, the server can choose to either: -+ * - terminate the client by raising a fatal error. -+ * - mark the wl_buffer as failed, and send a 'failed' event to the -+ * client. If the client uses a failed wl_buffer as an argument to any -+ * request, the behaviour is compositor implementation-defined. -+ * -+ * Warning! The protocol described in this file is experimental and -+ * backward incompatible changes may be made. Backward compatible changes -+ * may be added together with the corresponding interface version bump. -+ * Backward incompatible changes are done by bumping the version number in -+ * the protocol and interface names and resetting the interface version. -+ * Once the protocol is to be declared stable, the 'z' prefix and the -+ * version number in the protocol and interface names are removed and the -+ * interface version number is reset. -+ * @section page_iface_zwp_linux_dmabuf_v1_api API -+ * See @ref iface_zwp_linux_dmabuf_v1. -+ */ -+/** -+ * @defgroup iface_zwp_linux_dmabuf_v1 The zwp_linux_dmabuf_v1 interface -+ * -+ * Following the interfaces from: -+ * https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt -+ * and the Linux DRM sub-system's AddFb2 ioctl. -+ * -+ * This interface offers ways to create generic dmabuf-based -+ * wl_buffers. Immediately after a client binds to this interface, -+ * the set of supported formats and format modifiers is sent with -+ * 'format' and 'modifier' events. -+ * -+ * The following are required from clients: -+ * -+ * - Clients must ensure that either all data in the dma-buf is -+ * coherent for all subsequent read access or that coherency is -+ * correctly handled by the underlying kernel-side dma-buf -+ * implementation. -+ * -+ * - Don't make any more attachments after sending the buffer to the -+ * compositor. Making more attachments later increases the risk of -+ * the compositor not being able to use (re-import) an existing -+ * dmabuf-based wl_buffer. -+ * -+ * The underlying graphics stack must ensure the following: -+ * -+ * - The dmabuf file descriptors relayed to the server will stay valid -+ * for the whole lifetime of the wl_buffer. This means the server may -+ * at any time use those fds to import the dmabuf into any kernel -+ * sub-system that might accept it. -+ * -+ * To create a wl_buffer from one or more dmabufs, a client creates a -+ * zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params -+ * request. All planes required by the intended format are added with -+ * the 'add' request. Finally, a 'create' or 'create_immed' request is -+ * issued, which has the following outcome depending on the import success. -+ * -+ * The 'create' request, -+ * - on success, triggers a 'created' event which provides the final -+ * wl_buffer to the client. -+ * - on failure, triggers a 'failed' event to convey that the server -+ * cannot use the dmabufs received from the client. -+ * -+ * For the 'create_immed' request, -+ * - on success, the server immediately imports the added dmabufs to -+ * create a wl_buffer. No event is sent from the server in this case. -+ * - on failure, the server can choose to either: -+ * - terminate the client by raising a fatal error. -+ * - mark the wl_buffer as failed, and send a 'failed' event to the -+ * client. If the client uses a failed wl_buffer as an argument to any -+ * request, the behaviour is compositor implementation-defined. -+ * -+ * Warning! The protocol described in this file is experimental and -+ * backward incompatible changes may be made. Backward compatible changes -+ * may be added together with the corresponding interface version bump. -+ * Backward incompatible changes are done by bumping the version number in -+ * the protocol and interface names and resetting the interface version. -+ * Once the protocol is to be declared stable, the 'z' prefix and the -+ * version number in the protocol and interface names are removed and the -+ * interface version number is reset. -+ */ -+extern const struct wl_interface zwp_linux_dmabuf_v1_interface; -+/** -+ * @page page_iface_zwp_linux_buffer_params_v1 zwp_linux_buffer_params_v1 -+ * @section page_iface_zwp_linux_buffer_params_v1_desc Description -+ * -+ * This temporary object is a collection of dmabufs and other -+ * parameters that together form a single logical buffer. The temporary -+ * object may eventually create one wl_buffer unless cancelled by -+ * destroying it before requesting 'create'. -+ * -+ * Single-planar formats only require one dmabuf, however -+ * multi-planar formats may require more than one dmabuf. For all -+ * formats, an 'add' request must be called once per plane (even if the -+ * underlying dmabuf fd is identical). -+ * -+ * You must use consecutive plane indices ('plane_idx' argument for 'add') -+ * from zero to the number of planes used by the drm_fourcc format code. -+ * All planes required by the format must be given exactly once, but can -+ * be given in any order. Each plane index can be set only once. -+ * @section page_iface_zwp_linux_buffer_params_v1_api API -+ * See @ref iface_zwp_linux_buffer_params_v1. -+ */ -+/** -+ * @defgroup iface_zwp_linux_buffer_params_v1 The zwp_linux_buffer_params_v1 -+ * interface -+ * -+ * This temporary object is a collection of dmabufs and other -+ * parameters that together form a single logical buffer. The temporary -+ * object may eventually create one wl_buffer unless cancelled by -+ * destroying it before requesting 'create'. -+ * -+ * Single-planar formats only require one dmabuf, however -+ * multi-planar formats may require more than one dmabuf. For all -+ * formats, an 'add' request must be called once per plane (even if the -+ * underlying dmabuf fd is identical). -+ * -+ * You must use consecutive plane indices ('plane_idx' argument for 'add') -+ * from zero to the number of planes used by the drm_fourcc format code. -+ * All planes required by the format must be given exactly once, but can -+ * be given in any order. Each plane index can be set only once. -+ */ -+extern const struct wl_interface zwp_linux_buffer_params_v1_interface; -+ -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ * @struct zwp_linux_dmabuf_v1_listener -+ */ -+struct zwp_linux_dmabuf_v1_listener { -+ /** -+ * supported buffer format -+ * -+ * This event advertises one buffer format that the server -+ * supports. All the supported formats are advertised once when the -+ * client binds to this interface. A roundtrip after binding -+ * guarantees that the client has received all supported formats. -+ * -+ * For the definition of the format codes, see the -+ * zwp_linux_buffer_params_v1::create request. -+ * -+ * Warning: the 'format' event is likely to be deprecated and -+ * replaced with the 'modifier' event introduced in -+ * zwp_linux_dmabuf_v1 version 3, described below. Please refrain -+ * from using the information received from this event. -+ * @param format DRM_FORMAT code -+ */ -+ void (*format)(void* data, struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, -+ uint32_t format); -+ /** -+ * supported buffer format modifier -+ * -+ * This event advertises the formats that the server supports, -+ * along with the modifiers supported for each format. All the -+ * supported modifiers for all the supported formats are advertised -+ * once when the client binds to this interface. A roundtrip after -+ * binding guarantees that the client has received all supported -+ * format-modifier pairs. -+ * -+ * For the definition of the format and modifier codes, see the -+ * zwp_linux_buffer_params_v1::create request. -+ * @param format DRM_FORMAT code -+ * @param modifier_hi high 32 bits of layout modifier -+ * @param modifier_lo low 32 bits of layout modifier -+ * @since 3 -+ */ -+ void (*modifier)(void* data, struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, -+ uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo); -+}; ++ bool IsMatchingSize(int aWidth, int aHeight) { ++ return aWidth == GetWidth() && aHeight == GetHeight(); ++ } ++ bool IsMatchingSize(class WindowBackBuffer* aBuffer) { ++ return aBuffer->IsMatchingSize(GetWidth(), GetHeight()); ++ } + -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ */ -+static inline int zwp_linux_dmabuf_v1_add_listener( -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, -+ const struct zwp_linux_dmabuf_v1_listener* listener, void* data) { -+ return wl_proxy_add_listener((struct wl_proxy*)zwp_linux_dmabuf_v1, -+ (void (**)(void))listener, data); -+} ++ static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } + -+#define ZWP_LINUX_DMABUF_V1_DESTROY 0 -+#define ZWP_LINUX_DMABUF_V1_CREATE_PARAMS 1 ++ nsWaylandDisplay* GetWaylandDisplay() { return mWaylandDisplay; }; + -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ */ -+#define ZWP_LINUX_DMABUF_V1_FORMAT_SINCE_VERSION 1 -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ */ -+#define ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION 3 ++ WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay) ++ : mWaylandDisplay(aWaylandDisplay){}; ++ virtual ~WindowBackBuffer(){}; + -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ */ -+#define ZWP_LINUX_DMABUF_V1_DESTROY_SINCE_VERSION 1 -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ */ -+#define ZWP_LINUX_DMABUF_V1_CREATE_PARAMS_SINCE_VERSION 1 ++ private: ++ static gfx::SurfaceFormat mFormat; ++ nsWaylandDisplay* mWaylandDisplay; ++}; + -+/** @ingroup iface_zwp_linux_dmabuf_v1 */ -+static inline void zwp_linux_dmabuf_v1_set_user_data( -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, void* user_data) { -+ wl_proxy_set_user_data((struct wl_proxy*)zwp_linux_dmabuf_v1, user_data); -+} ++class WindowBackBufferShm : public WindowBackBuffer { ++ public: ++ WindowBackBufferShm(nsWaylandDisplay* aWaylandDisplay, int aWidth, ++ int aHeight); ++ ~WindowBackBufferShm(); + + already_AddRefed Lock(); + +- void Attach(wl_surface* aSurface); + void Detach(wl_buffer* aBuffer); + bool IsAttached() { return mAttached; } + + void Clear(); + bool Resize(int aWidth, int aHeight); + bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); + +- bool IsMatchingSize(int aWidth, int aHeight) { +- return aWidth == mWidth && aHeight == mHeight; +- } +- bool IsMatchingSize(class WindowBackBuffer* aBuffer) { +- return aBuffer->mWidth == mWidth && aBuffer->mHeight == mHeight; +- } ++ int GetWidth() { return mWidth; }; ++ int GetHeight() { return mHeight; }; + +- static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } ++ wl_buffer* GetWlBuffer() { return mWaylandBuffer; }; ++ void SetAttached() { mAttached = true; }; + + private: + void Create(int aWidth, int aHeight); + void Release(); + + // WaylandShmPool provides actual shared memory we draw into + WaylandShmPool mShmPool; + + // wl_buffer is a wayland object that encapsulates the shared memory + // and passes it to wayland compositor by wl_surface object. + wl_buffer* mWaylandBuffer; + int mWidth; + int mHeight; + bool mAttached; +- nsWaylandDisplay* mWaylandDisplay; +- static gfx::SurfaceFormat mFormat; ++}; + -+/** @ingroup iface_zwp_linux_dmabuf_v1 */ -+static inline void* zwp_linux_dmabuf_v1_get_user_data( -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { -+ return wl_proxy_get_user_data((struct wl_proxy*)zwp_linux_dmabuf_v1); -+} ++#ifdef HAVE_LIBDRM ++class WindowBackBufferDMABuf : public WindowBackBuffer { ++ public: ++ WindowBackBufferDMABuf(nsWaylandDisplay* aWaylandDisplay, int aWidth, ++ int aHeight); ++ ~WindowBackBufferDMABuf(); + -+static inline uint32_t zwp_linux_dmabuf_v1_get_version( -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { -+ return wl_proxy_get_version((struct wl_proxy*)zwp_linux_dmabuf_v1); -+} ++ bool IsAttached(); ++ void SetAttached(); + -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ * -+ * Objects created through this interface, especially wl_buffers, will -+ * remain valid. -+ */ -+static inline void zwp_linux_dmabuf_v1_destroy( -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { -+ wl_proxy_marshal((struct wl_proxy*)zwp_linux_dmabuf_v1, -+ ZWP_LINUX_DMABUF_V1_DESTROY); -+ -+ wl_proxy_destroy((struct wl_proxy*)zwp_linux_dmabuf_v1); -+} -+ -+/** -+ * @ingroup iface_zwp_linux_dmabuf_v1 -+ * -+ * This temporary object is used to collect multiple dmabuf handles into -+ * a single batch to create a wl_buffer. It can only be used once and -+ * should be destroyed after a 'created' or 'failed' event has been -+ * received. -+ */ -+static inline struct zwp_linux_buffer_params_v1* -+zwp_linux_dmabuf_v1_create_params( -+ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { -+ struct wl_proxy* params_id; -+ -+ params_id = wl_proxy_marshal_constructor( -+ (struct wl_proxy*)zwp_linux_dmabuf_v1, ZWP_LINUX_DMABUF_V1_CREATE_PARAMS, -+ &zwp_linux_buffer_params_v1_interface, NULL); ++ int GetWidth(); ++ int GetHeight(); ++ wl_buffer* GetWlBuffer(); + -+ return (struct zwp_linux_buffer_params_v1*)params_id; -+} ++ bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); + -+#ifndef ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ENUM -+# define ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ENUM -+enum zwp_linux_buffer_params_v1_error { -+ /** -+ * the dmabuf_batch object has already been used to create a wl_buffer -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED = 0, -+ /** -+ * plane index out of bounds -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX = 1, -+ /** -+ * the plane index was already set -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET = 2, -+ /** -+ * missing or too many planes to create a buffer -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE = 3, -+ /** -+ * format not supported -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT = 4, -+ /** -+ * invalid width or height -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS = 5, -+ /** -+ * offset + stride * height goes out of dmabuf bounds -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS = 6, -+ /** -+ * invalid wl_buffer resulted from importing dmabufs via the -+ * create_immed request on given buffer_params -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER = 7, -+}; -+#endif /* ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ENUM */ ++ already_AddRefed Lock(); ++ bool IsLocked(); ++ void Unlock(); + -+#ifndef ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_ENUM -+# define ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_ENUM -+enum zwp_linux_buffer_params_v1_flags { -+ /** -+ * contents are y-inverted -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT = 1, -+ /** -+ * content is interlaced -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED = 2, -+ /** -+ * bottom field first -+ */ -+ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_BOTTOM_FIRST = 4, -+}; -+#endif /* ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_ENUM */ ++ void Clear(); ++ void Detach(wl_buffer* aBuffer); ++ bool Resize(int aWidth, int aHeight); + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ * @struct zwp_linux_buffer_params_v1_listener -+ */ -+struct zwp_linux_buffer_params_v1_listener { -+ /** -+ * buffer creation succeeded -+ * -+ * This event indicates that the attempted buffer creation was -+ * successful. It provides the new wl_buffer referencing the -+ * dmabuf(s). -+ * -+ * Upon receiving this event, the client should destroy the -+ * zlinux_dmabuf_params object. -+ * @param buffer the newly created wl_buffer -+ */ -+ void (*created)(void* data, -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, -+ struct wl_buffer* buffer); -+ /** -+ * buffer creation failed -+ * -+ * This event indicates that the attempted buffer creation has -+ * failed. It usually means that one of the dmabuf constraints has -+ * not been fulfilled. -+ * -+ * Upon receiving this event, the client should destroy the -+ * zlinux_buffer_params object. -+ */ -+ void (*failed)(void* data, -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1); ++ private: ++ WaylandDMABufSurface mDMAbufSurface; +}; ++#endif + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+static inline int zwp_linux_buffer_params_v1_add_listener( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, -+ const struct zwp_linux_buffer_params_v1_listener* listener, void* data) { -+ return wl_proxy_add_listener((struct wl_proxy*)zwp_linux_buffer_params_v1, -+ (void (**)(void))listener, data); -+} -+ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_DESTROY 0 -+#define ZWP_LINUX_BUFFER_PARAMS_V1_ADD 1 -+#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE 2 -+#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED 3 ++class WindowImageSurface { ++ public: ++ static void Draw(gfx::SourceSurface* aSurface, gfx::DrawTarget* aDest, ++ const LayoutDeviceIntRegion& aRegion); + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATED_SINCE_VERSION 1 -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_FAILED_SINCE_VERSION 1 ++ void Draw(gfx::DrawTarget* aDest, ++ LayoutDeviceIntRegion& aWaylandBufferDamage); + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_DESTROY_SINCE_VERSION 1 -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_ADD_SINCE_VERSION 1 -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_SINCE_VERSION 1 -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ */ -+#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED_SINCE_VERSION 2 ++ WindowImageSurface(gfx::SourceSurface* aSurface, ++ const LayoutDeviceIntRegion& aUpdateRegion); + -+/** @ingroup iface_zwp_linux_buffer_params_v1 */ -+static inline void zwp_linux_buffer_params_v1_set_user_data( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, -+ void* user_data) { -+ wl_proxy_set_user_data((struct wl_proxy*)zwp_linux_buffer_params_v1, -+ user_data); -+} ++ private: ++ RefPtr mSurface; ++ const LayoutDeviceIntRegion mUpdateRegion; + }; + + // WindowSurfaceWayland is an abstraction for wl_surface + // and related management + class WindowSurfaceWayland : public WindowSurface { + public: + explicit WindowSurfaceWayland(nsWindow* aWindow); + ~WindowSurfaceWayland(); + + already_AddRefed Lock( + const LayoutDeviceIntRegion& aRegion) override; + void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; + void FrameCallbackHandler(); + void DelayedCommitHandler(); + + private: +- WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight); ++ WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight); ++ WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight, ++ bool aFullScreenUpdate, ++ bool aNoBackBufferCopy); + + already_AddRefed LockWaylandBuffer(int aWidth, int aHeight, +- bool aClearBuffer); ++ bool aClearBuffer, ++ bool aFullScreenUpdate, ++ bool aNoBackBufferCopy); ++ void UnlockWaylandBuffer(); + -+/** @ingroup iface_zwp_linux_buffer_params_v1 */ -+static inline void* zwp_linux_buffer_params_v1_get_user_data( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1) { -+ return wl_proxy_get_user_data((struct wl_proxy*)zwp_linux_buffer_params_v1); -+} + already_AddRefed LockImageSurface( + const gfx::IntSize& aLockSize); +- bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); ++ bool CommitImageSurfaceToWaylandBuffer( ++ const LayoutDeviceIntRegion& aRegion, ++ LayoutDeviceIntRegion& aWaylandBufferDamage); + void CommitWaylandBuffer(); + void CalcRectScale(LayoutDeviceIntRect& aRect, int scale); + ++ void DrawDelayedImageCommits(gfx::DrawTarget* aDrawTarget, ++ LayoutDeviceIntRegion& aWaylandBufferDamage); + -+static inline uint32_t zwp_linux_buffer_params_v1_get_version( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1) { -+ return wl_proxy_get_version((struct wl_proxy*)zwp_linux_buffer_params_v1); -+} + // TODO: Do we need to hold a reference to nsWindow object? + nsWindow* mWindow; + nsWaylandDisplay* mWaylandDisplay; + WindowBackBuffer* mWaylandBuffer; + LayoutDeviceIntRegion mWaylandBufferDamage; + WindowBackBuffer* mBackupBuffer[BACK_BUFFER_NUM]; +- RefPtr mImageSurface; + wl_callback* mFrameCallback; + wl_surface* mLastCommittedSurface; + MessageLoop* mDisplayThreadMessageLoop; + WindowSurfaceWayland** mDelayedCommitHandle; ++ RefPtr mImageSurface; ++ AutoTArray mDelayedImageCommits; + bool mDrawToWaylandBufferDirectly; + bool mPendingCommit; + bool mWaylandBufferFullScreenDamage; + bool mIsMainThread; + bool mNeedScaleFactorUpdate; + bool mWaitToFullScreenUpdate; + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ * -+ * Cleans up the temporary data sent to the server for dmabuf-based -+ * wl_buffer creation. -+ */ -+static inline void zwp_linux_buffer_params_v1_destroy( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1) { -+ wl_proxy_marshal((struct wl_proxy*)zwp_linux_buffer_params_v1, -+ ZWP_LINUX_BUFFER_PARAMS_V1_DESTROY); -+ -+ wl_proxy_destroy((struct wl_proxy*)zwp_linux_buffer_params_v1); ++ static bool UseDMABufBackend(); ++ static bool mUseDMABufInitialized; ++ static bool mUseDMABuf; + }; + + } // namespace widget + } // namespace mozilla + + #endif // _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H +diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build +--- a/widget/gtk/moz.build ++++ b/widget/gtk/moz.build +@@ -97,17 +97,18 @@ if CONFIG['MOZ_X11']: + + if CONFIG['MOZ_WAYLAND']: + UNIFIED_SOURCES += [ + 'nsClipboardWayland.cpp', + 'nsWaylandDisplay.cpp', + 'WindowSurfaceWayland.cpp', + ] + EXPORTS.mozilla.widget += [ +- 'nsWaylandDisplayShutdown.h' ++ 'nsWaylandDisplay.h', ++ 'nsWaylandDisplayShutdown.h', + ] + + if CONFIG['ACCESSIBILITY']: + UNIFIED_SOURCES += [ + 'maiRedundantObjectFactory.c', + ] + + UNIFIED_SOURCES += [ +diff --git a/widget/gtk/mozcontainer.cpp b/widget/gtk/mozcontainer.cpp +--- a/widget/gtk/mozcontainer.cpp ++++ b/widget/gtk/mozcontainer.cpp +@@ -641,17 +641,19 @@ struct wl_egl_window* moz_container_get_ + return container->eglwindow; + } + + gboolean moz_container_has_wl_egl_window(MozContainer* container) { + return container->eglwindow ? true : false; + } + + gboolean moz_container_surface_needs_clear(MozContainer* container) { +- gboolean state = container->surface_needs_clear; ++ return container->surface_needs_clear; +} + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ * -+ * This request adds one dmabuf to the set in this -+ * zwp_linux_buffer_params_v1. -+ * -+ * The 64-bit unsigned value combined from modifier_hi and modifier_lo -+ * is the dmabuf layout modifier. DRM AddFB2 ioctl calls this the -+ * fb modifier, which is defined in drm_mode.h of Linux UAPI. -+ * This is an opaque token. Drivers use this token to express tiling, -+ * compression, etc. driver-specific modifications to the base format -+ * defined by the DRM fourcc code. -+ * -+ * This request raises the PLANE_IDX error if plane_idx is too large. -+ * The error PLANE_SET is raised if attempting to set a plane that -+ * was already set. -+ */ -+static inline void zwp_linux_buffer_params_v1_add( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, int32_t fd, -+ uint32_t plane_idx, uint32_t offset, uint32_t stride, uint32_t modifier_hi, -+ uint32_t modifier_lo) { -+ wl_proxy_marshal((struct wl_proxy*)zwp_linux_buffer_params_v1, -+ ZWP_LINUX_BUFFER_PARAMS_V1_ADD, fd, plane_idx, offset, -+ stride, modifier_hi, modifier_lo); -+} ++void moz_container_surface_cleared(MozContainer* container) { + container->surface_needs_clear = false; +- return state; + } + #endif + + void moz_container_force_default_visual(MozContainer* container) { + container->force_default_visual = true; + } +diff --git a/widget/gtk/mozcontainer.h b/widget/gtk/mozcontainer.h +--- a/widget/gtk/mozcontainer.h ++++ b/widget/gtk/mozcontainer.h +@@ -96,15 +96,16 @@ void moz_container_put(MozContainer* con + void moz_container_force_default_visual(MozContainer* container); + + #ifdef MOZ_WAYLAND + struct wl_surface* moz_container_get_wl_surface(MozContainer* container); + struct wl_egl_window* moz_container_get_wl_egl_window(MozContainer* container); + + gboolean moz_container_has_wl_egl_window(MozContainer* container); + gboolean moz_container_surface_needs_clear(MozContainer* container); ++void moz_container_surface_cleared(MozContainer* container); + void moz_container_scale_changed(MozContainer* container, + GtkAllocation* aAllocation); + void moz_container_set_initial_draw_callback( + MozContainer* container, std::function inital_draw_cb); + #endif + + #endif /* __MOZ_CONTAINER_H__ */ +diff --git a/widget/gtk/mozwayland/moz.build b/widget/gtk/mozwayland/moz.build +--- a/widget/gtk/mozwayland/moz.build ++++ b/widget/gtk/mozwayland/moz.build +@@ -2,12 +2,16 @@ + # vim: set filetype=python: + # 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/. + + SOURCES += [ + 'mozwayland.c', + ] ++EXPORTS.mozilla.widget += [ ++ 'mozwayland.h', ++] + + SharedLibrary('mozwayland') + + CFLAGS += CONFIG['TK_CFLAGS'] + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ * -+ * This asks for creation of a wl_buffer from the added dmabuf -+ * buffers. The wl_buffer is not created immediately but returned via -+ * the 'created' event if the dmabuf sharing succeeds. The sharing -+ * may fail at runtime for reasons a client cannot predict, in -+ * which case the 'failed' event is triggered. -+ * -+ * The 'format' argument is a DRM_FORMAT code, as defined by the -+ * libdrm's drm_fourcc.h. The Linux kernel's DRM sub-system is the -+ * authoritative source on how the format codes should work. -+ * -+ * The 'flags' is a bitfield of the flags defined in enum "flags". -+ * 'y_invert' means the that the image needs to be y-flipped. -+ * -+ * Flag 'interlaced' means that the frame in the buffer is not -+ * progressive as usual, but interlaced. An interlaced buffer as -+ * supported here must always contain both top and bottom fields. -+ * The top field always begins on the first pixel row. The temporal -+ * ordering between the two fields is top field first, unless -+ * 'bottom_first' is specified. It is undefined whether 'bottom_first' -+ * is ignored if 'interlaced' is not set. -+ * -+ * This protocol does not convey any information about field rate, -+ * duration, or timing, other than the relative ordering between the -+ * two fields in one buffer. A compositor may have to estimate the -+ * intended field rate from the incoming buffer rate. It is undefined -+ * whether the time of receiving wl_surface.commit with a new buffer -+ * attached, applying the wl_surface state, wl_surface.frame callback -+ * trigger, presentation, or any other point in the compositor cycle -+ * is used to measure the frame or field times. There is no support -+ * for detecting missed or late frames/fields/buffers either, and -+ * there is no support whatsoever for cooperating with interlaced -+ * compositor output. -+ * -+ * The composited image quality resulting from the use of interlaced -+ * buffers is explicitly undefined. A compositor may use elaborate -+ * hardware features or software to deinterlace and create progressive -+ * output frames from a sequence of interlaced input buffers, or it -+ * may produce substandard image quality. However, compositors that -+ * cannot guarantee reasonable image quality in all cases are recommended -+ * to just reject all interlaced buffers. -+ * -+ * Any argument errors, including non-positive width or height, -+ * mismatch between the number of planes and the format, bad -+ * format, bad offset or stride, may be indicated by fatal protocol -+ * errors: INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, -+ * OUT_OF_BOUNDS. -+ * -+ * Dmabuf import errors in the server that are not obvious client -+ * bugs are returned via the 'failed' event as non-fatal. This -+ * allows attempting dmabuf sharing and falling back in the client -+ * if it fails. -+ * -+ * This request can be sent only once in the object's lifetime, after -+ * which the only legal request is destroy. This object should be -+ * destroyed after issuing a 'create' request. Attempting to use this -+ * object after issuing 'create' raises ALREADY_USED protocol error. -+ * -+ * It is not mandatory to issue 'create'. If a client wants to -+ * cancel the buffer creation, it can just destroy this object. -+ */ -+static inline void zwp_linux_buffer_params_v1_create( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, -+ int32_t width, int32_t height, uint32_t format, uint32_t flags) { -+ wl_proxy_marshal((struct wl_proxy*)zwp_linux_buffer_params_v1, -+ ZWP_LINUX_BUFFER_PARAMS_V1_CREATE, width, height, format, -+ flags); +diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp +--- a/widget/gtk/nsWaylandDisplay.cpp ++++ b/widget/gtk/nsWaylandDisplay.cpp +@@ -2,20 +2,16 @@ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* 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/. */ + + #include "nsWaylandDisplay.h" + +-#include "base/message_loop.h" // for MessageLoop +-#include "base/task.h" // for NewRunnableMethod, etc +-#include "mozilla/StaticMutex.h" +- + namespace mozilla { + namespace widget { + + // nsWaylandDisplay needs to be created for each calling thread(main thread, + // compositor thread and render thread) + #define MAX_DISPLAY_CONNECTIONS 3 + + static nsWaylandDisplay* gWaylandDisplays[MAX_DISPLAY_CONNECTIONS]; +@@ -107,16 +103,67 @@ void nsWaylandDisplay::SetDataDeviceMana + + void nsWaylandDisplay::SetSeat(wl_seat* aSeat) { mSeat = aSeat; } + + void nsWaylandDisplay::SetPrimarySelectionDeviceManager( + gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager) { + mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager; + } + ++#ifdef HAVE_LIBDRM ++void nsWaylandDisplay::SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf) { ++ mDmabuf = aDmabuf; +} + -+/** -+ * @ingroup iface_zwp_linux_buffer_params_v1 -+ * -+ * This asks for immediate creation of a wl_buffer by importing the -+ * added dmabufs. -+ * -+ * In case of import success, no event is sent from the server, and the -+ * wl_buffer is ready to be used by the client. -+ * -+ * Upon import failure, either of the following may happen, as seen fit -+ * by the implementation: -+ * - the client is terminated with one of the following fatal protocol -+ * errors: -+ * - INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, OUT_OF_BOUNDS, -+ * in case of argument errors such as mismatch between the number -+ * of planes and the format, bad format, non-positive width or -+ * height, or bad offset or stride. -+ * - INVALID_WL_BUFFER, in case the cause for failure is unknown or -+ * plaform specific. -+ * - the server creates an invalid wl_buffer, marks it as failed and -+ * sends a 'failed' event to the client. The result of using this -+ * invalid wl_buffer as an argument in any request by the client is -+ * defined by the compositor implementation. -+ * -+ * This takes the same arguments as a 'create' request, and obeys the -+ * same restrictions. -+ */ -+static inline struct wl_buffer* zwp_linux_buffer_params_v1_create_immed( -+ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, -+ int32_t width, int32_t height, uint32_t format, uint32_t flags) { -+ struct wl_proxy* buffer_id; ++GbmFormat* nsWaylandDisplay::GetGbmFormat(bool aHasAlpha) { ++ GbmFormat* format = aHasAlpha ? &mARGBFormat : &mXRGBFormat; ++ return format->mIsSupported ? format : nullptr; ++} + -+ buffer_id = wl_proxy_marshal_constructor( -+ (struct wl_proxy*)zwp_linux_buffer_params_v1, -+ ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED, &wl_buffer_interface, NULL, -+ width, height, format, flags); ++void nsWaylandDisplay::AddFormatModifier(bool aHasAlpha, int aFormat, ++ uint32_t mModifierHi, ++ uint32_t mModifierLo) { ++ GbmFormat* format = aHasAlpha ? &mARGBFormat : &mXRGBFormat; ++ format->mIsSupported = true; ++ format->mHasAlpha = aHasAlpha; ++ format->mFormat = aFormat; ++ format->mModifiersCount++; ++ format->mModifiers = ++ (uint64_t*)realloc(format->mModifiers, ++ format->mModifiersCount * sizeof(*format->mModifiers)); ++ format->mModifiers[format->mModifiersCount - 1] = ++ ((uint64_t)mModifierHi << 32) | mModifierLo; ++} + -+ return (struct wl_buffer*)buffer_id; ++static void dmabuf_modifiers(void* data, ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf, ++ uint32_t format, uint32_t modifier_hi, ++ uint32_t modifier_lo) { ++ auto display = reinterpret_cast(data); ++ switch (format) { ++ case DRM_FORMAT_ARGB8888: ++ display->AddFormatModifier(true, format, modifier_hi, modifier_lo); ++ break; ++ case DRM_FORMAT_XRGB8888: ++ display->AddFormatModifier(false, format, modifier_hi, modifier_lo); ++ break; ++ default: ++ break; ++ } +} + -+#ifdef __cplusplus ++static void dmabuf_format(void* data, ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf, ++ uint32_t format) { ++ // XXX: deprecated +} -+#endif + -+#endif -diff -up firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c.mozilla-1552590 firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c ---- firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c.mozilla-1552590 2019-05-27 12:15:32.033414339 +0200 -+++ firefox-67.0/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c 2019-05-27 12:15:32.033414339 +0200 -@@ -0,0 +1,81 @@ -+/* Generated by wayland-scanner 1.17.0 */ ++static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { ++ dmabuf_format, dmabuf_modifiers}; + -+/* -+ * Copyright © 2014, 2015 Collabora, Ltd. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ + static void global_registry_handler(void* data, wl_registry* registry, + uint32_t id, const char* interface, + uint32_t version) { + auto display = reinterpret_cast(data); + if (!display) return; + + if (strcmp(interface, "wl_shm") == 0) { + auto shm = static_cast( +@@ -144,16 +191,21 @@ static void global_registry_handler(void + display->GetEventQueue()); + display->SetPrimarySelectionDeviceManager(primary_selection_device_manager); + } else if (strcmp(interface, "wl_subcompositor") == 0) { + auto subcompositor = static_cast( + wl_registry_bind(registry, id, &wl_subcompositor_interface, 1)); + wl_proxy_set_queue((struct wl_proxy*)subcompositor, + display->GetEventQueue()); + display->SetSubcompositor(subcompositor); ++ } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version > 2) { ++ auto dmabuf = static_cast( ++ wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 3)); ++ display->SetDmabuf(dmabuf); ++ zwp_linux_dmabuf_v1_add_listener(dmabuf, &dmabuf_listener, data); + } + } + + static void global_registry_remover(void* data, wl_registry* registry, + uint32_t id) {} + + static const struct wl_registry_listener registry_listener = { + global_registry_handler, global_registry_remover}; +@@ -162,27 +214,85 @@ bool nsWaylandDisplay::DispatchEventQueu + wl_display_dispatch_queue_pending(mDisplay, mEventQueue); + return true; + } + + bool nsWaylandDisplay::Matches(wl_display* aDisplay) { + return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay; + } + ++bool nsWaylandDisplay::ConfigureGbm() { ++ if (!nsGbmLib::IsAvailable()) { ++ return false; ++ } + -+#include -+#include -+#include "wayland-util.h" ++ // TODO ++ const char* drm_render_node = getenv("MOZ_WAYLAND_DRM_DEVICE"); ++ if (!drm_render_node) { ++ drm_render_node = "/dev/dri/renderD128"; ++ } + -+#pragma GCC visibility push(default) -+extern const struct wl_interface wl_buffer_interface; -+extern const struct wl_interface zwp_linux_buffer_params_v1_interface; -+#pragma GCC visibility pop ++ mGbmFd = open(drm_render_node, O_RDWR); ++ if (mGbmFd < 0) { ++ NS_WARNING( ++ nsPrintfCString("Failed to open drm render node %s\n", drm_render_node) ++ .get()); ++ return false; ++ } + -+static const struct wl_interface* types[] = { -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ &zwp_linux_buffer_params_v1_interface, -+ &wl_buffer_interface, -+ NULL, -+ NULL, -+ NULL, -+ NULL, -+ &wl_buffer_interface, -+}; ++ mGbmDevice = nsGbmLib::CreateDevice(mGbmFd); ++ if (mGbmDevice == nullptr) { ++ NS_WARNING(nsPrintfCString("Failed to create drm render device %s\n", ++ drm_render_node) ++ .get()); ++ close(mGbmFd); ++ return false; ++ } + -+static const struct wl_message zwp_linux_dmabuf_v1_requests[] = { -+ {"destroy", "", types + 0}, -+ {"create_params", "n", types + 6}, -+}; ++ return true; ++} + -+static const struct wl_message zwp_linux_dmabuf_v1_events[] = { -+ {"format", "u", types + 0}, -+ {"modifier", "3uuu", types + 0}, -+}; ++gbm_device* nsWaylandDisplay::GetGbmDevice() { ++ if (!mGdmConfigured) { ++ ConfigureGbm(); ++ mGdmConfigured = true; ++ } ++ return mGbmDevice; ++} + -+const struct wl_interface zwp_linux_dmabuf_v1_interface = { -+ "zwp_linux_dmabuf_v1", 3, 2, -+ zwp_linux_dmabuf_v1_requests, 2, zwp_linux_dmabuf_v1_events, -+}; ++int nsWaylandDisplay::GetGbmDeviceFd() { ++ if (!mGdmConfigured) { ++ ConfigureGbm(); ++ mGdmConfigured = true; ++ } ++ return mGbmFd; ++} ++#endif + -+static const struct wl_message zwp_linux_buffer_params_v1_requests[] = { -+ {"destroy", "", types + 0}, -+ {"add", "huuuuu", types + 0}, -+ {"create", "iiuu", types + 0}, -+ {"create_immed", "2niiuu", types + 7}, -+}; + nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay) + : mDispatcherThreadLoop(nullptr), + mThreadId(PR_GetCurrentThread()), + mDisplay(aDisplay), + mEventQueue(nullptr), + mDataDeviceManager(nullptr), + mSubcompositor(nullptr), + mSeat(nullptr), + mShm(nullptr), + mPrimarySelectionDeviceManager(nullptr), +- mRegistry(nullptr) { ++ mRegistry(nullptr) ++#ifdef HAVE_LIBDRM ++ , ++ mGbmDevice(nullptr), ++ mGbmFd(-1), ++ mGdmConfigured(false), ++ mExplicitSync(false), ++ mXRGBFormat({false, false, -1, nullptr, 0}), ++ mARGBFormat({false, false, -1, nullptr, 0}) ++#endif ++{ + mRegistry = wl_display_get_registry(mDisplay); + wl_registry_add_listener(mRegistry, ®istry_listener, this); + + if (NS_IsMainThread()) { + // Use default event queue in main thread operated by Gtk+. + mEventQueue = nullptr; + wl_display_roundtrip(mDisplay); + wl_display_roundtrip(mDisplay); +@@ -205,10 +315,84 @@ nsWaylandDisplay::~nsWaylandDisplay() { + mRegistry = nullptr; + + if (mEventQueue) { + wl_event_queue_destroy(mEventQueue); + mEventQueue = nullptr; + } + } + ++#ifdef HAVE_LIBDRM ++void* nsGbmLib::sGbmLibHandle = nullptr; ++void* nsGbmLib::sXf86DrmLibHandle = nullptr; ++bool nsGbmLib::sLibLoaded = false; ++CreateDeviceFunc nsGbmLib::sCreateDevice; ++CreateFunc nsGbmLib::sCreate; ++CreateWithModifiersFunc nsGbmLib::sCreateWithModifiers; ++GetModifierFunc nsGbmLib::sGetModifier; ++GetStrideFunc nsGbmLib::sGetStride; ++GetFdFunc nsGbmLib::sGetFd; ++DestroyFunc nsGbmLib::sDestroy; ++MapFunc nsGbmLib::sMap; ++UnmapFunc nsGbmLib::sUnmap; ++GetPlaneCountFunc nsGbmLib::sGetPlaneCount; ++GetHandleForPlaneFunc nsGbmLib::sGetHandleForPlane; ++GetStrideForPlaneFunc nsGbmLib::sGetStrideForPlane; ++GetOffsetFunc nsGbmLib::sGetOffset; ++DrmPrimeHandleToFDFunc nsGbmLib::sDrmPrimeHandleToFD; + -+static const struct wl_message zwp_linux_buffer_params_v1_events[] = { -+ {"created", "n", types + 12}, -+ {"failed", "", types + 0}, -+}; ++bool nsGbmLib::IsAvailable() { ++ if (!Load()) { ++ return false; ++ } ++ return sCreateDevice != nullptr && sCreate != nullptr && ++ sCreateWithModifiers != nullptr && sGetModifier != nullptr && ++ sGetStride != nullptr && sGetFd != nullptr && sDestroy != nullptr && ++ sMap != nullptr && sUnmap != nullptr; ++} + -+const struct wl_interface zwp_linux_buffer_params_v1_interface = { -+ "zwp_linux_buffer_params_v1", 3, 4, -+ zwp_linux_buffer_params_v1_requests, 2, zwp_linux_buffer_params_v1_events, -+}; -diff -up firefox-67.0/widget/gtk/wayland/moz.build.mozilla-1552590 firefox-67.0/widget/gtk/wayland/moz.build ---- firefox-67.0/widget/gtk/wayland/moz.build.mozilla-1552590 2019-05-17 02:35:08.000000000 +0200 -+++ firefox-67.0/widget/gtk/wayland/moz.build 2019-05-27 12:15:32.033414339 +0200 -@@ -9,6 +9,12 @@ with Files("**"): ++bool nsGbmLib::IsModifierAvailable() { ++ if (!Load()) { ++ return false; ++ } ++ return sDrmPrimeHandleToFD != nullptr; ++} ++ ++bool nsGbmLib::Load() { ++ if (!sGbmLibHandle && !sLibLoaded) { ++ sLibLoaded = true; ++ ++ sGbmLibHandle = dlopen("libgbm.so", RTLD_LAZY | RTLD_LOCAL); ++ if (!sGbmLibHandle) { ++ return false; ++ } ++ ++ sCreateDevice = (CreateDeviceFunc)dlsym(sGbmLibHandle, "gbm_create_device"); ++ sCreate = (CreateFunc)dlsym(sGbmLibHandle, "gbm_bo_create"); ++ sCreateWithModifiers = (CreateWithModifiersFunc)dlsym( ++ sGbmLibHandle, "gbm_bo_create_with_modifiers"); ++ sGetModifier = (GetModifierFunc)dlsym(sGbmLibHandle, "gbm_bo_get_modifier"); ++ sGetStride = (GetStrideFunc)dlsym(sGbmLibHandle, "gbm_bo_get_stride"); ++ sGetFd = (GetFdFunc)dlsym(sGbmLibHandle, "gbm_bo_get_fd"); ++ sDestroy = (DestroyFunc)dlsym(sGbmLibHandle, "gbm_bo_destroy"); ++ sMap = (MapFunc)dlsym(sGbmLibHandle, "gbm_bo_map"); ++ sUnmap = (UnmapFunc)dlsym(sGbmLibHandle, "gbm_bo_unmap"); ++ sGetPlaneCount = ++ (GetPlaneCountFunc)dlsym(sGbmLibHandle, "gbm_bo_get_plane_count"); ++ sGetHandleForPlane = (GetHandleForPlaneFunc)dlsym( ++ sGbmLibHandle, "gbm_bo_get_handle_for_plane"); ++ sGetStrideForPlane = (GetStrideForPlaneFunc)dlsym( ++ sGbmLibHandle, "gbm_bo_get_stride_for_plane"); ++ sGetOffset = (GetOffsetFunc)dlsym(sGbmLibHandle, "gbm_bo_get_offset"); ++ ++ sXf86DrmLibHandle = dlopen("libdrm.so", RTLD_LAZY | RTLD_LOCAL); ++ if (sXf86DrmLibHandle) { ++ sDrmPrimeHandleToFD = (DrmPrimeHandleToFDFunc)dlsym(sXf86DrmLibHandle, ++ "drmPrimeHandleToFD"); ++ } ++ } ++ ++ return sGbmLibHandle; ++} ++#endif ++ + } // namespace widget + } // namespace mozilla +diff --git a/widget/gtk/nsWaylandDisplay.h b/widget/gtk/nsWaylandDisplay.h +--- a/widget/gtk/nsWaylandDisplay.h ++++ b/widget/gtk/nsWaylandDisplay.h +@@ -1,24 +1,43 @@ + /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim:expandtab:shiftwidth=4:tabstop=4: + */ + /* 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/. */ - SOURCES += [ - 'gtk-primary-selection-protocol.c', -+ 'linux-dmabuf-unstable-v1-protocol.c' -+] +-#ifndef __MOZ_WAYLAND_REGISTRY_H__ +-#define __MOZ_WAYLAND_REGISTRY_H__ ++#ifndef __MOZ_WAYLAND_DISPLAY_H__ ++#define __MOZ_WAYLAND_DISPLAY_H__ + -+EXPORTS.mozilla.widget += [ -+ 'gtk-primary-selection-client-protocol.h', -+ 'linux-dmabuf-unstable-v1-client-protocol.h', - ] ++#include "mozilla/widget/mozwayland.h" ++#include "mozilla/widget/gtk-primary-selection-client-protocol.h" + +-#include "mozwayland/mozwayland.h" +-#include "wayland/gtk-primary-selection-client-protocol.h" ++#include "base/message_loop.h" // for MessageLoop ++#include "base/task.h" // for NewRunnableMethod, etc ++#include "mozilla/StaticMutex.h" ++ ++#ifdef HAVE_LIBDRM ++# include ++# include ++# include ++# include "mozilla/widget/linux-dmabuf-unstable-v1-client-protocol.h" ++#endif - include('/ipc/chromium/chromium-config.mozbuild') -diff -up firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1552590 firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp ---- firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1552590 2019-05-27 12:15:32.028414340 +0200 -+++ firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp 2019-05-27 12:15:32.033414339 +0200 -@@ -35,6 +35,9 @@ extern mozilla::LazyLogModule gWidgetWay namespace mozilla { namespace widget { -+bool WindowSurfaceWayland::mUseDMABuf = false; -+bool WindowSurfaceWayland::mUseDMABufInitialized = false; -+ - /* - Wayland multi-thread rendering scheme - -@@ -258,7 +261,7 @@ static void buffer_release(void* data, w - - static const struct wl_buffer_listener buffer_listener = {buffer_release}; - --void WindowBackBuffer::Create(int aWidth, int aHeight) { -+void WindowBackBufferShm::Create(int aWidth, int aHeight) { - MOZ_ASSERT(!IsAttached(), "We can't resize attached buffers."); ++struct GbmFormat { ++ bool mIsSupported; ++ bool mHasAlpha; ++ int mFormat; ++ uint64_t* mModifiers; ++ int mModifiersCount; ++}; ++ + // Our general connection to Wayland display server, + // holds our display connection and runs event loop. + class nsWaylandDisplay { + public: + explicit nsWaylandDisplay(wl_display* aDisplay); + virtual ~nsWaylandDisplay(); - int newBufferSize = aWidth * aHeight * BUFFER_BPP; -@@ -268,7 +271,7 @@ void WindowBackBuffer::Create(int aWidth - wl_shm_pool_create_buffer(mShmPool.GetShmPool(), 0, aWidth, aHeight, - aWidth * BUFFER_BPP, WL_SHM_FORMAT_ARGB8888); - wl_proxy_set_queue((struct wl_proxy*)mWaylandBuffer, -- mWaylandDisplay->GetEventQueue()); -+ GetWaylandDisplay()->GetEventQueue()); - wl_buffer_add_listener(mWaylandBuffer, &buffer_listener, this); + bool DispatchEventQueue(); +@@ -41,28 +60,143 @@ class nsWaylandDisplay { + void SetSubcompositor(wl_subcompositor* aSubcompositor); + void SetDataDeviceManager(wl_data_device_manager* aDataDeviceManager); + void SetSeat(wl_seat* aSeat); + void SetPrimarySelectionDeviceManager( + gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager); - mWidth = aWidth; -@@ -280,31 +283,31 @@ void WindowBackBuffer::Create(int aWidth - mWaylandBuffer ? wl_proxy_get_id((struct wl_proxy*)mWaylandBuffer) : -1)); - } + void Shutdown(); --void WindowBackBuffer::Release() { -+void WindowBackBufferShm::Release() { - LOGWAYLAND(("%s [%p]\n", __PRETTY_FUNCTION__, (void*)this)); ++#ifdef HAVE_LIBDRM ++ void SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf); ++ zwp_linux_dmabuf_v1* GetDmabuf() { return mDmabuf; }; ++ gbm_device* GetGbmDevice(); ++ int GetGbmDeviceFd(); ++ bool IsExplicitSyncEnabled() { return mExplicitSync; } ++ GbmFormat* GetGbmFormat(bool aHasAlpha); ++ void AddFormatModifier(bool aHasAlpha, int aFormat, uint32_t mModifierHi, ++ uint32_t mModifierLo); ++#endif ++ + private: ++#ifdef HAVE_LIBDRM ++ bool ConfigureGbm(); ++#endif ++ + MessageLoop* mDispatcherThreadLoop; + PRThread* mThreadId; + wl_display* mDisplay; + wl_event_queue* mEventQueue; + wl_data_device_manager* mDataDeviceManager; + wl_subcompositor* mSubcompositor; + wl_seat* mSeat; + wl_shm* mShm; + gtk_primary_selection_device_manager* mPrimarySelectionDeviceManager; + wl_registry* mRegistry; ++#ifdef HAVE_LIBDRM ++ zwp_linux_dmabuf_v1* mDmabuf; ++ gbm_device* mGbmDevice; ++ int mGbmFd; ++ bool mGdmConfigured; ++ bool mExplicitSync; ++ GbmFormat mXRGBFormat; ++ GbmFormat mARGBFormat; ++#endif + }; - wl_buffer_destroy(mWaylandBuffer); - mWidth = mHeight = 0; - } + void WaylandDispatchDisplays(); + nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr); --void WindowBackBuffer::Clear() { -+void WindowBackBufferShm::Clear() { - memset(mShmPool.GetImageData(), 0, mHeight * mWidth * BUFFER_BPP); - } ++#ifdef HAVE_LIBDRM ++typedef struct gbm_device* (*CreateDeviceFunc)(int); ++typedef struct gbm_bo* (*CreateFunc)(struct gbm_device*, uint32_t, uint32_t, ++ uint32_t, uint32_t); ++typedef struct gbm_bo* (*CreateFunc)(struct gbm_device*, uint32_t, uint32_t, ++ uint32_t, uint32_t); ++typedef struct gbm_bo* (*CreateWithModifiersFunc)(struct gbm_device*, uint32_t, ++ uint32_t, uint32_t, ++ const uint64_t*, ++ const unsigned int); ++typedef uint64_t (*GetModifierFunc)(struct gbm_bo*); ++typedef uint32_t (*GetStrideFunc)(struct gbm_bo*); ++typedef int (*GetFdFunc)(struct gbm_bo*); ++typedef void (*DestroyFunc)(struct gbm_bo*); ++typedef void* (*MapFunc)(struct gbm_bo*, uint32_t, uint32_t, uint32_t, uint32_t, ++ uint32_t, uint32_t*, void**); ++typedef void (*UnmapFunc)(struct gbm_bo*, void*); ++typedef int (*GetPlaneCountFunc)(struct gbm_bo*); ++typedef union gbm_bo_handle (*GetHandleForPlaneFunc)(struct gbm_bo*, int); ++typedef uint32_t (*GetStrideForPlaneFunc)(struct gbm_bo*, int); ++typedef uint32_t (*GetOffsetFunc)(struct gbm_bo*, int); ++ ++typedef int (*DrmPrimeHandleToFDFunc)(int, uint32_t, uint32_t, int*); ++ ++class nsGbmLib { ++ public: ++ static bool Load(); ++ static bool IsAvailable(); ++ static bool IsModifierAvailable(); ++ ++ static struct gbm_device* CreateDevice(int fd) { return sCreateDevice(fd); }; ++ static struct gbm_bo* Create(struct gbm_device* gbm, uint32_t width, ++ uint32_t height, uint32_t format, ++ uint32_t flags) { ++ return sCreate(gbm, width, height, format, flags); ++ } ++ static void Destroy(struct gbm_bo* bo) { sDestroy(bo); } ++ static uint32_t GetStride(struct gbm_bo* bo) { return sGetStride(bo); } ++ static int GetFd(struct gbm_bo* bo) { return sGetFd(bo); } ++ static void* Map(struct gbm_bo* bo, uint32_t x, uint32_t y, uint32_t width, ++ uint32_t height, uint32_t flags, uint32_t* stride, ++ void** map_data) { ++ return sMap(bo, x, y, width, height, flags, stride, map_data); ++ } ++ static void Unmap(struct gbm_bo* bo, void* map_data) { sUnmap(bo, map_data); } ++ static struct gbm_bo* CreateWithModifiers(struct gbm_device* gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, ++ const uint64_t* modifiers, ++ const unsigned int count) { ++ return sCreateWithModifiers(gbm, width, height, format, modifiers, count); ++ } ++ static uint64_t GetModifier(struct gbm_bo* bo) { return sGetModifier(bo); } ++ static int GetPlaneCount(struct gbm_bo* bo) { return sGetPlaneCount(bo); } ++ static union gbm_bo_handle GetHandleForPlane(struct gbm_bo* bo, int plane) { ++ return sGetHandleForPlane(bo, plane); ++ } ++ static uint32_t GetStrideForPlane(struct gbm_bo* bo, int plane) { ++ return sGetStrideForPlane(bo, plane); ++ } ++ static uint32_t GetOffset(struct gbm_bo* bo, int plane) { ++ return sGetOffset(bo, plane); ++ } ++ ++ static int DrmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, ++ int* prime_fd) { ++ return sDrmPrimeHandleToFD(fd, handle, flags, prime_fd); ++ } ++ ++ private: ++ static CreateDeviceFunc sCreateDevice; ++ static CreateFunc sCreate; ++ static CreateWithModifiersFunc sCreateWithModifiers; ++ static GetModifierFunc sGetModifier; ++ static GetStrideFunc sGetStride; ++ static GetFdFunc sGetFd; ++ static DestroyFunc sDestroy; ++ static MapFunc sMap; ++ static UnmapFunc sUnmap; ++ static GetPlaneCountFunc sGetPlaneCount; ++ static GetHandleForPlaneFunc sGetHandleForPlane; ++ static GetStrideForPlaneFunc sGetStrideForPlane; ++ static GetOffsetFunc sGetOffset; ++ static DrmPrimeHandleToFDFunc sDrmPrimeHandleToFD; ++ ++ static void* sGbmLibHandle; ++ static void* sXf86DrmLibHandle; ++ static bool sLibLoaded; ++}; ++#endif ++ + } // namespace widget + } // namespace mozilla --WindowBackBuffer::WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay, -- int aWidth, int aHeight) -- : mShmPool(aWaylandDisplay, aWidth * aHeight * BUFFER_BPP), -+WindowBackBufferShm::WindowBackBufferShm(nsWaylandDisplay* aWaylandDisplay, -+ int aWidth, int aHeight) -+ : WindowBackBuffer(aWaylandDisplay), -+ mShmPool(aWaylandDisplay, aWidth * aHeight * BUFFER_BPP), - mWaylandBuffer(nullptr), - mWidth(aWidth), - mHeight(aHeight), -- mAttached(false), -- mWaylandDisplay(aWaylandDisplay) { -+ mAttached(false) { - Create(aWidth, aHeight); +-#endif // __MOZ_WAYLAND_REGISTRY_H__ ++#endif // __MOZ_WAYLAND_DISPLAY_H__ +diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp +--- a/widget/gtk/nsWindow.cpp ++++ b/widget/gtk/nsWindow.cpp +@@ -4237,17 +4237,18 @@ LayoutDeviceIntSize nsWindow::GetSafeWin + // reads it as CARD16. Sizes of pixmaps, used for drawing, are (unsigned) + // CARD16 in the protocol, but the server's ProcCreatePixmap returns + // BadAlloc if dimensions cannot be represented by signed shorts. + // Because we are creating Cairo surfaces to represent window buffers, + // we also must ensure that the window can fit in a Cairo surface. + LayoutDeviceIntSize result = aSize; + int32_t maxSize = 32767; + if (mLayerManager && mLayerManager->AsKnowsCompositor()) { +- maxSize = std::min(maxSize, mLayerManager->AsKnowsCompositor()->GetMaxTextureSize()); ++ maxSize = std::min(maxSize, ++ mLayerManager->AsKnowsCompositor()->GetMaxTextureSize()); + } + if (result.width > maxSize) { + result.width = maxSize; + } + if (result.height > maxSize) { + result.height = maxSize; + } + return result; +@@ -6827,21 +6828,24 @@ wl_surface* nsWindow::GetWaylandSurface( + "drawing!"); + return nullptr; } --WindowBackBuffer::~WindowBackBuffer() { Release(); } -+WindowBackBufferShm::~WindowBackBufferShm() { Release(); } - --bool WindowBackBuffer::Resize(int aWidth, int aHeight) { -+bool WindowBackBufferShm::Resize(int aWidth, int aHeight) { - if (aWidth == mWidth && aHeight == mHeight) return true; - - LOGWAYLAND( -@@ -317,20 +320,20 @@ bool WindowBackBuffer::Resize(int aWidth + bool nsWindow::WaylandSurfaceNeedsClear() { + if (mContainer) { + return moz_container_surface_needs_clear(MOZ_CONTAINER(mContainer)); + } +- +- NS_WARNING( +- "nsWindow::WaylandSurfaceNeedsClear(): We don't have any mContainer!"); + return false; } ++ ++void nsWindow::WaylandSurfaceCleared() { ++ if (mContainer) { ++ return moz_container_surface_cleared(MOZ_CONTAINER(mContainer)); ++ } ++} + #endif - void WindowBackBuffer::Attach(wl_surface* aSurface) { -- LOGWAYLAND(( -- "%s [%p] wl_surface %p ID %d wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, -- (void*)this, (void*)aSurface, -- aSurface ? wl_proxy_get_id((struct wl_proxy*)aSurface) : -1, -- (void*)mWaylandBuffer, -- mWaylandBuffer ? wl_proxy_get_id((struct wl_proxy*)mWaylandBuffer) : -1)); -+ LOGWAYLAND( -+ ("%s [%p] wl_surface %p ID %d wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, -+ (void*)this, (void*)aSurface, -+ aSurface ? wl_proxy_get_id((struct wl_proxy*)aSurface) : -1, -+ (void*)GetWlBuffer(), -+ GetWlBuffer() ? wl_proxy_get_id((struct wl_proxy*)GetWlBuffer()) : -1)); - -- wl_surface_attach(aSurface, mWaylandBuffer, 0, 0); -+ wl_surface_attach(aSurface, GetWlBuffer(), 0, 0); - wl_surface_commit(aSurface); -- wl_display_flush(mWaylandDisplay->GetDisplay()); -- mAttached = true; -+ wl_display_flush(GetWaylandDisplay()->GetDisplay()); -+ SetAttached(); - } + #ifdef MOZ_X11 + /* XApp progress support currently works by setting a property + * on a window with this Atom name. A supporting window manager + * will notice this and pass it along to whatever handling has + * been implemented on that end (e.g. passing it on to a taskbar + * widget.) There is no issue if WM support is lacking, this is +diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h +--- a/widget/gtk/nsWindow.h ++++ b/widget/gtk/nsWindow.h +@@ -341,16 +341,17 @@ class nsWindow final : public nsBaseWidg --void WindowBackBuffer::Detach(wl_buffer* aBuffer) { -+void WindowBackBufferShm::Detach(wl_buffer* aBuffer) { - LOGWAYLAND(("%s [%p] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, (void*)this, - (void*)aBuffer, - aBuffer ? wl_proxy_get_id((struct wl_proxy*)aBuffer) : -1)); -@@ -338,19 +341,20 @@ void WindowBackBuffer::Detach(wl_buffer* - mAttached = false; - } + #ifdef MOZ_X11 + Display* XDisplay() { return mXDisplay; } + #endif + #ifdef MOZ_WAYLAND + wl_display* GetWaylandDisplay(); + wl_surface* GetWaylandSurface(); + bool WaylandSurfaceNeedsClear(); ++ void WaylandSurfaceCleared(); + #endif + virtual void GetCompositorWidgetInitData( + mozilla::widget::CompositorWidgetInitData* aInitData) override; --bool WindowBackBuffer::SetImageDataFromBuffer( -+bool WindowBackBufferShm::SetImageDataFromBuffer( - class WindowBackBuffer* aSourceBuffer) { -- if (!IsMatchingSize(aSourceBuffer)) { -- Resize(aSourceBuffer->mWidth, aSourceBuffer->mHeight); -+ auto sourceBuffer = static_cast(aSourceBuffer); -+ if (!IsMatchingSize(sourceBuffer)) { -+ Resize(sourceBuffer->mWidth, sourceBuffer->mHeight); - } - - mShmPool.SetImageDataFromPool( -- &aSourceBuffer->mShmPool, -- aSourceBuffer->mWidth * aSourceBuffer->mHeight * BUFFER_BPP); -+ &sourceBuffer->mShmPool, -+ sourceBuffer->mWidth * sourceBuffer->mHeight * BUFFER_BPP); - return true; - } - --already_AddRefed WindowBackBuffer::Lock() { -+already_AddRefed WindowBackBufferShm::Lock() { - LOGWAYLAND(( - "%s [%p] [%d x %d] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, - (void*)this, mWidth, mHeight, (void*)mWaylandBuffer, -@@ -359,9 +363,71 @@ already_AddRefed Window - gfx::IntSize lockSize(mWidth, mHeight); - return gfxPlatform::CreateDrawTargetForData( - static_cast(mShmPool.GetImageData()), lockSize, -- BUFFER_BPP * mWidth, mFormat); -+ BUFFER_BPP * mWidth, GetSurfaceFormat()); -+} + virtual nsresult SetNonClientMargins( + LayoutDeviceIntMargin& aMargins) override; + void SetDrawsInTitlebar(bool aState) override; + virtual void UpdateWindowDraggingRegion( +diff --git a/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h b/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h +new file mode 100644 +--- /dev/null ++++ b/widget/gtk/wayland/linux-dmabuf-unstable-v1-client-protocol.h +@@ -0,0 +1,650 @@ ++/* Generated by wayland-scanner 1.17.0 */ + -+#ifdef HAVE_LIBDRM -+WindowBackBufferDMABuf::WindowBackBufferDMABuf( -+ nsWaylandDisplay* aWaylandDisplay, int aWidth, int aHeight) -+ : WindowBackBuffer(aWaylandDisplay) { -+ mDMAbufSurface.Create(aWidth, aHeight); - } - -+WindowBackBufferDMABuf::~WindowBackBufferDMABuf() { mDMAbufSurface.Release(); } ++#ifndef LINUX_DMABUF_UNSTABLE_V1_CLIENT_PROTOCOL_H ++#define LINUX_DMABUF_UNSTABLE_V1_CLIENT_PROTOCOL_H + -+already_AddRefed WindowBackBufferDMABuf::Lock() { -+ LOGWAYLAND( -+ ("%s [%p] [%d x %d] wl_buffer %p ID %d\n", __PRETTY_FUNCTION__, -+ (void*)this, GetWidth(), GetHeight(), (void*)GetWlBuffer(), -+ GetWlBuffer() ? wl_proxy_get_id((struct wl_proxy*)GetWlBuffer()) : -1)); ++#include ++#include ++#include "wayland-client.h" + -+ uint32_t stride; -+ void* pixels = mDMAbufSurface.Map(&stride); -+ gfx::IntSize lockSize(GetWidth(), GetHeight()); -+ return gfxPlatform::CreateDrawTargetForData( -+ static_cast(pixels), lockSize, stride, -+ GetSurfaceFormat()); -+} ++#ifdef __cplusplus ++extern "C" { ++#endif + -+void WindowBackBufferDMABuf::Unlock() { mDMAbufSurface.Unmap(); } ++/** ++ * @page page_linux_dmabuf_unstable_v1 The linux_dmabuf_unstable_v1 protocol ++ * @section page_ifaces_linux_dmabuf_unstable_v1 Interfaces ++ * - @subpage page_iface_zwp_linux_dmabuf_v1 - factory for creating dmabuf-based ++ * wl_buffers ++ * - @subpage page_iface_zwp_linux_buffer_params_v1 - parameters for creating a ++ * dmabuf-based wl_buffer ++ * @section page_copyright_linux_dmabuf_unstable_v1 Copyright ++ *
++ *
++ * Copyright © 2014, 2015 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ * 
++ */ ++struct wl_buffer; ++struct zwp_linux_buffer_params_v1; ++struct zwp_linux_dmabuf_v1; + -+bool WindowBackBufferDMABuf::IsAttached() { -+ return mDMAbufSurface.WLBufferIsAttached(); -+} ++/** ++ * @page page_iface_zwp_linux_dmabuf_v1 zwp_linux_dmabuf_v1 ++ * @section page_iface_zwp_linux_dmabuf_v1_desc Description ++ * ++ * Following the interfaces from: ++ * https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt ++ * and the Linux DRM sub-system's AddFb2 ioctl. ++ * ++ * This interface offers ways to create generic dmabuf-based ++ * wl_buffers. Immediately after a client binds to this interface, ++ * the set of supported formats and format modifiers is sent with ++ * 'format' and 'modifier' events. ++ * ++ * The following are required from clients: ++ * ++ * - Clients must ensure that either all data in the dma-buf is ++ * coherent for all subsequent read access or that coherency is ++ * correctly handled by the underlying kernel-side dma-buf ++ * implementation. ++ * ++ * - Don't make any more attachments after sending the buffer to the ++ * compositor. Making more attachments later increases the risk of ++ * the compositor not being able to use (re-import) an existing ++ * dmabuf-based wl_buffer. ++ * ++ * The underlying graphics stack must ensure the following: ++ * ++ * - The dmabuf file descriptors relayed to the server will stay valid ++ * for the whole lifetime of the wl_buffer. This means the server may ++ * at any time use those fds to import the dmabuf into any kernel ++ * sub-system that might accept it. ++ * ++ * To create a wl_buffer from one or more dmabufs, a client creates a ++ * zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params ++ * request. All planes required by the intended format are added with ++ * the 'add' request. Finally, a 'create' or 'create_immed' request is ++ * issued, which has the following outcome depending on the import success. ++ * ++ * The 'create' request, ++ * - on success, triggers a 'created' event which provides the final ++ * wl_buffer to the client. ++ * - on failure, triggers a 'failed' event to convey that the server ++ * cannot use the dmabufs received from the client. ++ * ++ * For the 'create_immed' request, ++ * - on success, the server immediately imports the added dmabufs to ++ * create a wl_buffer. No event is sent from the server in this case. ++ * - on failure, the server can choose to either: ++ * - terminate the client by raising a fatal error. ++ * - mark the wl_buffer as failed, and send a 'failed' event to the ++ * client. If the client uses a failed wl_buffer as an argument to any ++ * request, the behaviour is compositor implementation-defined. ++ * ++ * Warning! The protocol described in this file is experimental and ++ * backward incompatible changes may be made. Backward compatible changes ++ * may be added together with the corresponding interface version bump. ++ * Backward incompatible changes are done by bumping the version number in ++ * the protocol and interface names and resetting the interface version. ++ * Once the protocol is to be declared stable, the 'z' prefix and the ++ * version number in the protocol and interface names are removed and the ++ * interface version number is reset. ++ * @section page_iface_zwp_linux_dmabuf_v1_api API ++ * See @ref iface_zwp_linux_dmabuf_v1. ++ */ ++/** ++ * @defgroup iface_zwp_linux_dmabuf_v1 The zwp_linux_dmabuf_v1 interface ++ * ++ * Following the interfaces from: ++ * https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt ++ * and the Linux DRM sub-system's AddFb2 ioctl. ++ * ++ * This interface offers ways to create generic dmabuf-based ++ * wl_buffers. Immediately after a client binds to this interface, ++ * the set of supported formats and format modifiers is sent with ++ * 'format' and 'modifier' events. ++ * ++ * The following are required from clients: ++ * ++ * - Clients must ensure that either all data in the dma-buf is ++ * coherent for all subsequent read access or that coherency is ++ * correctly handled by the underlying kernel-side dma-buf ++ * implementation. ++ * ++ * - Don't make any more attachments after sending the buffer to the ++ * compositor. Making more attachments later increases the risk of ++ * the compositor not being able to use (re-import) an existing ++ * dmabuf-based wl_buffer. ++ * ++ * The underlying graphics stack must ensure the following: ++ * ++ * - The dmabuf file descriptors relayed to the server will stay valid ++ * for the whole lifetime of the wl_buffer. This means the server may ++ * at any time use those fds to import the dmabuf into any kernel ++ * sub-system that might accept it. ++ * ++ * To create a wl_buffer from one or more dmabufs, a client creates a ++ * zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params ++ * request. All planes required by the intended format are added with ++ * the 'add' request. Finally, a 'create' or 'create_immed' request is ++ * issued, which has the following outcome depending on the import success. ++ * ++ * The 'create' request, ++ * - on success, triggers a 'created' event which provides the final ++ * wl_buffer to the client. ++ * - on failure, triggers a 'failed' event to convey that the server ++ * cannot use the dmabufs received from the client. ++ * ++ * For the 'create_immed' request, ++ * - on success, the server immediately imports the added dmabufs to ++ * create a wl_buffer. No event is sent from the server in this case. ++ * - on failure, the server can choose to either: ++ * - terminate the client by raising a fatal error. ++ * - mark the wl_buffer as failed, and send a 'failed' event to the ++ * client. If the client uses a failed wl_buffer as an argument to any ++ * request, the behaviour is compositor implementation-defined. ++ * ++ * Warning! The protocol described in this file is experimental and ++ * backward incompatible changes may be made. Backward compatible changes ++ * may be added together with the corresponding interface version bump. ++ * Backward incompatible changes are done by bumping the version number in ++ * the protocol and interface names and resetting the interface version. ++ * Once the protocol is to be declared stable, the 'z' prefix and the ++ * version number in the protocol and interface names are removed and the ++ * interface version number is reset. ++ */ ++extern const struct wl_interface zwp_linux_dmabuf_v1_interface; ++/** ++ * @page page_iface_zwp_linux_buffer_params_v1 zwp_linux_buffer_params_v1 ++ * @section page_iface_zwp_linux_buffer_params_v1_desc Description ++ * ++ * This temporary object is a collection of dmabufs and other ++ * parameters that together form a single logical buffer. The temporary ++ * object may eventually create one wl_buffer unless cancelled by ++ * destroying it before requesting 'create'. ++ * ++ * Single-planar formats only require one dmabuf, however ++ * multi-planar formats may require more than one dmabuf. For all ++ * formats, an 'add' request must be called once per plane (even if the ++ * underlying dmabuf fd is identical). ++ * ++ * You must use consecutive plane indices ('plane_idx' argument for 'add') ++ * from zero to the number of planes used by the drm_fourcc format code. ++ * All planes required by the format must be given exactly once, but can ++ * be given in any order. Each plane index can be set only once. ++ * @section page_iface_zwp_linux_buffer_params_v1_api API ++ * See @ref iface_zwp_linux_buffer_params_v1. ++ */ ++/** ++ * @defgroup iface_zwp_linux_buffer_params_v1 The zwp_linux_buffer_params_v1 ++ * interface ++ * ++ * This temporary object is a collection of dmabufs and other ++ * parameters that together form a single logical buffer. The temporary ++ * object may eventually create one wl_buffer unless cancelled by ++ * destroying it before requesting 'create'. ++ * ++ * Single-planar formats only require one dmabuf, however ++ * multi-planar formats may require more than one dmabuf. For all ++ * formats, an 'add' request must be called once per plane (even if the ++ * underlying dmabuf fd is identical). ++ * ++ * You must use consecutive plane indices ('plane_idx' argument for 'add') ++ * from zero to the number of planes used by the drm_fourcc format code. ++ * All planes required by the format must be given exactly once, but can ++ * be given in any order. Each plane index can be set only once. ++ */ ++extern const struct wl_interface zwp_linux_buffer_params_v1_interface; + -+void WindowBackBufferDMABuf::SetAttached() { -+ return mDMAbufSurface.WLBufferSetAttached(); ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ * @struct zwp_linux_dmabuf_v1_listener ++ */ ++struct zwp_linux_dmabuf_v1_listener { ++ /** ++ * supported buffer format ++ * ++ * This event advertises one buffer format that the server ++ * supports. All the supported formats are advertised once when the ++ * client binds to this interface. A roundtrip after binding ++ * guarantees that the client has received all supported formats. ++ * ++ * For the definition of the format codes, see the ++ * zwp_linux_buffer_params_v1::create request. ++ * ++ * Warning: the 'format' event is likely to be deprecated and ++ * replaced with the 'modifier' event introduced in ++ * zwp_linux_dmabuf_v1 version 3, described below. Please refrain ++ * from using the information received from this event. ++ * @param format DRM_FORMAT code ++ */ ++ void (*format)(void* data, struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, ++ uint32_t format); ++ /** ++ * supported buffer format modifier ++ * ++ * This event advertises the formats that the server supports, ++ * along with the modifiers supported for each format. All the ++ * supported modifiers for all the supported formats are advertised ++ * once when the client binds to this interface. A roundtrip after ++ * binding guarantees that the client has received all supported ++ * format-modifier pairs. ++ * ++ * For the definition of the format and modifier codes, see the ++ * zwp_linux_buffer_params_v1::create request. ++ * @param format DRM_FORMAT code ++ * @param modifier_hi high 32 bits of layout modifier ++ * @param modifier_lo low 32 bits of layout modifier ++ * @since 3 ++ */ ++ void (*modifier)(void* data, struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, ++ uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo); ++}; ++ ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ */ ++static inline int zwp_linux_dmabuf_v1_add_listener( ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, ++ const struct zwp_linux_dmabuf_v1_listener* listener, void* data) { ++ return wl_proxy_add_listener((struct wl_proxy*)zwp_linux_dmabuf_v1, ++ (void (**)(void))listener, data); +} + -+int WindowBackBufferDMABuf::GetWidth() { return mDMAbufSurface.GetWidth(); } ++#define ZWP_LINUX_DMABUF_V1_DESTROY 0 ++#define ZWP_LINUX_DMABUF_V1_CREATE_PARAMS 1 + -+int WindowBackBufferDMABuf::GetHeight() { return mDMAbufSurface.GetHeight(); } ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ */ ++#define ZWP_LINUX_DMABUF_V1_FORMAT_SINCE_VERSION 1 ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ */ ++#define ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION 3 + -+wl_buffer* WindowBackBufferDMABuf::GetWlBuffer() { -+ return mDMAbufSurface.GetWLBuffer(); ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ */ ++#define ZWP_LINUX_DMABUF_V1_DESTROY_SINCE_VERSION 1 ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ */ ++#define ZWP_LINUX_DMABUF_V1_CREATE_PARAMS_SINCE_VERSION 1 ++ ++/** @ingroup iface_zwp_linux_dmabuf_v1 */ ++static inline void zwp_linux_dmabuf_v1_set_user_data( ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, void* user_data) { ++ wl_proxy_set_user_data((struct wl_proxy*)zwp_linux_dmabuf_v1, user_data); +} + -+bool WindowBackBufferDMABuf::IsLocked() { return mDMAbufSurface.IsMapped(); } ++/** @ingroup iface_zwp_linux_dmabuf_v1 */ ++static inline void* zwp_linux_dmabuf_v1_get_user_data( ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { ++ return wl_proxy_get_user_data((struct wl_proxy*)zwp_linux_dmabuf_v1); ++} + -+bool WindowBackBufferDMABuf::Resize(int aWidth, int aHeight) { -+ return mDMAbufSurface.Resize(aWidth, aHeight); ++static inline uint32_t zwp_linux_dmabuf_v1_get_version( ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { ++ return wl_proxy_get_version((struct wl_proxy*)zwp_linux_dmabuf_v1); +} + -+bool WindowBackBufferDMABuf::SetImageDataFromBuffer( -+ class WindowBackBuffer* aSourceBuffer) { -+ WindowBackBufferDMABuf* source = -+ static_cast(aSourceBuffer); -+ mDMAbufSurface.CopyFrom(&source->mDMAbufSurface); -+ return true; ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ * ++ * Objects created through this interface, especially wl_buffers, will ++ * remain valid. ++ */ ++static inline void zwp_linux_dmabuf_v1_destroy( ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { ++ wl_proxy_marshal((struct wl_proxy*)zwp_linux_dmabuf_v1, ++ ZWP_LINUX_DMABUF_V1_DESTROY); ++ ++ wl_proxy_destroy((struct wl_proxy*)zwp_linux_dmabuf_v1); +} + -+void WindowBackBufferDMABuf::Detach(wl_buffer* aBuffer) { -+ mDMAbufSurface.WLBufferDetach(); ++/** ++ * @ingroup iface_zwp_linux_dmabuf_v1 ++ * ++ * This temporary object is used to collect multiple dmabuf handles into ++ * a single batch to create a wl_buffer. It can only be used once and ++ * should be destroyed after a 'created' or 'failed' event has been ++ * received. ++ */ ++static inline struct zwp_linux_buffer_params_v1* ++zwp_linux_dmabuf_v1_create_params( ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1) { ++ struct wl_proxy* params_id; ++ ++ params_id = wl_proxy_marshal_constructor( ++ (struct wl_proxy*)zwp_linux_dmabuf_v1, ZWP_LINUX_DMABUF_V1_CREATE_PARAMS, ++ &zwp_linux_buffer_params_v1_interface, NULL); ++ ++ return (struct zwp_linux_buffer_params_v1*)params_id; +} + -+void WindowBackBufferDMABuf::Clear() { mDMAbufSurface.Clear(); } -+#endif ++#ifndef ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ENUM ++# define ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ENUM ++enum zwp_linux_buffer_params_v1_error { ++ /** ++ * the dmabuf_batch object has already been used to create a wl_buffer ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED = 0, ++ /** ++ * plane index out of bounds ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX = 1, ++ /** ++ * the plane index was already set ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET = 2, ++ /** ++ * missing or too many planes to create a buffer ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE = 3, ++ /** ++ * format not supported ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT = 4, ++ /** ++ * invalid width or height ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS = 5, ++ /** ++ * offset + stride * height goes out of dmabuf bounds ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS = 6, ++ /** ++ * invalid wl_buffer resulted from importing dmabufs via the ++ * create_immed request on given buffer_params ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER = 7, ++}; ++#endif /* ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ENUM */ ++ ++#ifndef ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_ENUM ++# define ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_ENUM ++enum zwp_linux_buffer_params_v1_flags { ++ /** ++ * contents are y-inverted ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT = 1, ++ /** ++ * content is interlaced ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED = 2, ++ /** ++ * bottom field first ++ */ ++ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_BOTTOM_FIRST = 4, ++}; ++#endif /* ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_ENUM */ + - static void frame_callback_handler(void* data, struct wl_callback* callback, - uint32_t time) { - auto surface = reinterpret_cast(data); -@@ -415,13 +481,50 @@ WindowSurfaceWayland::~WindowSurfaceWayl - } - } - --WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(int aWidth, -- int aHeight) { -+bool WindowSurfaceWayland::UseDMABufBackend() { -+ if (!mUseDMABufInitialized) { -+#ifdef HAVE_LIBDRM -+ if (WaylandDMABufSurface::IsAvailable()) { -+ mUseDMABuf = -+ Preferences::GetBool("gfx.wayland_dmabuf_backend.enabled", false); -+ } -+#endif -+ mUseDMABufInitialized = true; -+ } -+ return mUseDMABuf; -+} ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ * @struct zwp_linux_buffer_params_v1_listener ++ */ ++struct zwp_linux_buffer_params_v1_listener { ++ /** ++ * buffer creation succeeded ++ * ++ * This event indicates that the attempted buffer creation was ++ * successful. It provides the new wl_buffer referencing the ++ * dmabuf(s). ++ * ++ * Upon receiving this event, the client should destroy the ++ * zlinux_dmabuf_params object. ++ * @param buffer the newly created wl_buffer ++ */ ++ void (*created)(void* data, ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, ++ struct wl_buffer* buffer); ++ /** ++ * buffer creation failed ++ * ++ * This event indicates that the attempted buffer creation has ++ * failed. It usually means that one of the dmabuf constraints has ++ * not been fulfilled. ++ * ++ * Upon receiving this event, the client should destroy the ++ * zlinux_buffer_params object. ++ */ ++ void (*failed)(void* data, ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1); ++}; + -+WindowBackBuffer* WindowSurfaceWayland::CreateWaylandBuffer(int aWidth, -+ int aHeight) { -+ if (UseDMABufBackend()) { -+ static bool sDMABufBufferCreated = false; -+ WindowBackBuffer* buffer = -+ new WindowBackBufferDMABuf(mWaylandDisplay, aWidth, aHeight); -+ if (buffer) { -+ sDMABufBufferCreated = true; -+ return buffer; -+ } -+ // If this is the first failure and there's no dmabuf already active -+ // we can safely fallback to Shm. Otherwise we can't mix DMAbuf and -+ // SHM buffers so just fails now. -+ if (sDMABufBufferCreated) { -+ NS_WARNING("Failed to allocate DMABuf buffer!"); -+ return nullptr; -+ } else { -+ NS_WARNING("Wayland DMABuf failed, switched back to Shm backend!"); -+ mUseDMABuf = false; -+ } -+ } -+ return new WindowBackBufferShm(mWaylandDisplay, aWidth, aHeight); ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++static inline int zwp_linux_buffer_params_v1_add_listener( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, ++ const struct zwp_linux_buffer_params_v1_listener* listener, void* data) { ++ return wl_proxy_add_listener((struct wl_proxy*)zwp_linux_buffer_params_v1, ++ (void (**)(void))listener, data); +} + -+WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw( -+ int aWidth, int aHeight, bool aFullScreenUpdate, bool aNoBackBufferCopy) { - if (!mWaylandBuffer) { - LOGWAYLAND(("%s [%p] Create [%d x %d]\n", __PRETTY_FUNCTION__, (void*)this, - aWidth, aHeight)); - -- mWaylandBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); -+ mWaylandBuffer = CreateWaylandBuffer(aWidth, aHeight); - mWaitToFullScreenUpdate = true; - return mWaylandBuffer; - } -@@ -447,8 +550,7 @@ WindowBackBuffer* WindowSurfaceWayland:: - for (availableBuffer = 0; availableBuffer < BACK_BUFFER_NUM; - availableBuffer++) { - if (!mBackupBuffer[availableBuffer]) { -- mBackupBuffer[availableBuffer] = -- new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); -+ mBackupBuffer[availableBuffer] = CreateWaylandBuffer(aWidth, aHeight); - break; - } - -@@ -464,17 +566,26 @@ WindowBackBuffer* WindowSurfaceWayland:: - 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 (lastWaylandBuffer->IsMatchingSize(aWidth, aHeight)) { -- LOGWAYLAND(("%s [%p] Copy from old buffer [%d x %d]\n", __PRETTY_FUNCTION__, -- (void*)this, aWidth, aHeight)); -+ 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. -- mWaylandBuffer->SetImageDataFromBuffer(lastWaylandBuffer); -+ // 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; -@@ -491,11 +602,15 @@ WindowBackBuffer* WindowSurfaceWayland:: - } - - already_AddRefed WindowSurfaceWayland::LockWaylandBuffer( -- int aWidth, int aHeight, bool aClearBuffer) { -- WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight); -+ int aWidth, int aHeight, bool aClearBuffer, bool aFullScreenUpdate, -+ bool aNoBackBufferCopy) { -+ WindowBackBuffer* buffer = GetWaylandBufferToDraw( -+ aWidth, aHeight, aFullScreenUpdate, aNoBackBufferCopy); - if (!buffer) { -- NS_WARNING( -- "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); -+ if (!aNoBackBufferCopy) { -+ NS_WARNING( -+ "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); -+ } - return nullptr; - } - -@@ -506,6 +621,8 @@ already_AddRefed Window - return buffer->Lock(); - } - -+void WindowSurfaceWayland::UnlockWaylandBuffer() { mWaylandBuffer->Unlock(); } ++#define ZWP_LINUX_BUFFER_PARAMS_V1_DESTROY 0 ++#define ZWP_LINUX_BUFFER_PARAMS_V1_ADD 1 ++#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE 2 ++#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED 3 + - already_AddRefed WindowSurfaceWayland::LockImageSurface( - const gfx::IntSize& aLockSize) { - if (!mImageSurface || mImageSurface->CairoStatus() || -@@ -555,10 +672,18 @@ already_AddRefed Window - lockSize.height == screenRect.height); - - if (mDrawToWaylandBufferDirectly) { -- RefPtr dt = -- LockWaylandBuffer(screenRect.width, screenRect.height, -- mWindow->WaylandSurfaceNeedsClear()); -+ // If there's any pending image commit scratch them as we're going -+ // to redraw the whole sceen anyway. -+ mDelayedImageCommits.Clear(); ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATED_SINCE_VERSION 1 ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++#define ZWP_LINUX_BUFFER_PARAMS_V1_FAILED_SINCE_VERSION 1 + -+ bool needsClear = mWindow->WaylandSurfaceNeedsClear(); -+ RefPtr dt = LockWaylandBuffer( -+ screenRect.width, screenRect.height, needsClear, -+ /* aFullScreenUpdate */ true, /* aNoBackBufferCopy */ true); - if (dt) { -+ if (needsClear) { -+ mWindow->WaylandSurfaceCleared(); -+ } - // 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. -@@ -577,8 +702,49 @@ already_AddRefed Window - return LockImageSurface(lockSize); - } - -+void WindowImageSurface::Draw(gfx::SourceSurface* aSurface, -+ gfx::DrawTarget* aDest, -+ const LayoutDeviceIntRegion& aRegion) { -+ uint32_t numRects = aRegion.GetNumRects(); -+ if (numRects != 1) { -+ AutoTArray rects; -+ rects.SetCapacity(numRects); -+ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { -+ rects.AppendElement(iter.Get().ToUnknownRect()); -+ } -+ aDest->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); -+ } ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++#define ZWP_LINUX_BUFFER_PARAMS_V1_DESTROY_SINCE_VERSION 1 ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++#define ZWP_LINUX_BUFFER_PARAMS_V1_ADD_SINCE_VERSION 1 ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_SINCE_VERSION 1 ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ */ ++#define ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED_SINCE_VERSION 2 + -+ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); -+ gfx::Rect rect(bounds); -+ aDest->DrawSurface(aSurface, rect, rect); ++/** @ingroup iface_zwp_linux_buffer_params_v1 */ ++static inline void zwp_linux_buffer_params_v1_set_user_data( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, ++ void* user_data) { ++ wl_proxy_set_user_data((struct wl_proxy*)zwp_linux_buffer_params_v1, ++ user_data); ++} + -+ if (numRects != 1) { -+ aDest->PopClip(); -+ } ++/** @ingroup iface_zwp_linux_buffer_params_v1 */ ++static inline void* zwp_linux_buffer_params_v1_get_user_data( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1) { ++ return wl_proxy_get_user_data((struct wl_proxy*)zwp_linux_buffer_params_v1); +} + -+void WindowImageSurface::Draw(gfx::DrawTarget* aDest, -+ LayoutDeviceIntRegion& aWaylandBufferDamage) { -+ Draw(mSurface.get(), aDest, mUpdateRegion); -+ aWaylandBufferDamage.OrWith(mUpdateRegion); ++static inline uint32_t zwp_linux_buffer_params_v1_get_version( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1) { ++ return wl_proxy_get_version((struct wl_proxy*)zwp_linux_buffer_params_v1); +} + -+WindowImageSurface::WindowImageSurface( -+ gfx::SourceSurface* aSurface, const LayoutDeviceIntRegion& aUpdateRegion) -+ : mSurface(aSurface), mUpdateRegion(aUpdateRegion){}; ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ * ++ * Cleans up the temporary data sent to the server for dmabuf-based ++ * wl_buffer creation. ++ */ ++static inline void zwp_linux_buffer_params_v1_destroy( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1) { ++ wl_proxy_marshal((struct wl_proxy*)zwp_linux_buffer_params_v1, ++ ZWP_LINUX_BUFFER_PARAMS_V1_DESTROY); + -+void WindowSurfaceWayland::DrawDelayedImageCommits( -+ gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage) { -+ for (unsigned int i = 0; i < mDelayedImageCommits.Length(); i++) { -+ mDelayedImageCommits[i].Draw(aDrawTarget, aWaylandBufferDamage); -+ } -+ mDelayedImageCommits.Clear(); ++ wl_proxy_destroy((struct wl_proxy*)zwp_linux_buffer_params_v1); +} + - bool WindowSurfaceWayland::CommitImageSurfaceToWaylandBuffer( -- const LayoutDeviceIntRegion& aRegion) { -+ const LayoutDeviceIntRegion& aRegion, -+ LayoutDeviceIntRegion& aWaylandBufferDamage) { - MOZ_ASSERT(!mDrawToWaylandBufferDirectly); - - LayoutDeviceIntRect screenRect = mWindow->GetBounds(); -@@ -589,30 +755,31 @@ bool WindowSurfaceWayland::CommitImageSu - return false; - } - -- RefPtr dt = LockWaylandBuffer( -- screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear()); - RefPtr surf = - gfx::Factory::CreateSourceSurfaceForCairoSurface( - mImageSurface->CairoSurface(), mImageSurface->GetSize(), - mImageSurface->Format()); -- if (!dt || !surf) { -+ if (!surf) { - return false; - } - -- uint32_t numRects = aRegion.GetNumRects(); -- if (numRects != 1) { -- AutoTArray 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(); -+ bool needsClear = mWindow->WaylandSurfaceNeedsClear(); -+ RefPtr dt = LockWaylandBuffer( -+ screenRect.width, screenRect.height, needsClear, -+ /* fullscreenDrawing */ false, /* aNoBackBufferCopy */ true); -+ if (dt) { -+ if (needsClear) { -+ mWindow->WaylandSurfaceCleared(); -+ } -+ // 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(); -+ } else { -+ mDelayedImageCommits.AppendElement(WindowImageSurface(surf, aRegion)); -+ return false; - } - - return true; -@@ -653,6 +820,24 @@ void WindowSurfaceWayland::CommitWayland - return; - } - -+ if (!mDrawToWaylandBufferDirectly) { -+ // There's some cached drawings - try to flush them now. -+ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); -+ bool needsClear = mWindow->WaylandSurfaceNeedsClear(); -+ RefPtr dt = -+ LockWaylandBuffer(screenRect.width, screenRect.height, needsClear, -+ /* fullscreenInvalidate */ false, -+ /* aNoBackBufferCopy */ true); -+ if (dt) { -+ if (needsClear) { -+ mWindow->WaylandSurfaceCleared(); -+ } -+ DrawDelayedImageCommits(dt, mWaylandBufferDamage); -+ UnlockWaylandBuffer(); -+ mDrawToWaylandBufferDirectly = true; -+ } -+ } ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ * ++ * This request adds one dmabuf to the set in this ++ * zwp_linux_buffer_params_v1. ++ * ++ * The 64-bit unsigned value combined from modifier_hi and modifier_lo ++ * is the dmabuf layout modifier. DRM AddFB2 ioctl calls this the ++ * fb modifier, which is defined in drm_mode.h of Linux UAPI. ++ * This is an opaque token. Drivers use this token to express tiling, ++ * compression, etc. driver-specific modifications to the base format ++ * defined by the DRM fourcc code. ++ * ++ * This request raises the PLANE_IDX error if plane_idx is too large. ++ * The error PLANE_SET is raised if attempting to set a plane that ++ * was already set. ++ */ ++static inline void zwp_linux_buffer_params_v1_add( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, int32_t fd, ++ uint32_t plane_idx, uint32_t offset, uint32_t stride, uint32_t modifier_hi, ++ uint32_t modifier_lo) { ++ wl_proxy_marshal((struct wl_proxy*)zwp_linux_buffer_params_v1, ++ ZWP_LINUX_BUFFER_PARAMS_V1_ADD, fd, plane_idx, offset, ++ stride, modifier_hi, modifier_lo); ++} + - wl_surface* waylandSurface = mWindow->GetWaylandSurface(); - if (!waylandSurface) { - // Target window is not created yet - delay the commit. This can happen only -@@ -745,14 +930,21 @@ void WindowSurfaceWayland::Commit(const - } - #endif - -- // We have new content at mImageSurface - copy data to mWaylandBuffer first. -- if (!mDrawToWaylandBufferDirectly) { -- CommitImageSurfaceToWaylandBuffer(aInvalidRegion); -- } -- -- // If we're not at fullscreen damage add drawing area from aInvalidRegion -- if (!mWaylandBufferFullScreenDamage) { -- mWaylandBufferDamage.OrWith(aInvalidRegion); -+ if (mDrawToWaylandBufferDirectly) { -+ MOZ_ASSERT(mWaylandBuffer->IsLocked()); -+ // If we're not at fullscreen damage add drawing area from aInvalidRegion -+ if (!mWaylandBufferFullScreenDamage) { -+ mWaylandBufferDamage.OrWith(aInvalidRegion); -+ } -+ UnlockWaylandBuffer(); -+ } else { -+ MOZ_ASSERT(!mWaylandBuffer->IsLocked(), -+ "Drawing to already locked buffer?"); -+ if (CommitImageSurfaceToWaylandBuffer(aInvalidRegion, -+ mWaylandBufferDamage)) { -+ // Our cached drawing is flushed, we can draw fullscreen again. -+ mDrawToWaylandBufferDirectly = true; -+ } - } - - // We're ready to commit. -diff -up firefox-67.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1552590 firefox-67.0/widget/gtk/WindowSurfaceWayland.h ---- firefox-67.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1552590 2019-05-27 12:15:32.028414340 +0200 -+++ firefox-67.0/widget/gtk/WindowSurfaceWayland.h 2019-05-27 12:15:32.034414339 +0200 -@@ -10,6 +10,9 @@ - #include - #include "mozilla/gfx/Types.h" - #include "nsWaylandDisplay.h" -+#ifdef HAVE_LIBDRM -+# include "mozilla/gfx/WaylandDMABufSurface.h" -+#endif - - #define BACK_BUFFER_NUM 2 - -@@ -40,12 +43,53 @@ class WaylandShmPool { - // Holds actual graphics data for wl_surface - class WindowBackBuffer { - public: -- WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight); -- ~WindowBackBuffer(); -+ virtual already_AddRefed Lock() = 0; -+ virtual void Unlock(){}; -+ virtual bool IsLocked() { return false; }; ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ * ++ * This asks for creation of a wl_buffer from the added dmabuf ++ * buffers. The wl_buffer is not created immediately but returned via ++ * the 'created' event if the dmabuf sharing succeeds. The sharing ++ * may fail at runtime for reasons a client cannot predict, in ++ * which case the 'failed' event is triggered. ++ * ++ * The 'format' argument is a DRM_FORMAT code, as defined by the ++ * libdrm's drm_fourcc.h. The Linux kernel's DRM sub-system is the ++ * authoritative source on how the format codes should work. ++ * ++ * The 'flags' is a bitfield of the flags defined in enum "flags". ++ * 'y_invert' means the that the image needs to be y-flipped. ++ * ++ * Flag 'interlaced' means that the frame in the buffer is not ++ * progressive as usual, but interlaced. An interlaced buffer as ++ * supported here must always contain both top and bottom fields. ++ * The top field always begins on the first pixel row. The temporal ++ * ordering between the two fields is top field first, unless ++ * 'bottom_first' is specified. It is undefined whether 'bottom_first' ++ * is ignored if 'interlaced' is not set. ++ * ++ * This protocol does not convey any information about field rate, ++ * duration, or timing, other than the relative ordering between the ++ * two fields in one buffer. A compositor may have to estimate the ++ * intended field rate from the incoming buffer rate. It is undefined ++ * whether the time of receiving wl_surface.commit with a new buffer ++ * attached, applying the wl_surface state, wl_surface.frame callback ++ * trigger, presentation, or any other point in the compositor cycle ++ * is used to measure the frame or field times. There is no support ++ * for detecting missed or late frames/fields/buffers either, and ++ * there is no support whatsoever for cooperating with interlaced ++ * compositor output. ++ * ++ * The composited image quality resulting from the use of interlaced ++ * buffers is explicitly undefined. A compositor may use elaborate ++ * hardware features or software to deinterlace and create progressive ++ * output frames from a sequence of interlaced input buffers, or it ++ * may produce substandard image quality. However, compositors that ++ * cannot guarantee reasonable image quality in all cases are recommended ++ * to just reject all interlaced buffers. ++ * ++ * Any argument errors, including non-positive width or height, ++ * mismatch between the number of planes and the format, bad ++ * format, bad offset or stride, may be indicated by fatal protocol ++ * errors: INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, ++ * OUT_OF_BOUNDS. ++ * ++ * Dmabuf import errors in the server that are not obvious client ++ * bugs are returned via the 'failed' event as non-fatal. This ++ * allows attempting dmabuf sharing and falling back in the client ++ * if it fails. ++ * ++ * This request can be sent only once in the object's lifetime, after ++ * which the only legal request is destroy. This object should be ++ * destroyed after issuing a 'create' request. Attempting to use this ++ * object after issuing 'create' raises ALREADY_USED protocol error. ++ * ++ * It is not mandatory to issue 'create'. If a client wants to ++ * cancel the buffer creation, it can just destroy this object. ++ */ ++static inline void zwp_linux_buffer_params_v1_create( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, ++ int32_t width, int32_t height, uint32_t format, uint32_t flags) { ++ wl_proxy_marshal((struct wl_proxy*)zwp_linux_buffer_params_v1, ++ ZWP_LINUX_BUFFER_PARAMS_V1_CREATE, width, height, format, ++ flags); ++} + -+ void Attach(wl_surface* aSurface); -+ virtual void Detach(wl_buffer* aBuffer) = 0; -+ virtual bool IsAttached() = 0; ++/** ++ * @ingroup iface_zwp_linux_buffer_params_v1 ++ * ++ * This asks for immediate creation of a wl_buffer by importing the ++ * added dmabufs. ++ * ++ * In case of import success, no event is sent from the server, and the ++ * wl_buffer is ready to be used by the client. ++ * ++ * Upon import failure, either of the following may happen, as seen fit ++ * by the implementation: ++ * - the client is terminated with one of the following fatal protocol ++ * errors: ++ * - INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, OUT_OF_BOUNDS, ++ * in case of argument errors such as mismatch between the number ++ * of planes and the format, bad format, non-positive width or ++ * height, or bad offset or stride. ++ * - INVALID_WL_BUFFER, in case the cause for failure is unknown or ++ * plaform specific. ++ * - the server creates an invalid wl_buffer, marks it as failed and ++ * sends a 'failed' event to the client. The result of using this ++ * invalid wl_buffer as an argument in any request by the client is ++ * defined by the compositor implementation. ++ * ++ * This takes the same arguments as a 'create' request, and obeys the ++ * same restrictions. ++ */ ++static inline struct wl_buffer* zwp_linux_buffer_params_v1_create_immed( ++ struct zwp_linux_buffer_params_v1* zwp_linux_buffer_params_v1, ++ int32_t width, int32_t height, uint32_t format, uint32_t flags) { ++ struct wl_proxy* buffer_id; + -+ virtual void Clear() = 0; -+ virtual bool Resize(int aWidth, int aHeight) = 0; ++ buffer_id = wl_proxy_marshal_constructor( ++ (struct wl_proxy*)zwp_linux_buffer_params_v1, ++ ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED, &wl_buffer_interface, NULL, ++ width, height, format, flags); + -+ virtual int GetWidth() = 0; -+ virtual int GetHeight() = 0; -+ virtual wl_buffer* GetWlBuffer() = 0; -+ virtual void SetAttached() = 0; ++ return (struct wl_buffer*)buffer_id; ++} + -+ virtual bool SetImageDataFromBuffer( -+ class WindowBackBuffer* aSourceBuffer) = 0; ++#ifdef __cplusplus ++} ++#endif + -+ bool IsMatchingSize(int aWidth, int aHeight) { -+ return aWidth == GetWidth() && aHeight == GetHeight(); -+ } -+ bool IsMatchingSize(class WindowBackBuffer* aBuffer) { -+ return aBuffer->IsMatchingSize(GetWidth(), GetHeight()); -+ } ++#endif +diff --git a/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c b/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c +new file mode 100644 +--- /dev/null ++++ b/widget/gtk/wayland/linux-dmabuf-unstable-v1-protocol.c +@@ -0,0 +1,81 @@ ++/* Generated by wayland-scanner 1.17.0 */ + -+ static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } ++/* ++ * Copyright © 2014, 2015 Collabora, Ltd. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ + -+ nsWaylandDisplay* GetWaylandDisplay() { return mWaylandDisplay; }; ++#include ++#include ++#include "wayland-util.h" + -+ WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay) -+ : mWaylandDisplay(aWaylandDisplay){}; -+ virtual ~WindowBackBuffer(){}; ++#pragma GCC visibility push(default) ++extern const struct wl_interface wl_buffer_interface; ++extern const struct wl_interface zwp_linux_buffer_params_v1_interface; ++#pragma GCC visibility pop + -+ private: -+ static gfx::SurfaceFormat mFormat; -+ nsWaylandDisplay* mWaylandDisplay; ++static const struct wl_interface* types[] = { ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ &zwp_linux_buffer_params_v1_interface, ++ &wl_buffer_interface, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ &wl_buffer_interface, +}; + -+class WindowBackBufferShm : public WindowBackBuffer { -+ public: -+ WindowBackBufferShm(nsWaylandDisplay* aWaylandDisplay, int aWidth, -+ int aHeight); -+ ~WindowBackBufferShm(); - - already_AddRefed Lock(); - -- void Attach(wl_surface* aSurface); - void Detach(wl_buffer* aBuffer); - bool IsAttached() { return mAttached; } - -@@ -53,14 +97,11 @@ class WindowBackBuffer { - bool Resize(int aWidth, int aHeight); - bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); - -- bool IsMatchingSize(int aWidth, int aHeight) { -- return aWidth == mWidth && aHeight == mHeight; -- } -- bool IsMatchingSize(class WindowBackBuffer* aBuffer) { -- return aBuffer->mWidth == mWidth && aBuffer->mHeight == mHeight; -- } -+ int GetWidth() { return mWidth; }; -+ int GetHeight() { return mHeight; }; - -- static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } -+ wl_buffer* GetWlBuffer() { return mWaylandBuffer; }; -+ void SetAttached() { mAttached = true; }; - - private: - void Create(int aWidth, int aHeight); -@@ -75,8 +116,51 @@ class WindowBackBuffer { - int mWidth; - int mHeight; - bool mAttached; -- nsWaylandDisplay* mWaylandDisplay; -- static gfx::SurfaceFormat mFormat; ++static const struct wl_message zwp_linux_dmabuf_v1_requests[] = { ++ {"destroy", "", types + 0}, ++ {"create_params", "n", types + 6}, +}; + -+#ifdef HAVE_LIBDRM -+class WindowBackBufferDMABuf : public WindowBackBuffer { -+ public: -+ WindowBackBufferDMABuf(nsWaylandDisplay* aWaylandDisplay, int aWidth, -+ int aHeight); -+ ~WindowBackBufferDMABuf(); -+ -+ bool IsAttached(); -+ void SetAttached(); -+ -+ int GetWidth(); -+ int GetHeight(); -+ wl_buffer* GetWlBuffer(); -+ -+ bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); -+ -+ already_AddRefed Lock(); -+ bool IsLocked(); -+ void Unlock(); -+ -+ void Clear(); -+ void Detach(wl_buffer* aBuffer); -+ bool Resize(int aWidth, int aHeight); -+ -+ private: -+ WaylandDMABufSurface mDMAbufSurface; ++static const struct wl_message zwp_linux_dmabuf_v1_events[] = { ++ {"format", "u", types + 0}, ++ {"modifier", "3uuu", types + 0}, +}; -+#endif + -+class WindowImageSurface { -+ public: -+ static void Draw(gfx::SourceSurface* aSurface, gfx::DrawTarget* aDest, -+ const LayoutDeviceIntRegion& aRegion); ++const struct wl_interface zwp_linux_dmabuf_v1_interface = { ++ "zwp_linux_dmabuf_v1", 3, 2, ++ zwp_linux_dmabuf_v1_requests, 2, zwp_linux_dmabuf_v1_events, ++}; + -+ void Draw(gfx::DrawTarget* aDest, -+ LayoutDeviceIntRegion& aWaylandBufferDamage); ++static const struct wl_message zwp_linux_buffer_params_v1_requests[] = { ++ {"destroy", "", types + 0}, ++ {"add", "huuuuu", types + 0}, ++ {"create", "iiuu", types + 0}, ++ {"create_immed", "2niiuu", types + 7}, ++}; + -+ WindowImageSurface(gfx::SourceSurface* aSurface, -+ const LayoutDeviceIntRegion& aUpdateRegion); ++static const struct wl_message zwp_linux_buffer_params_v1_events[] = { ++ {"created", "n", types + 12}, ++ {"failed", "", types + 0}, ++}; + -+ private: -+ RefPtr mSurface; -+ const LayoutDeviceIntRegion mUpdateRegion; - }; - - // WindowSurfaceWayland is an abstraction for wl_surface -@@ -93,33 +177,50 @@ class WindowSurfaceWayland : public Wind - void DelayedCommitHandler(); ++const struct wl_interface zwp_linux_buffer_params_v1_interface = { ++ "zwp_linux_buffer_params_v1", 3, 4, ++ zwp_linux_buffer_params_v1_requests, 2, zwp_linux_buffer_params_v1_events, ++}; +diff --git a/widget/gtk/wayland/moz.build b/widget/gtk/wayland/moz.build +--- a/widget/gtk/wayland/moz.build ++++ b/widget/gtk/wayland/moz.build +@@ -4,16 +4,22 @@ + # 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/. - private: -- WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight); -+ WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight); -+ WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight, -+ bool aFullScreenUpdate, -+ bool aNoBackBufferCopy); + with Files("**"): + BUG_COMPONENT = ("Core", "Widget: Gtk") - already_AddRefed LockWaylandBuffer(int aWidth, int aHeight, -- bool aClearBuffer); -+ bool aClearBuffer, -+ bool aFullScreenUpdate, -+ bool aNoBackBufferCopy); -+ void UnlockWaylandBuffer(); + SOURCES += [ + 'gtk-primary-selection-protocol.c', ++ 'linux-dmabuf-unstable-v1-protocol.c' ++] + - already_AddRefed LockImageSurface( - const gfx::IntSize& aLockSize); -- bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); -+ bool CommitImageSurfaceToWaylandBuffer( -+ const LayoutDeviceIntRegion& aRegion, -+ LayoutDeviceIntRegion& aWaylandBufferDamage); - void CommitWaylandBuffer(); - void CalcRectScale(LayoutDeviceIntRect& aRect, int scale); ++EXPORTS.mozilla.widget += [ ++ 'gtk-primary-selection-client-protocol.h', ++ 'linux-dmabuf-unstable-v1-client-protocol.h', + ] -+ void DrawDelayedImageCommits(gfx::DrawTarget* aDrawTarget, -+ LayoutDeviceIntRegion& aWaylandBufferDamage); -+ - // TODO: Do we need to hold a reference to nsWindow object? - nsWindow* mWindow; - nsWaylandDisplay* mWaylandDisplay; - WindowBackBuffer* mWaylandBuffer; - LayoutDeviceIntRegion mWaylandBufferDamage; - WindowBackBuffer* mBackupBuffer[BACK_BUFFER_NUM]; -- RefPtr mImageSurface; - wl_callback* mFrameCallback; - wl_surface* mLastCommittedSurface; - MessageLoop* mDisplayThreadMessageLoop; - WindowSurfaceWayland** mDelayedCommitHandle; -+ RefPtr mImageSurface; -+ AutoTArray mDelayedImageCommits; - bool mDrawToWaylandBufferDirectly; - bool mPendingCommit; - bool mWaylandBufferFullScreenDamage; - bool mIsMainThread; - bool mNeedScaleFactorUpdate; - bool mWaitToFullScreenUpdate; -+ -+ static bool UseDMABufBackend(); -+ static bool mUseDMABufInitialized; -+ static bool mUseDMABuf; - }; + include('/ipc/chromium/chromium-config.mozbuild') - } // namespace widget + FINAL_LIBRARY = 'xul' + + CFLAGS += CONFIG['TK_CFLAGS'] + CXXFLAGS += CONFIG['TK_CFLAGS'] + -- cgit