Bug 1554520 - [Wayland] Load DMABuf setup in WaylandDisplay class, r=jhorak

- Implement nsGbmLib object which binds symbols run-time from libgbm.so library.
- Load available DRM pixel formats from Wayland registry and store related modifiers at WaylandDisplay object.
- Implement Gbm device setup at WaylandDisplay.

Differential Revision: https://phabricator.services.mozilla.com/D32633

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Martin Stransky 2019-06-04 08:46:59 +00:00
Родитель 940758881d
Коммит 057f924f15
3 изменённых файлов: 342 добавлений и 10 удалений

Просмотреть файл

@ -7,7 +7,11 @@
SOURCES += [
'mozwayland.c',
]
EXPORTS.mozilla.widget += [
'mozwayland.h',
]
SharedLibrary('mozwayland')
CFLAGS += CONFIG['TK_CFLAGS']

Просмотреть файл

@ -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 {
@ -112,6 +108,58 @@ void nsWaylandDisplay::SetPrimarySelectionDeviceManager(
mPrimarySelectionDeviceManager = aPrimarySelectionDeviceManager;
}
#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) {
@ -150,6 +198,14 @@ static void global_registry_handler(void* data, wl_registry* registry,
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,
@ -167,6 +223,56 @@ bool nsWaylandDisplay::Matches(wl_display* aDisplay) {
return mThreadId == PR_GetCurrentThread() && aDisplay == mDisplay;
}
#ifdef HAVE_LIBDRM
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;
}
#endif
nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
: mDispatcherThreadLoop(nullptr),
mThreadId(PR_GetCurrentThread()),
@ -177,7 +283,17 @@ nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
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, &registry_listener, this);
@ -210,5 +326,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

Просмотреть файл

@ -5,15 +5,34 @@
* 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"
#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
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 {
@ -46,7 +65,26 @@ class nsWaylandDisplay {
void Shutdown();
#ifdef HAVE_LIBDRM
void SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf);
zwp_linux_dmabuf_v1* GetDmabuf() { return mDmabuf; };
gbm_device* GetGbmDevice();
// Returns -1 if we fails to gbm device file descriptor.
int GetGbmDeviceFd();
bool IsExplicitSyncEnabled() { return mExplicitSync; }
GbmFormat* GetGbmFormat(bool aHasAlpha);
void AddFormatModifier(bool aHasAlpha, int aFormat, uint32_t mModifierHi,
uint32_t mModifierLo);
#endif
private:
#ifdef HAVE_LIBDRM
bool ConfigureGbm();
#endif
MessageLoop* mDispatcherThreadLoop;
PRThread* mThreadId;
wl_display* mDisplay;
@ -57,12 +95,112 @@ class nsWaylandDisplay {
wl_shm* mShm;
gtk_primary_selection_device_manager* mPrimarySelectionDeviceManager;
wl_registry* mRegistry;
#ifdef HAVE_LIBDRM
zwp_linux_dmabuf_v1* mDmabuf;
gbm_device* mGbmDevice;
int mGbmFd;
bool mGdmConfigured;
bool mExplicitSync;
GbmFormat mXRGBFormat;
GbmFormat mARGBFormat;
#endif
};
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__