2508 lines
93 KiB
Diff
2508 lines
93 KiB
Diff
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 <fcntl.h>
|
|
+#include <getopt.h>
|
|
+#include <signal.h>
|
|
+#include <stdbool.h>
|
|
+#include <stdint.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <sys/time.h>
|
|
+#include <dlfcn.h>
|
|
+
|
|
+#include <gbm.h>
|
|
+
|
|
+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<bool>(mAvailable);
|
|
+}
|
|
+
|
|
+static void buffer_release(void* data, wl_buffer* buffer) {
|
|
+ auto surface = reinterpret_cast<WaylandDMABufSurface*>(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<WaylandDMABufSurface*>(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 <stdint.h>
|
|
+#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<nsWaylandDisplay*>(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<nsWaylandDisplay *>(data);
|
|
- if (!display)
|
|
- return;
|
|
+ auto display = reinterpret_cast<nsWaylandDisplay*>(data);
|
|
+ if (!display) return;
|
|
|
|
if (strcmp(interface, "wl_shm") == 0) {
|
|
- auto shm = static_cast<wl_shm *>(
|
|
+ auto shm = static_cast<wl_shm*>(
|
|
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<wl_data_device_manager *>(
|
|
+ auto data_device_manager = static_cast<wl_data_device_manager*>(
|
|
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<wl_seat *>(
|
|
+ auto seat = static_cast<wl_seat*>(
|
|
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<gtk_primary_selection_device_manager *>(wl_registry_bind(
|
|
+ static_cast<gtk_primary_selection_device_manager*>(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<wl_subcompositor *>(
|
|
+ auto subcompositor = static_cast<wl_subcompositor*>(
|
|
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<zwp_linux_dmabuf_v1*>(
|
|
+ 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 <drm/drm_fourcc.h>
|
|
+# include <xf86drm.h>
|
|
+# include <gbm.h>
|
|
+# 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 <stdint.h>
|
|
+#include <stddef.h>
|
|
+#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
|
|
+ * <pre>
|
|
+ *
|
|
+ * 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.
|
|
+ * </pre>
|
|
+ */
|
|
+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 <stdlib.h>
|
|
+#include <stdint.h>
|
|
+#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<class WindowBackBufferShm*>(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<gfx::DrawTarget> WindowBackBuffer::Lock() {
|
|
+already_AddRefed<gfx::DrawTarget> 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<gfx::DrawTarget> Window
|
|
gfx::IntSize lockSize(mWidth, mHeight);
|
|
return gfxPlatform::CreateDrawTargetForData(
|
|
static_cast<unsigned char*>(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<gfx::DrawTarget> 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<unsigned char*>(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<WindowBackBufferDMABuf*>(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<WindowSurfaceWayland*>(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<gfx::DrawTarget> 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<gfx::DrawTarget> Window
|
|
return buffer->Lock();
|
|
}
|
|
|
|
+void WindowSurfaceWayland::UnlockWaylandBuffer() { mWaylandBuffer->Unlock(); }
|
|
+
|
|
already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockImageSurface(
|
|
const gfx::IntSize& aLockSize) {
|
|
if (!mImageSurface || mImageSurface->CairoStatus() ||
|
|
@@ -555,10 +672,18 @@ already_AddRefed<gfx::DrawTarget> Window
|
|
lockSize.height == screenRect.height);
|
|
|
|
if (mDrawToWaylandBufferDirectly) {
|
|
- RefPtr<gfx::DrawTarget> 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<gfx::DrawTarget> 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<gfx::DrawTarget> 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<IntRect, 32> 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<gfx::DrawTarget> dt = LockWaylandBuffer(
|
|
- screenRect.width, screenRect.height, mWindow->WaylandSurfaceNeedsClear());
|
|
RefPtr<gfx::SourceSurface> 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<IntRect, 32> rects;
|
|
- rects.SetCapacity(numRects);
|
|
- for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
|
|
- rects.AppendElement(iter.Get().ToUnknownRect());
|
|
- }
|
|
- dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
|
|
- }
|
|
-
|
|
- dt->DrawSurface(surf, rect, rect);
|
|
-
|
|
- if (numRects != 1) {
|
|
- dt->PopClip();
|
|
+ bool needsClear = mWindow->WaylandSurfaceNeedsClear();
|
|
+ RefPtr<gfx::DrawTarget> 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<gfx::DrawTarget> 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 <prthread.h>
|
|
#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<gfx::DrawTarget> 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<gfx::DrawTarget> 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<gfx::DrawTarget> 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<gfx::SourceSurface> 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<gfx::DrawTarget> LockWaylandBuffer(int aWidth, int aHeight,
|
|
- bool aClearBuffer);
|
|
+ bool aClearBuffer,
|
|
+ bool aFullScreenUpdate,
|
|
+ bool aNoBackBufferCopy);
|
|
+ void UnlockWaylandBuffer();
|
|
+
|
|
already_AddRefed<gfx::DrawTarget> 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<gfxImageSurface> mImageSurface;
|
|
wl_callback* mFrameCallback;
|
|
wl_surface* mLastCommittedSurface;
|
|
MessageLoop* mDisplayThreadMessageLoop;
|
|
WindowSurfaceWayland** mDelayedCommitHandle;
|
|
+ RefPtr<gfxImageSurface> mImageSurface;
|
|
+ AutoTArray<WindowImageSurface, 30> mDelayedImageCommits;
|
|
bool mDrawToWaylandBufferDirectly;
|
|
bool mPendingCommit;
|
|
bool mWaylandBufferFullScreenDamage;
|
|
bool mIsMainThread;
|
|
bool mNeedScaleFactorUpdate;
|
|
bool mWaitToFullScreenUpdate;
|
|
+
|
|
+ static bool UseDMABufBackend();
|
|
+ static bool mUseDMABufInitialized;
|
|
+ static bool mUseDMABuf;
|
|
};
|
|
|
|
} // namespace widget
|