From ecd684cf2179cefa1a9c86e5ecdd2d8dec361809 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 27 May 2019 14:19:43 +0200 Subject: Added mozbz#1552590 --- firefox.spec | 9 +- mozilla-1552590.patch | 2507 +++++++++++++++++++++++++++++++++++++++++++++++++ mozilla-1553747.patch | 73 -- 3 files changed, 2513 insertions(+), 76 deletions(-) create mode 100644 mozilla-1552590.patch delete mode 100644 mozilla-1553747.patch diff --git a/firefox.spec b/firefox.spec index 7994cd2..eb2c5c0 100644 --- a/firefox.spec +++ b/firefox.spec @@ -99,7 +99,7 @@ ExcludeArch: s390x Summary: Mozilla Firefox Web browser Name: firefox Version: 67.0 -Release: 4%{?pre_tag}%{?dist} +Release: 5%{?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,7 +163,7 @@ Patch579: mozilla-1468911.patch Patch580: mozilla-1539471.patch Patch581: mozilla-1517205.patch Patch582: mozilla-1508378.patch -Patch583: mozilla-1553747.patch +Patch584: mozilla-1552590.patch # PGO/LTO patches Patch600: pgo.patch @@ -378,7 +378,7 @@ This package contains results of tests executed during build. %patch580 -p1 -b .mozilla-1539471 %patch581 -p1 -b .mozilla-1517205 %patch582 -p1 -b .mozilla-1508378 -%patch583 -p1 -b .mozilla-1553747 +%patch584 -p1 -b .mozilla-1552590 # PGO patches %patch600 -p1 -b .pgo @@ -936,6 +936,9 @@ 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-1552590.patch b/mozilla-1552590.patch new file mode 100644 index 0000000..4726c20 --- /dev/null +++ b/mozilla-1552590.patch @@ -0,0 +1,2507 @@ +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 +@@ -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: */ ++/* 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/. */ ++ ++// Based on weston/simple-dmabuf-egl.c ++ ++#include "WaylandDMABufSurface.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++using namespace mozilla; ++using namespace mozilla::widget; ++ ++#ifndef DRM_FORMAT_MOD_INVALID ++# define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) ++#endif ++#define BUFFER_FLAGS 0 ++ ++bool WaylandDMABufSurface::mAvailable = false; ++bool WaylandDMABufSurface::mInitialized = false; ++ ++bool WaylandDMABufSurface::IsAvailable() { ++ if (!mInitialized) { ++ mInitialized = true; ++ if (!nsGbmLib::IsAvailable()) { ++ return false; ++ } ++ ++ // Test Alpha and non-alpha formats ++ nsWaylandDisplay* display = WaylandDisplayGet(); ++ if (!display->GetGbmFormat(false) || !display->GetGbmFormat(true)) { ++ return false; ++ } ++ mAvailable = true; ++ } ++ return static_cast(mAvailable); ++} ++ ++static void buffer_release(void* data, wl_buffer* buffer) { ++ auto surface = reinterpret_cast(data); ++ surface->WLBufferDetach(); ++} ++ ++static const struct wl_buffer_listener buffer_listener = {buffer_release}; ++ ++static void buffer_created(void* data, ++ struct zwp_linux_buffer_params_v1* params, ++ struct wl_buffer* new_buffer) { ++ auto surface = static_cast(data); ++ ++ surface->SetWLBuffer(new_buffer); ++ ++ nsWaylandDisplay* display = WaylandDisplayGet(); ++ /* When not using explicit synchronization listen to wl_buffer.release ++ * for release notifications, otherwise we are going to use ++ * zwp_linux_buffer_release_v1. */ ++ if (!display->IsExplicitSyncEnabled()) { ++ wl_buffer_add_listener(new_buffer, &buffer_listener, surface); ++ } ++ zwp_linux_buffer_params_v1_destroy(params); ++} ++ ++static void buffer_create_failed(void* data, ++ struct zwp_linux_buffer_params_v1* params) { ++ zwp_linux_buffer_params_v1_destroy(params); ++} ++ ++static const struct zwp_linux_buffer_params_v1_listener params_listener = { ++ buffer_created, buffer_create_failed}; ++ ++WaylandDMABufSurface::WaylandDMABufSurface() ++ : mWidth(0), ++ mHeight(0), ++ mGmbFormat(nullptr), ++ mWLBuffer(nullptr), ++ mMappedRegion(nullptr), ++ mGbmBufferObject(nullptr), ++ mBufferModifier(DRM_FORMAT_MOD_INVALID), ++ mBufferPlaneCount(1), ++ mWLBufferAttached(false), ++ mFastWLBufferCreation(true) { ++ for (int i = 0; i < DMABUF_BUFFER_PLANES; i++) { ++ mDmabufFds[i] = -1; ++ mStrides[i] = 0; ++ mOffsets[i] = 0; ++ } ++} ++ ++WaylandDMABufSurface::~WaylandDMABufSurface() { Release(); } ++ ++bool WaylandDMABufSurface::Create(int aWidth, int aHeight, bool aHasAlpha) { ++ MOZ_ASSERT(mWLBuffer == nullptr); ++ ++ mWidth = aWidth; ++ mHeight = aHeight; ++ ++ nsWaylandDisplay* display = WaylandDisplayGet(); ++ mGmbFormat = display->GetGbmFormat(aHasAlpha); ++ if (!mGmbFormat) { ++ // Requested DRM format is not supposed. ++ return false; ++ } ++ ++#ifdef HAVE_GBM_MODIFIERS ++ if (nsGbmLib::IsModifierAvailable() && mGmbFormat->mModifiersCount > 0) { ++ mGbmBufferObject = nsGbmLib::CreateWithModifiers( ++ display->GetGbmDevice(), mWidth, mHeight, mGmbFormat->mFormat, ++ mGmbFormat->mModifiers, mGmbFormat->mModifiersCount); ++ if (mGbmBufferObject) { ++ mBufferModifier = nsGbmLib::GetModifier(mGbmBufferObject); ++ } ++ } ++#endif ++ ++ if (!mGbmBufferObject) { ++ mGbmBufferObject = ++ nsGbmLib::Create(display->GetGbmDevice(), mWidth, mHeight, ++ mGmbFormat->mFormat, GBM_BO_USE_RENDERING); ++ } ++ ++ if (!mGbmBufferObject) { ++ return false; ++ } ++ ++#ifdef HAVE_GBM_MODIFIERS ++ if (nsGbmLib::IsModifierAvailable()) { ++ mBufferPlaneCount = nsGbmLib::GetPlaneCount(mGbmBufferObject); ++ for (int i = 0; i < mBufferPlaneCount; i++) { ++ uint32_t handle = nsGbmLib::GetHandleForPlane(mGbmBufferObject, i).u32; ++ int ret = nsGbmLib::DrmPrimeHandleToFD(display->GetGbmDeviceFd(), handle, ++ 0, &mDmabufFds[i]); ++ if (ret < 0 || mDmabufFds[i] < 0) { ++ Release(); ++ return false; ++ } ++ mStrides[i] = nsGbmLib::GetStrideForPlane(mGbmBufferObject, i); ++ mOffsets[i] = nsGbmLib::GetOffset(mGbmBufferObject, i); ++ } ++ } else ++#endif ++ { ++ mBufferPlaneCount = 1; ++ mStrides[0] = nsGbmLib::GetStride(mGbmBufferObject); ++ mDmabufFds[0] = nsGbmLib::GetFd(mGbmBufferObject); ++ if (mDmabufFds[0] < 0) { ++ Release(); ++ return false; ++ } ++ } ++ ++ struct zwp_linux_buffer_params_v1* params = ++ zwp_linux_dmabuf_v1_create_params(display->GetDmabuf()); ++ for (int i = 0; i < mBufferPlaneCount; i++) { ++ zwp_linux_buffer_params_v1_add(params, mDmabufFds[i], i, mOffsets[i], ++ mStrides[i], mBufferModifier >> 32, ++ mBufferModifier & 0xffffffff); ++ } ++ zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, this); ++ ++ if (mFastWLBufferCreation) { ++ mWLBuffer = zwp_linux_buffer_params_v1_create_immed( ++ params, mWidth, mHeight, mGmbFormat->mFormat, BUFFER_FLAGS); ++ /* When not using explicit synchronization listen to ++ * wl_buffer.release for release notifications, otherwise we ++ * are going to use zwp_linux_buffer_release_v1. */ ++ if (!display->IsExplicitSyncEnabled()) { ++ wl_buffer_add_listener(mWLBuffer, &buffer_listener, this); ++ } ++ } else { ++ zwp_linux_buffer_params_v1_create(params, mWidth, mHeight, ++ mGmbFormat->mFormat, BUFFER_FLAGS); ++ } ++ ++ return true; ++} ++ ++void WaylandDMABufSurface::Release() { ++ MOZ_ASSERT(!IsMapped(), "We can't release mapped buffer!"); ++ ++ if (mWLBuffer) { ++ wl_buffer_destroy(mWLBuffer); ++ mWLBuffer = nullptr; ++ } ++ ++ if (mGbmBufferObject) { ++ nsGbmLib::Destroy(mGbmBufferObject); ++ mGbmBufferObject = nullptr; ++ } ++ ++ for (int i = 0; i < mBufferPlaneCount; i++) { ++ if (mDmabufFds[i] >= 0) { ++ close(mDmabufFds[i]); ++ mDmabufFds[i] = 0; ++ } ++ } ++} ++ ++void* WaylandDMABufSurface::MapReadOnly(uint32_t aX, uint32_t aY, ++ uint32_t aWidth, uint32_t aHeight, ++ uint32_t* aStride) { ++ NS_ASSERTION(mMappedRegion == nullptr, "Already mapped?"); ++ void* map_data = nullptr; ++ *aStride = 0; ++ mMappedRegion = nsGbmLib::Map(mGbmBufferObject, aX, aY, aWidth, aHeight, ++ GBM_BO_TRANSFER_READ, aStride, &map_data); ++ return mMappedRegion; ++} ++ ++void* WaylandDMABufSurface::MapReadOnly(uint32_t* aStride) { ++ return MapReadOnly(0, 0, mWidth, mHeight, aStride); ++} ++ ++void* WaylandDMABufSurface::Map(uint32_t aX, uint32_t aY, uint32_t aWidth, ++ uint32_t aHeight, uint32_t* aStride) { ++ NS_ASSERTION(mMappedRegion == nullptr, "Already mapped?"); ++ void* map_data = nullptr; ++ *aStride = 0; ++ mMappedRegion = nsGbmLib::Map(mGbmBufferObject, aX, aY, aWidth, aHeight, ++ GBM_BO_TRANSFER_READ_WRITE, aStride, &map_data); ++ return mMappedRegion; ++} ++ ++void* WaylandDMABufSurface::Map(uint32_t* aStride) { ++ return Map(0, 0, mWidth, mHeight, aStride); ++} ++ ++void WaylandDMABufSurface::Unmap() { ++ if (mMappedRegion) { ++ nsGbmLib::Unmap(mGbmBufferObject, mMappedRegion); ++ mMappedRegion = nullptr; ++ } ++} ++ ++bool WaylandDMABufSurface::Resize(int aWidth, int aHeight) { ++ if (aWidth == mWidth && aHeight == mHeight) { ++ return true; ++ } ++ ++ if (IsMapped()) { ++ NS_WARNING("We can't resize mapped surface!"); ++ return false; ++ } ++ ++ Release(); ++ return Create(aWidth, aHeight, mGmbFormat->mHasAlpha); ++} ++ ++bool WaylandDMABufSurface::CopyFrom( ++ class WaylandDMABufSurface* aSourceSurface) { ++ // Not implemented - we should not call that. ++ MOZ_CRASH(); ++} ++ ++// TODO - EGL clear ++void WaylandDMABufSurface::Clear() { ++ uint32_t destStride; ++ void* destData = Map(&destStride); ++ 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 +@@ -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: */ ++/* 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 WaylandDMABufSurface_h__ ++#define WaylandDMABufSurface_h__ ++ ++#include ++#include "mozilla/widget/nsWaylandDisplay.h" ++ ++#define DMABUF_BUFFER_PLANES 4 ++ ++class WaylandDMABufSurface { ++ public: ++ static bool IsAvailable(); ++ ++ bool CreateFrameBuffer(int aWidth, int aHeight); ++ bool CreateEGLImage(int aWidth, int aHeight); ++ ++ bool Create(int aWidth, int aHeight, bool aHasAlpha = true); ++ bool Resize(int aWidth, int aHeight); ++ void Release(); ++ void Clear(); ++ ++ bool CopyFrom(class WaylandDMABufSurface* aSourceSurface); ++ ++ int GetWidth() { return mWidth; }; ++ int GetHeight() { return mHeight; }; ++ ++ void* MapReadOnly(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight, ++ uint32_t* aStride); ++ void* MapReadOnly(uint32_t* aStride); ++ void* Map(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight, ++ uint32_t* aStride); ++ void* Map(uint32_t* aStride); ++ bool IsMapped() { return mMappedRegion; }; ++ void Unmap(); ++ ++ void SetWLBuffer(struct wl_buffer* aWLBuffer) { mWLBuffer = aWLBuffer; }; ++ wl_buffer* GetWLBuffer() { return mWLBuffer; }; ++ ++ void WLBufferDetach() { mWLBufferAttached = false; }; ++ bool WLBufferIsAttached() { return mWLBufferAttached; }; ++ void WLBufferSetAttached() { mWLBufferAttached = true; }; ++ ++ WaylandDMABufSurface(); ++ ~WaylandDMABufSurface(); ++ ++ private: ++ int mWidth; ++ int mHeight; ++ mozilla::widget::GbmFormat* mGmbFormat; ++ ++ wl_buffer* mWLBuffer; ++ void* mMappedRegion; ++ ++ struct gbm_bo* mGbmBufferObject; ++ uint64_t mBufferModifier; ++ int mBufferPlaneCount; ++ int mDmabufFds[DMABUF_BUFFER_PLANES]; ++ uint32_t mStrides[DMABUF_BUFFER_PLANES]; ++ uint32_t mOffsets[DMABUF_BUFFER_PLANES]; ++ ++ bool mWLBufferAttached; ++ bool mFastWLBufferCreation; ++ ++ static bool mAvailable; ++ static bool mInitialized; ++}; ++ ++#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 + pref("widget.content.allow-gtk-dark-theme", false); + #endif + #endif ++#ifdef MOZ_WAYLAND ++#ifdef HAVE_LIBDRM ++pref("gfx.wayland_dmabuf_backend.enabled", false); ++#endif ++#endif + + 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 + set_config('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True)) + set_define('MOZ_WAYLAND', depends_if(wayland_headers)(lambda _: True)) + ++drm_headers = pkg_check_modules('HAVE_LIBDRM', 'libdrm > 2.4', when=wayland_headers) ++set_config('HAVE_LIBDRM', depends_if(drm_headers)(lambda _: True)) ++set_define('HAVE_LIBDRM', depends_if(drm_headers)(lambda _: True)) ++ ++gbm_modifiers = pkg_check_modules('HAVE_GBM_MODIFIERS', 'gbm >= 17.1', when=drm_headers) ++set_config('HAVE_GBM_MODIFIERS', depends_if(gbm_modifiers)(lambda _: True)) ++set_define('HAVE_GBM_MODIFIERS', depends_if(gbm_modifiers)(lambda _: True)) ++ + # 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()); + } + + return container->surface; +@@ -596,9 +596,13 @@ gboolean moz_container_has_wl_egl_window + + 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; ++} ++ + #endif + + 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_ + + 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', ++] + + SharedLibrary('mozwayland') + + 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 @@ + + #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 { + +@@ -58,7 +54,7 @@ static nsWaylandDisplay *WaylandDisplayG + return nullptr; + } + +-nsWaylandDisplay *WaylandDisplayGet(GdkDisplay *aGdkDisplay) { ++nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay) { + if (!aGdkDisplay) { + aGdkDisplay = gdk_display_get_default(); + } +@@ -90,84 +86,193 @@ static void WaylandDisplayLoopLocked(wl_ + + 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::SetShm(wl_shm* aShm) { mShm = aShm; } + +-void nsWaylandDisplay::SetSubcompositor(wl_subcompositor *aSubcompositor) { ++void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) { + mSubcompositor = aSubcompositor; + } + + void nsWaylandDisplay::SetDataDeviceManager( +- wl_data_device_manager *aDataDeviceManager) { ++ wl_data_device_manager* aDataDeviceManager) { + mDataDeviceManager = aDataDeviceManager; + } + +-void nsWaylandDisplay::SetSeat(wl_seat *aSeat) { mSeat = aSeat; } ++void nsWaylandDisplay::SetSeat(wl_seat* aSeat) { mSeat = aSeat; } + + void nsWaylandDisplay::SetPrimarySelectionDeviceManager( +- gtk_primary_selection_device_manager *aPrimarySelectionDeviceManager) { ++ gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager) { + mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager; + } + +-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; ++} ++ ++GbmFormat* nsWaylandDisplay::GetGbmFormat(bool aHasAlpha) { ++ GbmFormat* format = aHasAlpha ? &mARGBFormat : &mXRGBFormat; ++ return format->mIsSupported ? format : nullptr; ++} ++ ++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; ++} ++ ++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; ++ } ++} ++ ++static void dmabuf_format(void* data, ++ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf, ++ uint32_t format) { ++ // XXX: deprecated ++} ++ ++static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { ++ dmabuf_format, dmabuf_modifiers}; ++#endif ++ ++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; + + 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; ++ } ++ ++ // TODO ++ const char* drm_render_node = getenv("MOZ_WAYLAND_DRM_DEVICE"); ++ if (!drm_render_node) { ++ drm_render_node = "/dev/dri/renderD128"; ++ } ++ ++ 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; ++ } ++ ++ 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; ++ } ++ ++ return true; ++} ++ ++gbm_device* nsWaylandDisplay::GetGbmDevice() { ++ if (!mGdmConfigured) { ++ ConfigureGbm(); ++ mGdmConfigured = true; ++ } ++ return mGbmDevice; ++} ++ ++int nsWaylandDisplay::GetGbmDeviceFd() { ++ if (!mGdmConfigured) { ++ ConfigureGbm(); ++ mGdmConfigured = true; ++ } ++ return mGbmFd; ++} ++#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}) ++#endif ++{ + mRegistry = wl_display_get_registry(mDisplay); + wl_registry_add_listener(mRegistry, ®istry_listener, this); + +@@ -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() { + } + } + ++#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; ++ } ++ 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 -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/. */ + +-#ifndef __MOZ_WAYLAND_REGISTRY_H__ +-#define __MOZ_WAYLAND_REGISTRY_H__ ++#ifndef __MOZ_WAYLAND_DISPLAY_H__ ++#define __MOZ_WAYLAND_DISPLAY_H__ + +-#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" + +-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 + + // TODO: Bug 1467125 - We need to integrate wl_display_dispatch_queue_pending() + // with compositor event loop. + #define EVENT_LOOP_DELAY (1000 / 240) + ++namespace mozilla { ++namespace widget { ++ ++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 { +@@ -26,6 +45,7 @@ class nsWaylandDisplay { + virtual ~nsWaylandDisplay(); + + bool DisplayLoop(); ++ bool DispatchEventQueue(); + bool Matches(wl_display* aDisplay); + + wl_display* GetDisplay() { return mDisplay; }; +@@ -47,7 +67,22 @@ class nsWaylandDisplay { + void SetPrimarySelectionDeviceManager( + gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager); + +-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 ++ ++ private: ++#ifdef HAVE_LIBDRM ++ bool ConfigureGbm(); ++#endif ++ + 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 + }; + ++void WaylandDispatchDisplays(); + nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr); + ++#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 + +-#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)); + } +- +- 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 + + #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(); + #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 */ ++ ++#ifndef LINUX_DMABUF_UNSTABLE_V1_CLIENT_PROTOCOL_H ++#define LINUX_DMABUF_UNSTABLE_V1_CLIENT_PROTOCOL_H ++ ++#include ++#include ++#include "wayland-client.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @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; ++ ++/** ++ * @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); ++}; ++ ++/** ++ * @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); ++} ++ ++#define ZWP_LINUX_DMABUF_V1_DESTROY 0 ++#define ZWP_LINUX_DMABUF_V1_CREATE_PARAMS 1 ++ ++/** ++ * @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 ++ ++/** ++ * @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); ++} ++ ++/** @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); ++} ++ ++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); ++} ++ ++/** ++ * @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); ++ ++ return (struct zwp_linux_buffer_params_v1*)params_id; ++} ++ ++#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 */ ++ ++/** ++ * @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); ++}; ++ ++/** ++ * @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 ++ ++/** ++ * @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 ++ ++/** ++ * @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 ++ ++/** @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); ++} ++ ++/** @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); ++} ++ ++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); ++} ++ ++/** ++ * @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); ++} ++ ++/** ++ * @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); ++} ++ ++/** ++ * @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); ++} ++ ++/** ++ * @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; ++ ++ 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); ++ ++ return (struct wl_buffer*)buffer_id; ++} ++ ++#ifdef __cplusplus ++} ++#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 */ ++ ++/* ++ * 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. ++ */ ++ ++#include ++#include ++#include "wayland-util.h" ++ ++#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 ++ ++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, ++}; ++ ++static const struct wl_message zwp_linux_dmabuf_v1_requests[] = { ++ {"destroy", "", types + 0}, ++ {"create_params", "n", types + 6}, ++}; ++ ++static const struct wl_message zwp_linux_dmabuf_v1_events[] = { ++ {"format", "u", types + 0}, ++ {"modifier", "3uuu", types + 0}, ++}; ++ ++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, ++}; ++ ++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}, ++}; ++ ++static const struct wl_message zwp_linux_buffer_params_v1_events[] = { ++ {"created", "n", types + 12}, ++ {"failed", "", types + 0}, ++}; ++ ++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("**"): + + SOURCES += [ + 'gtk-primary-selection-protocol.c', ++ 'linux-dmabuf-unstable-v1-protocol.c' ++] ++ ++EXPORTS.mozilla.widget += [ ++ 'gtk-primary-selection-client-protocol.h', ++ 'linux-dmabuf-unstable-v1-client-protocol.h', + ] + + 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."); + + 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); + + mWidth = aWidth; +@@ -280,31 +283,31 @@ void WindowBackBuffer::Create(int aWidth + mWaylandBuffer ? wl_proxy_get_id((struct wl_proxy*)mWaylandBuffer) : -1)); + } + +-void WindowBackBuffer::Release() { ++void WindowBackBufferShm::Release() { + LOGWAYLAND(("%s [%p]\n", __PRETTY_FUNCTION__, (void*)this)); + + 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( +@@ -317,20 +320,20 @@ bool WindowBackBuffer::Resize(int aWidth + } + + 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(); + } + +-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; + } + +-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()); ++} ++ ++#ifdef HAVE_LIBDRM ++WindowBackBufferDMABuf::WindowBackBufferDMABuf( ++ nsWaylandDisplay* aWaylandDisplay, int aWidth, int aHeight) ++ : WindowBackBuffer(aWaylandDisplay) { ++ mDMAbufSurface.Create(aWidth, aHeight); + } + ++WindowBackBufferDMABuf::~WindowBackBufferDMABuf() { mDMAbufSurface.Release(); } ++ ++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)); ++ ++ uint32_t stride; ++ void* pixels = mDMAbufSurface.Map(&stride); ++ gfx::IntSize lockSize(GetWidth(), GetHeight()); ++ return gfxPlatform::CreateDrawTargetForData( ++ static_cast(pixels), lockSize, stride, ++ GetSurfaceFormat()); ++} ++ ++void WindowBackBufferDMABuf::Unlock() { mDMAbufSurface.Unmap(); } ++ ++bool WindowBackBufferDMABuf::IsAttached() { ++ return mDMAbufSurface.WLBufferIsAttached(); ++} ++ ++void WindowBackBufferDMABuf::SetAttached() { ++ return mDMAbufSurface.WLBufferSetAttached(); ++} ++ ++int WindowBackBufferDMABuf::GetWidth() { return mDMAbufSurface.GetWidth(); } ++ ++int WindowBackBufferDMABuf::GetHeight() { return mDMAbufSurface.GetHeight(); } ++ ++wl_buffer* WindowBackBufferDMABuf::GetWlBuffer() { ++ return mDMAbufSurface.GetWLBuffer(); ++} ++ ++bool WindowBackBufferDMABuf::IsLocked() { return mDMAbufSurface.IsMapped(); } ++ ++bool WindowBackBufferDMABuf::Resize(int aWidth, int aHeight) { ++ return mDMAbufSurface.Resize(aWidth, aHeight); ++} ++ ++bool WindowBackBufferDMABuf::SetImageDataFromBuffer( ++ class WindowBackBuffer* aSourceBuffer) { ++ WindowBackBufferDMABuf* source = ++ static_cast(aSourceBuffer); ++ mDMAbufSurface.CopyFrom(&source->mDMAbufSurface); ++ return true; ++} ++ ++void WindowBackBufferDMABuf::Detach(wl_buffer* aBuffer) { ++ mDMAbufSurface.WLBufferDetach(); ++} ++ ++void WindowBackBufferDMABuf::Clear() { mDMAbufSurface.Clear(); } ++#endif ++ + 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; ++} ++ ++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); ++} ++ ++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(); } ++ + 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(); ++ ++ 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()); ++ } ++ ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ gfx::Rect rect(bounds); ++ aDest->DrawSurface(aSurface, rect, rect); ++ ++ if (numRects != 1) { ++ aDest->PopClip(); ++ } ++} ++ ++void WindowImageSurface::Draw(gfx::DrawTarget* aDest, ++ LayoutDeviceIntRegion& aWaylandBufferDamage) { ++ Draw(mSurface.get(), aDest, mUpdateRegion); ++ aWaylandBufferDamage.OrWith(mUpdateRegion); ++} ++ ++WindowImageSurface::WindowImageSurface( ++ gfx::SourceSurface* aSurface, const LayoutDeviceIntRegion& aUpdateRegion) ++ : mSurface(aSurface), mUpdateRegion(aUpdateRegion){}; ++ ++void WindowSurfaceWayland::DrawDelayedImageCommits( ++ gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aWaylandBufferDamage) { ++ for (unsigned int i = 0; i < mDelayedImageCommits.Length(); i++) { ++ mDelayedImageCommits[i].Draw(aDrawTarget, aWaylandBufferDamage); ++ } ++ mDelayedImageCommits.Clear(); ++} ++ + 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; ++ } ++ } ++ + 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; }; ++ ++ void Attach(wl_surface* aSurface); ++ virtual void Detach(wl_buffer* aBuffer) = 0; ++ virtual bool IsAttached() = 0; ++ ++ virtual void Clear() = 0; ++ virtual bool Resize(int aWidth, int aHeight) = 0; ++ ++ virtual int GetWidth() = 0; ++ virtual int GetHeight() = 0; ++ virtual wl_buffer* GetWlBuffer() = 0; ++ virtual void SetAttached() = 0; ++ ++ virtual bool SetImageDataFromBuffer( ++ class WindowBackBuffer* aSourceBuffer) = 0; ++ ++ bool IsMatchingSize(int aWidth, int aHeight) { ++ return aWidth == GetWidth() && aHeight == GetHeight(); ++ } ++ bool IsMatchingSize(class WindowBackBuffer* aBuffer) { ++ return aBuffer->IsMatchingSize(GetWidth(), GetHeight()); ++ } ++ ++ static gfx::SurfaceFormat GetSurfaceFormat() { return mFormat; } ++ ++ nsWaylandDisplay* GetWaylandDisplay() { return mWaylandDisplay; }; ++ ++ WindowBackBuffer(nsWaylandDisplay* aWaylandDisplay) ++ : mWaylandDisplay(aWaylandDisplay){}; ++ virtual ~WindowBackBuffer(){}; ++ ++ private: ++ static gfx::SurfaceFormat mFormat; ++ nsWaylandDisplay* mWaylandDisplay; ++}; ++ ++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; ++}; ++ ++#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; ++}; ++#endif ++ ++class WindowImageSurface { ++ public: ++ static void Draw(gfx::SourceSurface* aSurface, gfx::DrawTarget* aDest, ++ const LayoutDeviceIntRegion& aRegion); ++ ++ void Draw(gfx::DrawTarget* aDest, ++ LayoutDeviceIntRegion& aWaylandBufferDamage); ++ ++ WindowImageSurface(gfx::SourceSurface* aSurface, ++ const LayoutDeviceIntRegion& aUpdateRegion); ++ ++ private: ++ RefPtr mSurface; ++ const LayoutDeviceIntRegion mUpdateRegion; + }; + + // WindowSurfaceWayland is an abstraction for wl_surface +@@ -93,33 +177,50 @@ class WindowSurfaceWayland : public Wind + 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(); ++ + 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); ++ + // 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; + }; + + } // namespace widget diff --git a/mozilla-1553747.patch b/mozilla-1553747.patch deleted file mode 100644 index cb6c1a6..0000000 --- a/mozilla-1553747.patch +++ /dev/null @@ -1,73 +0,0 @@ -diff -up firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1553747 firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp ---- firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp.mozilla-1553747 2019-05-23 13:17:03.169677512 +0200 -+++ firefox-67.0/widget/gtk/WindowSurfaceWayland.cpp 2019-05-23 13:17:03.172677504 +0200 -@@ -416,7 +416,7 @@ WindowSurfaceWayland::~WindowSurfaceWayl - } - - WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(int aWidth, -- int aHeight) { -+ int aHeight, bool aFullScreenUpdate) { - if (!mWaylandBuffer) { - LOGWAYLAND(("%s [%p] Create [%d x %d]\n", __PRETTY_FUNCTION__, (void*)this, - aWidth, aHeight)); -@@ -473,8 +473,10 @@ WindowBackBuffer* WindowSurfaceWayland:: - (void*)this, aWidth, aHeight)); - // 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) { -+ mWaylandBuffer->SetImageDataFromBuffer(lastWaylandBuffer); -+ } - // When buffer switches we need to damage whole screen - // (https://bugzilla.redhat.com/show_bug.cgi?id=1418260) - mWaylandBufferFullScreenDamage = true; -@@ -491,8 +493,9 @@ 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) { -+ WindowBackBuffer* buffer = GetWaylandBufferToDraw(aWidth, aHeight, -+ aFullScreenUpdate); - if (!buffer) { - NS_WARNING( - "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available"); -@@ -557,7 +560,7 @@ already_AddRefed Window - if (mDrawToWaylandBufferDirectly) { - RefPtr dt = - LockWaylandBuffer(screenRect.width, screenRect.height, -- mWindow->WaylandSurfaceNeedsClear()); -+ mWindow->WaylandSurfaceNeedsClear(), true); - if (dt) { - // When we have a request to update whole screen at once - // (surface was created, resized or changed somehow) -@@ -590,7 +593,8 @@ bool WindowSurfaceWayland::CommitImageSu - } - - RefPtr dt = LockWaylandBuffer( -- screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear()); -+ screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear(), -+ false); - RefPtr surf = - gfx::Factory::CreateSourceSurfaceForCairoSurface( - mImageSurface->CairoSurface(), mImageSurface->GetSize(), -diff -up firefox-67.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1553747 firefox-67.0/widget/gtk/WindowSurfaceWayland.h ---- firefox-67.0/widget/gtk/WindowSurfaceWayland.h.mozilla-1553747 2019-05-23 13:17:03.169677512 +0200 -+++ firefox-67.0/widget/gtk/WindowSurfaceWayland.h 2019-05-23 14:21:16.002920509 +0200 -@@ -93,10 +93,11 @@ class WindowSurfaceWayland : public Wind - void DelayedCommitHandler(); - - private: -- WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight); -+ WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight, -+ bool aFullScreenUpdate); - - already_AddRefed LockWaylandBuffer(int aWidth, int aHeight, -- bool aClearBuffer); -+ bool aClearBuffer, bool aFullScreenUpdate); - already_AddRefed LockImageSurface( - const gfx::IntSize& aLockSize); - bool CommitImageSurfaceToWaylandBuffer(const LayoutDeviceIntRegion& aRegion); -- cgit