зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
940758881d
Коммит
057f924f15
|
@ -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, ®istry_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__
|
||||
|
|
Загрузка…
Ссылка в новой задаче