2018-11-30 22:52:05 +03:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2018-11-23 10:04:16 +03:00
|
|
|
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
|
|
*/
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "nsWaylandDisplay.h"
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace widget {
|
|
|
|
|
2019-06-08 00:45:46 +03:00
|
|
|
#define GBMLIB_NAME "libgbm.so.1"
|
|
|
|
#define DRMLIB_NAME "libdrm.so.2"
|
|
|
|
|
2019-07-01 11:55:03 +03:00
|
|
|
bool nsWaylandDisplay::mIsDMABufEnabled = false;
|
|
|
|
// -1 mean the pref was not loaded yet
|
|
|
|
int nsWaylandDisplay::mIsDMABufPrefState = -1;
|
|
|
|
bool nsWaylandDisplay::mIsDMABufConfigured = false;
|
2019-06-10 15:37:06 +03:00
|
|
|
|
2019-07-01 09:38:32 +03:00
|
|
|
wl_display* WaylandDisplayGetWLDisplay(GdkDisplay* aGdkDisplay) {
|
|
|
|
if (!aGdkDisplay) {
|
|
|
|
aGdkDisplay = gdk_display_get_default();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Available as of GTK 3.8+
|
|
|
|
static auto sGdkWaylandDisplayGetWlDisplay = (wl_display * (*)(GdkDisplay*))
|
|
|
|
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
|
|
|
|
return sGdkWaylandDisplayGetWlDisplay(aGdkDisplay);
|
|
|
|
}
|
|
|
|
|
2019-02-18 12:15:30 +03:00
|
|
|
// nsWaylandDisplay needs to be created for each calling thread(main thread,
|
|
|
|
// compositor thread and render thread)
|
|
|
|
#define MAX_DISPLAY_CONNECTIONS 3
|
2018-11-23 10:04:16 +03:00
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
static nsWaylandDisplay* gWaylandDisplays[MAX_DISPLAY_CONNECTIONS];
|
2018-11-23 10:04:16 +03:00
|
|
|
static StaticMutex gWaylandDisplaysMutex;
|
|
|
|
|
2019-04-30 12:37:37 +03:00
|
|
|
void WaylandDisplayShutdown() {
|
|
|
|
StaticMutexAutoLock lock(gWaylandDisplaysMutex);
|
2019-05-01 11:47:10 +03:00
|
|
|
for (auto& display : gWaylandDisplays) {
|
2019-04-30 12:37:37 +03:00
|
|
|
if (display) {
|
|
|
|
display->Shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 00:39:51 +03:00
|
|
|
static void ReleaseDisplaysAtExit() {
|
|
|
|
for (int i = 0; i < MAX_DISPLAY_CONNECTIONS; i++) {
|
|
|
|
delete gWaylandDisplays[i];
|
|
|
|
gWaylandDisplays[i] = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
static void DispatchDisplay(nsWaylandDisplay* aDisplay) {
|
2019-04-30 12:37:37 +03:00
|
|
|
aDisplay->DispatchEventQueue();
|
|
|
|
}
|
|
|
|
|
2018-11-23 10:04:16 +03:00
|
|
|
// Each thread which is using wayland connection (wl_display) has to operate
|
|
|
|
// its own wl_event_queue. Main Firefox thread wl_event_queue is handled
|
|
|
|
// by Gtk main loop, other threads/wl_event_queue has to be handled by us.
|
|
|
|
//
|
|
|
|
// nsWaylandDisplay is our interface to wayland compositor. It provides wayland
|
|
|
|
// global objects as we need (wl_display, wl_shm) and operates wl_event_queue on
|
|
|
|
// compositor (not the main) thread.
|
2019-04-30 12:37:37 +03:00
|
|
|
void WaylandDispatchDisplays() {
|
|
|
|
StaticMutexAutoLock lock(gWaylandDisplaysMutex);
|
2019-05-01 11:47:10 +03:00
|
|
|
for (auto& display : gWaylandDisplays) {
|
2019-04-30 12:37:37 +03:00
|
|
|
if (display && display->GetDispatcherThreadLoop()) {
|
|
|
|
display->GetDispatcherThreadLoop()->PostTask(NewRunnableFunction(
|
|
|
|
"WaylandDisplayDispatch", &DispatchDisplay, display));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-23 10:04:16 +03:00
|
|
|
|
|
|
|
// Get WaylandDisplay for given wl_display and actual calling thread.
|
2019-05-01 11:47:10 +03:00
|
|
|
static nsWaylandDisplay* WaylandDisplayGetLocked(GdkDisplay* aGdkDisplay,
|
|
|
|
const StaticMutexAutoLock&) {
|
2019-07-01 09:38:32 +03:00
|
|
|
wl_display* waylandDisplay = WaylandDisplayGetWLDisplay(aGdkDisplay);
|
2019-04-10 00:39:51 +03:00
|
|
|
|
|
|
|
// Search existing display connections for wl_display:thread combination.
|
2019-05-01 11:47:10 +03:00
|
|
|
for (auto& display : gWaylandDisplays) {
|
2019-04-10 00:39:51 +03:00
|
|
|
if (display && display->Matches(waylandDisplay)) {
|
2018-11-23 10:04:16 +03:00
|
|
|
return display;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
for (auto& display : gWaylandDisplays) {
|
2018-11-23 10:04:16 +03:00
|
|
|
if (display == nullptr) {
|
2019-04-10 00:39:51 +03:00
|
|
|
display = new nsWaylandDisplay(waylandDisplay);
|
|
|
|
atexit(ReleaseDisplaysAtExit);
|
2018-11-23 10:04:16 +03:00
|
|
|
return display;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_CRASH("There's too many wayland display conections!");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay) {
|
2018-11-23 10:04:16 +03:00
|
|
|
if (!aGdkDisplay) {
|
|
|
|
aGdkDisplay = gdk_display_get_default();
|
2019-07-02 12:17:22 +03:00
|
|
|
if (!aGdkDisplay) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-11-23 10:04:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
StaticMutexAutoLock lock(gWaylandDisplaysMutex);
|
2019-04-10 00:39:51 +03:00
|
|
|
return WaylandDisplayGetLocked(aGdkDisplay, lock);
|
2018-11-23 10:04:16 +03:00
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
void nsWaylandDisplay::SetShm(wl_shm* aShm) { mShm = aShm; }
|
2018-11-23 10:04:16 +03:00
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) {
|
2018-11-23 10:04:16 +03:00
|
|
|
mSubcompositor = aSubcompositor;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsWaylandDisplay::SetDataDeviceManager(
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_data_device_manager* aDataDeviceManager) {
|
2018-11-23 10:04:16 +03:00
|
|
|
mDataDeviceManager = aDataDeviceManager;
|
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
void nsWaylandDisplay::SetSeat(wl_seat* aSeat) { mSeat = aSeat; }
|
2018-11-23 10:04:16 +03:00
|
|
|
|
|
|
|
void nsWaylandDisplay::SetPrimarySelectionDeviceManager(
|
2019-05-01 11:47:10 +03:00
|
|
|
gtk_primary_selection_device_manager* aPrimarySelectionDeviceManager) {
|
2018-11-23 10:04:16 +03:00
|
|
|
mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager;
|
|
|
|
}
|
|
|
|
|
2019-06-04 11:46:59 +03:00
|
|
|
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};
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
static void global_registry_handler(void* data, wl_registry* registry,
|
|
|
|
uint32_t id, const char* interface,
|
2018-11-23 10:04:16 +03:00
|
|
|
uint32_t version) {
|
2019-05-01 11:47:10 +03:00
|
|
|
auto display = reinterpret_cast<nsWaylandDisplay*>(data);
|
2019-04-10 00:39:51 +03:00
|
|
|
if (!display) return;
|
2018-11-23 10:04:16 +03:00
|
|
|
|
|
|
|
if (strcmp(interface, "wl_shm") == 0) {
|
2019-05-01 11:47:10 +03:00
|
|
|
auto shm = static_cast<wl_shm*>(
|
2018-11-23 10:04:16 +03:00
|
|
|
wl_registry_bind(registry, id, &wl_shm_interface, 1));
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_proxy_set_queue((struct wl_proxy*)shm, display->GetEventQueue());
|
2018-11-23 10:04:16 +03:00
|
|
|
display->SetShm(shm);
|
|
|
|
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
|
|
|
|
int data_device_manager_version = MIN(version, 3);
|
2019-05-01 11:47:10 +03:00
|
|
|
auto data_device_manager = static_cast<wl_data_device_manager*>(
|
2018-11-23 10:04:16 +03:00
|
|
|
wl_registry_bind(registry, id, &wl_data_device_manager_interface,
|
|
|
|
data_device_manager_version));
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_proxy_set_queue((struct wl_proxy*)data_device_manager,
|
2018-11-23 10:04:16 +03:00
|
|
|
display->GetEventQueue());
|
|
|
|
display->SetDataDeviceManager(data_device_manager);
|
|
|
|
} else if (strcmp(interface, "wl_seat") == 0) {
|
2019-05-01 11:47:10 +03:00
|
|
|
auto seat = static_cast<wl_seat*>(
|
2018-11-23 10:04:16 +03:00
|
|
|
wl_registry_bind(registry, id, &wl_seat_interface, 1));
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_proxy_set_queue((struct wl_proxy*)seat, display->GetEventQueue());
|
2018-11-23 10:04:16 +03:00
|
|
|
display->SetSeat(seat);
|
|
|
|
} else if (strcmp(interface, "gtk_primary_selection_device_manager") == 0) {
|
|
|
|
auto primary_selection_device_manager =
|
2019-05-01 11:47:10 +03:00
|
|
|
static_cast<gtk_primary_selection_device_manager*>(wl_registry_bind(
|
2018-11-23 10:04:16 +03:00
|
|
|
registry, id, >k_primary_selection_device_manager_interface, 1));
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_proxy_set_queue((struct wl_proxy*)primary_selection_device_manager,
|
2018-11-23 10:04:16 +03:00
|
|
|
display->GetEventQueue());
|
|
|
|
display->SetPrimarySelectionDeviceManager(primary_selection_device_manager);
|
|
|
|
} else if (strcmp(interface, "wl_subcompositor") == 0) {
|
2019-05-01 11:47:10 +03:00
|
|
|
auto subcompositor = static_cast<wl_subcompositor*>(
|
2018-11-23 10:04:16 +03:00
|
|
|
wl_registry_bind(registry, id, &wl_subcompositor_interface, 1));
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_proxy_set_queue((struct wl_proxy*)subcompositor,
|
2018-11-23 10:04:16 +03:00
|
|
|
display->GetEventQueue());
|
|
|
|
display->SetSubcompositor(subcompositor);
|
2019-06-21 00:52:40 +03:00
|
|
|
} else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version > 2) {
|
2019-06-04 11:46:59 +03:00
|
|
|
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);
|
|
|
|
}
|
2018-11-23 10:04:16 +03:00
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
static void global_registry_remover(void* data, wl_registry* registry,
|
2018-11-23 10:04:16 +03:00
|
|
|
uint32_t id) {}
|
|
|
|
|
|
|
|
static const struct wl_registry_listener registry_listener = {
|
|
|
|
global_registry_handler, global_registry_remover};
|
|
|
|
|
2019-04-30 12:37:37 +03:00
|
|
|
bool nsWaylandDisplay::DispatchEventQueue() {
|
2018-11-23 10:04:16 +03:00
|
|
|
wl_display_dispatch_queue_pending(mDisplay, mEventQueue);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
bool nsWaylandDisplay::Matches(wl_display* aDisplay) {
|
2018-11-23 10:04:16 +03:00
|
|
|
return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay;
|
|
|
|
}
|
|
|
|
|
2019-06-04 11:46:59 +03:00
|
|
|
bool nsWaylandDisplay::ConfigureGbm() {
|
|
|
|
if (!nsGbmLib::IsAvailable()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO - Better DRM device detection/configuration.
|
|
|
|
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);
|
|
|
|
mGbmFd = -1;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-05-01 11:47:10 +03:00
|
|
|
nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
|
2019-04-30 12:37:37 +03:00
|
|
|
: mDispatcherThreadLoop(nullptr),
|
|
|
|
mThreadId(PR_GetCurrentThread()),
|
2018-11-23 10:04:16 +03:00
|
|
|
mDisplay(aDisplay),
|
|
|
|
mEventQueue(nullptr),
|
|
|
|
mDataDeviceManager(nullptr),
|
|
|
|
mSubcompositor(nullptr),
|
|
|
|
mSeat(nullptr),
|
|
|
|
mShm(nullptr),
|
2019-04-10 00:39:51 +03:00
|
|
|
mPrimarySelectionDeviceManager(nullptr),
|
2019-06-21 00:52:40 +03:00
|
|
|
mRegistry(nullptr),
|
2019-06-04 11:46:59 +03:00
|
|
|
mGbmDevice(nullptr),
|
|
|
|
mGbmFd(-1),
|
2019-06-08 00:31:56 +03:00
|
|
|
mXRGBFormat({false, false, -1, nullptr, 0}),
|
2019-06-10 15:37:06 +03:00
|
|
|
mARGBFormat({false, false, -1, nullptr, 0}),
|
|
|
|
mGdmConfigured(false),
|
2019-06-21 00:52:40 +03:00
|
|
|
mExplicitSync(false) {
|
2019-04-10 00:39:51 +03:00
|
|
|
mRegistry = wl_display_get_registry(mDisplay);
|
|
|
|
wl_registry_add_listener(mRegistry, ®istry_listener, this);
|
2018-11-23 10:04:16 +03:00
|
|
|
|
|
|
|
if (NS_IsMainThread()) {
|
2019-07-01 11:55:03 +03:00
|
|
|
// We can't load the preference from compositor/render thread,
|
|
|
|
// only from main one. So we can't call it directly from
|
|
|
|
// nsWaylandDisplay::IsDMABufEnabled() as it can be called from various
|
|
|
|
// threads.
|
|
|
|
if (mIsDMABufPrefState == -1) {
|
|
|
|
mIsDMABufPrefState =
|
2019-06-10 15:37:06 +03:00
|
|
|
Preferences::GetBool("widget.wayland_dmabuf_backend.enabled", false);
|
|
|
|
}
|
2018-11-23 10:04:16 +03:00
|
|
|
// Use default event queue in main thread operated by Gtk+.
|
|
|
|
mEventQueue = nullptr;
|
|
|
|
wl_display_roundtrip(mDisplay);
|
|
|
|
wl_display_roundtrip(mDisplay);
|
|
|
|
} else {
|
2019-04-30 12:37:37 +03:00
|
|
|
mDispatcherThreadLoop = MessageLoop::current();
|
2018-11-23 10:04:16 +03:00
|
|
|
mEventQueue = wl_display_create_queue(mDisplay);
|
2019-05-01 11:47:10 +03:00
|
|
|
wl_proxy_set_queue((struct wl_proxy*)mRegistry, mEventQueue);
|
2018-11-23 10:04:16 +03:00
|
|
|
wl_display_roundtrip_queue(mDisplay, mEventQueue);
|
|
|
|
wl_display_roundtrip_queue(mDisplay, mEventQueue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-30 12:37:37 +03:00
|
|
|
void nsWaylandDisplay::Shutdown() { mDispatcherThreadLoop = nullptr; }
|
|
|
|
|
2018-11-23 10:04:16 +03:00
|
|
|
nsWaylandDisplay::~nsWaylandDisplay() {
|
|
|
|
// Owned by Gtk+, we don't need to release
|
|
|
|
mDisplay = nullptr;
|
|
|
|
|
2019-04-10 00:39:51 +03:00
|
|
|
wl_registry_destroy(mRegistry);
|
|
|
|
mRegistry = nullptr;
|
|
|
|
|
2018-11-23 10:04:16 +03:00
|
|
|
if (mEventQueue) {
|
|
|
|
wl_event_queue_destroy(mEventQueue);
|
|
|
|
mEventQueue = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-01 11:55:03 +03:00
|
|
|
bool nsWaylandDisplay::IsDMABufEnabled() {
|
|
|
|
if (mIsDMABufConfigured) {
|
|
|
|
return mIsDMABufEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
// WaylandDisplayGet() sets mIsDMABufPrefState
|
|
|
|
nsWaylandDisplay* display = WaylandDisplayGet();
|
2019-07-02 12:17:22 +03:00
|
|
|
if (!display) {
|
|
|
|
NS_WARNING("Failed to get nsWaylandDisplay, called too early?");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-07-01 11:55:03 +03:00
|
|
|
if (nsWaylandDisplay::mIsDMABufPrefState == -1) {
|
|
|
|
MOZ_ASSERT(false,
|
|
|
|
"We're missing nsWaylandDisplay preference configuration!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mIsDMABufConfigured = true;
|
|
|
|
if (!nsWaylandDisplay::mIsDMABufPrefState) {
|
|
|
|
// Disabled by user, just quit.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!display->ConfigureGbm()) {
|
|
|
|
NS_WARNING("Failed to create GbmDevice, DMABUF/DRM won't be available!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!display->GetGbmFormat(/* aHasAlpha */ false) ||
|
|
|
|
!display->GetGbmFormat(/* aHasAlpha */ true)) {
|
|
|
|
NS_WARNING(
|
|
|
|
"Failed to create obtain pixel format, DMABUF/DRM won't be available!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mIsDMABufEnabled = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-06-04 11:46:59 +03:00
|
|
|
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;
|
|
|
|
|
2019-06-08 00:45:46 +03:00
|
|
|
sGbmLibHandle = dlopen(GBMLIB_NAME, RTLD_LAZY | RTLD_LOCAL);
|
2019-06-04 11:46:59 +03:00
|
|
|
if (!sGbmLibHandle) {
|
2019-06-08 00:45:46 +03:00
|
|
|
NS_WARNING(nsPrintfCString("Failed to load %s, dmabuf isn't available.\n",
|
|
|
|
GBMLIB_NAME)
|
|
|
|
.get());
|
2019-06-04 11:46:59 +03:00
|
|
|
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");
|
|
|
|
|
2019-06-08 00:45:46 +03:00
|
|
|
sXf86DrmLibHandle = dlopen(DRMLIB_NAME, RTLD_LAZY | RTLD_LOCAL);
|
2019-06-04 11:46:59 +03:00
|
|
|
if (sXf86DrmLibHandle) {
|
|
|
|
sDrmPrimeHandleToFD = (DrmPrimeHandleToFDFunc)dlsym(sXf86DrmLibHandle,
|
|
|
|
"drmPrimeHandleToFD");
|
2019-06-08 00:45:46 +03:00
|
|
|
if (!sDrmPrimeHandleToFD) {
|
|
|
|
NS_WARNING(nsPrintfCString(
|
|
|
|
"Failed to load %s, gbm modifiers are not available.\n",
|
|
|
|
DRMLIB_NAME)
|
|
|
|
.get());
|
|
|
|
}
|
2019-06-04 11:46:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sGbmLibHandle;
|
|
|
|
}
|
|
|
|
|
2018-11-23 10:04:16 +03:00
|
|
|
} // namespace widget
|
|
|
|
} // namespace mozilla
|