mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1588904 - [Linux/EGL] Use correct rendering device in multi-GPU setup, r=stransky,emilio,jgilbert,geckoview-reviewers,m_kato
Fetch the DRM device in the EGL version of glxtest, set it in gfxInfo and pass it to gfxVars. Finally, use it in nsDMABufDevice::Configure(). While on it, also clean up EGL typedefs and defines a bit to match how it's done for GLX. Inspired by and copied from wlroots and Xwayland. Thanks to emersion! Differential Revision: https://phabricator.services.mozilla.com/D98108
This commit is contained in:
parent
a1ccc07a39
commit
736a9e904d
@ -73,7 +73,8 @@ class gfxVarReceiver;
|
||||
_(FxREmbedded, bool, false) \
|
||||
_(UseAHardwareBufferContent, bool, false) \
|
||||
_(UseAHardwareBufferSharedSurface, bool, false) \
|
||||
_(UseEGL, bool, false)
|
||||
_(UseEGL, bool, false) \
|
||||
_(DrmRenderDevice, nsCString, nsCString())
|
||||
|
||||
/* Add new entries above this line. */
|
||||
|
||||
|
@ -223,6 +223,9 @@ class MockGfxInfo final : public nsIGfxInfo {
|
||||
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
NS_IMETHOD ControlGPUProcessForXPCShell(bool aEnable,
|
||||
bool* _retval) override {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
@ -102,6 +102,11 @@ gfxPlatformGtk::gfxPlatformGtk() {
|
||||
#endif
|
||||
if (IsWaylandDisplay() || useEGLOnX11) {
|
||||
gfxVars::SetUseEGL(true);
|
||||
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
nsAutoCString drmRenderDevice;
|
||||
gfxInfo->GetDrmRenderDevice(drmRenderDevice);
|
||||
gfxVars::SetDrmRenderDevice(drmRenderDevice);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,23 +84,62 @@ typedef uint32_t GLenum;
|
||||
// clang-format on
|
||||
|
||||
// stuff from egl.h
|
||||
typedef intptr_t EGLAttrib;
|
||||
typedef int EGLBoolean;
|
||||
typedef void* EGLConfig;
|
||||
typedef void* EGLContext;
|
||||
typedef void* EGLDeviceEXT;
|
||||
typedef void* EGLDisplay;
|
||||
typedef int EGLint;
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef void* EGLSurface;
|
||||
typedef void* (*PFNEGLGETPROCADDRESS)(const char*);
|
||||
|
||||
#define EGL_NO_CONTEXT nullptr
|
||||
#define EGL_FALSE 0
|
||||
#define EGL_TRUE 1
|
||||
#define EGL_BLUE_SIZE 0x3022
|
||||
#define EGL_GREEN_SIZE 0x3023
|
||||
#define EGL_RED_SIZE 0x3024
|
||||
#define EGL_NONE 0x3038
|
||||
#define EGL_VENDOR 0x3053
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
#define EGL_NO_CONTEXT nullptr
|
||||
#define EGL_DEVICE_EXT 0x322C
|
||||
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
|
||||
|
||||
// stuff from xf86drm.h
|
||||
#define DRM_NODE_RENDER 2
|
||||
#define DRM_NODE_MAX 3
|
||||
|
||||
typedef struct _drmDevice {
|
||||
char** nodes;
|
||||
int available_nodes;
|
||||
int bustype;
|
||||
union {
|
||||
void* pci;
|
||||
void* usb;
|
||||
void* platform;
|
||||
void* host1x;
|
||||
} businfo;
|
||||
union {
|
||||
void* pci;
|
||||
void* usb;
|
||||
void* platform;
|
||||
void* host1x;
|
||||
} deviceinfo;
|
||||
} drmDevice, *drmDevicePtr;
|
||||
|
||||
// Open libGL and load needed symbols
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# define LIBGL_FILENAME "libGL.so"
|
||||
# define LIBGLES_FILENAME "libGLESv2.so"
|
||||
# define LIBEGL_FILENAME "libEGL.so"
|
||||
# define LIBDRM_FILENAME "libdrm.so"
|
||||
#else
|
||||
# define LIBGL_FILENAME "libGL.so.1"
|
||||
# define LIBGLES_FILENAME "libGLESv2.so.2"
|
||||
# define LIBEGL_FILENAME "libEGL.so.1"
|
||||
# define LIBDRM_FILENAME "libdrm.so.2"
|
||||
#endif
|
||||
|
||||
#define EXIT_FAILURE_BUFFER_TOO_SMALL 2
|
||||
@ -282,18 +321,91 @@ static void get_pci_status() {
|
||||
dlclose(libpci);
|
||||
}
|
||||
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef void* EGLDisplay;
|
||||
typedef int EGLBoolean;
|
||||
typedef int EGLint;
|
||||
typedef void* (*PFNEGLGETPROCADDRESS)(const char*);
|
||||
#ifdef MOZ_WAYLAND
|
||||
static bool device_has_name(const drmDevice* device, const char* name) {
|
||||
for (size_t i = 0; i < DRM_NODE_MAX; i++) {
|
||||
if (!(device->available_nodes & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(device->nodes[i], name) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static char* get_render_name(const char* name) {
|
||||
void* libdrm = dlopen(LIBDRM_FILENAME, RTLD_LAZY);
|
||||
if (!libdrm) {
|
||||
record_warning("Failed to open libdrm");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
typedef int (*DRMGETDEVICES2)(uint32_t, drmDevicePtr*, int);
|
||||
DRMGETDEVICES2 drmGetDevices2 =
|
||||
cast<DRMGETDEVICES2>(dlsym(libdrm, "drmGetDevices2"));
|
||||
|
||||
typedef void (*DRMFREEDEVICE)(drmDevicePtr*);
|
||||
DRMFREEDEVICE drmFreeDevice =
|
||||
cast<DRMFREEDEVICE>(dlsym(libdrm, "drmFreeDevice"));
|
||||
|
||||
if (!drmGetDevices2 || !drmFreeDevice) {
|
||||
record_warning(
|
||||
"libdrm missing methods for drmGetDevices2 or drmFreeDevice");
|
||||
dlclose(libdrm);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
int devices_len = drmGetDevices2(flags, nullptr, 0);
|
||||
if (devices_len < 0) {
|
||||
record_warning("drmGetDevices2 failed");
|
||||
dlclose(libdrm);
|
||||
return nullptr;
|
||||
}
|
||||
drmDevice** devices = (drmDevice**)calloc(devices_len, sizeof(drmDevice*));
|
||||
if (!devices) {
|
||||
record_warning("Allocation error");
|
||||
dlclose(libdrm);
|
||||
return nullptr;
|
||||
}
|
||||
devices_len = drmGetDevices2(flags, devices, devices_len);
|
||||
if (devices_len < 0) {
|
||||
free(devices);
|
||||
record_warning("drmGetDevices2 failed");
|
||||
dlclose(libdrm);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const drmDevice* match = nullptr;
|
||||
for (int i = 0; i < devices_len; i++) {
|
||||
if (device_has_name(devices[i], name)) {
|
||||
match = devices[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char* render_name = nullptr;
|
||||
if (!match) {
|
||||
record_warning("Cannot find DRM device");
|
||||
} else if (!(match->available_nodes & (1 << DRM_NODE_RENDER))) {
|
||||
record_warning("DRM device has no render node");
|
||||
} else {
|
||||
render_name = strdup(match->nodes[DRM_NODE_RENDER]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < devices_len; i++) {
|
||||
drmFreeDevice(&devices[i]);
|
||||
}
|
||||
free(devices);
|
||||
|
||||
dlclose(libdrm);
|
||||
return render_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void get_gles_status(EGLDisplay dpy,
|
||||
PFNEGLGETPROCADDRESS eglGetProcAddress) {
|
||||
typedef void* EGLConfig;
|
||||
typedef void* EGLContext;
|
||||
typedef void* EGLSurface;
|
||||
|
||||
typedef EGLBoolean (*PFNEGLCHOOSECONFIGPROC)(
|
||||
EGLDisplay dpy, EGLint const* attrib_list, EGLConfig* configs,
|
||||
EGLint config_size, EGLint* num_config);
|
||||
@ -317,6 +429,18 @@ static void get_gles_status(EGLDisplay dpy,
|
||||
PFNEGLMAKECURRENTPROC eglMakeCurrent =
|
||||
cast<PFNEGLMAKECURRENTPROC>(eglGetProcAddress("eglMakeCurrent"));
|
||||
|
||||
typedef const char* (*PFNEGLQUERYDEVICESTRINGEXTPROC)(EGLDeviceEXT device,
|
||||
EGLint name);
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT =
|
||||
cast<PFNEGLQUERYDEVICESTRINGEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDeviceStringEXT"));
|
||||
|
||||
typedef EGLBoolean (*PFNEGLQUERYDISPLAYATTRIBEXTPROC)(
|
||||
EGLDisplay dpy, EGLint name, EGLAttrib * value);
|
||||
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT =
|
||||
cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDisplayAttribEXT"));
|
||||
|
||||
if (!eglChooseConfig || !eglCreateContext || !eglCreatePbufferSurface ||
|
||||
!eglMakeCurrent) {
|
||||
record_error("libEGL missing methods for GLES test");
|
||||
@ -370,6 +494,28 @@ static void get_gles_status(EGLDisplay dpy,
|
||||
record_error("libGLESv2 glGetString returned null");
|
||||
}
|
||||
|
||||
if (eglQueryDeviceStringEXT) {
|
||||
EGLDeviceEXT device = nullptr;
|
||||
|
||||
if (eglQueryDisplayAttribEXT(dpy, EGL_DEVICE_EXT, (EGLAttrib*)&device) ==
|
||||
EGL_TRUE) {
|
||||
const char* deviceString =
|
||||
eglQueryDeviceStringEXT(device, EGL_DRM_DEVICE_FILE_EXT);
|
||||
if (deviceString) {
|
||||
record_value("MESA_ACCELERATED\nTRUE\n");
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
char* renderDeviceName = get_render_name(deviceString);
|
||||
if (renderDeviceName) {
|
||||
record_value("DRM_RENDERDEVICE\n%s\n", renderDeviceName);
|
||||
} else {
|
||||
record_warning("Can't find render node name for DRM device");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (libgl) {
|
||||
dlclose(libgl);
|
||||
}
|
||||
|
@ -167,6 +167,8 @@ void GfxInfo::GetData() {
|
||||
nsCString screenInfo;
|
||||
nsCString adapterRam;
|
||||
|
||||
nsCString drmRenderDevice;
|
||||
|
||||
AutoTArray<nsCString, 2> pciVendors;
|
||||
AutoTArray<nsCString, 2> pciDevices;
|
||||
|
||||
@ -207,6 +209,8 @@ void GfxInfo::GetData() {
|
||||
stringToFill = pciVendors.AppendElement();
|
||||
} else if (!strcmp(line, "PCI_DEVICE_ID")) {
|
||||
stringToFill = pciDevices.AppendElement();
|
||||
} else if (!strcmp(line, "DRM_RENDERDEVICE")) {
|
||||
stringToFill = &drmRenderDevice;
|
||||
} else if (!strcmp(line, "WARNING")) {
|
||||
logString = true;
|
||||
} else if (!strcmp(line, "ERROR")) {
|
||||
@ -265,6 +269,8 @@ void GfxInfo::GetData() {
|
||||
NS_WARNING("Failed to parse GL version!");
|
||||
}
|
||||
|
||||
mDrmRenderDevice = std::move(drmRenderDevice);
|
||||
|
||||
// Mesa always exposes itself in the GL_VERSION string, but not always the
|
||||
// GL_VENDOR string.
|
||||
mIsMesa = glVersion.Find("Mesa") != -1;
|
||||
@ -1096,6 +1102,13 @@ GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
|
||||
GetData();
|
||||
aDrmRenderDevice.Assign(mDrmRenderDevice);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// Implement nsIGfxInfoDebug
|
||||
|
@ -50,6 +50,7 @@ class GfxInfo final : public GfxInfoBase {
|
||||
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
|
||||
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
|
||||
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
|
||||
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
|
||||
using GfxInfoBase::GetFeatureStatus;
|
||||
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
|
||||
@ -92,6 +93,8 @@ class GfxInfo final : public GfxInfoBase {
|
||||
nsCString mSecondaryVendorId;
|
||||
nsCString mSecondaryDeviceId;
|
||||
|
||||
nsCString mDrmRenderDevice;
|
||||
|
||||
struct ScreenInfo {
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
|
@ -369,6 +369,11 @@ GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void GfxInfo::AddCrashReportAnnotations() {
|
||||
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID,
|
||||
mGLStrings->Vendor());
|
||||
|
@ -59,6 +59,7 @@ class GfxInfo : public GfxInfoBase {
|
||||
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
|
||||
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
|
||||
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
|
||||
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
|
||||
using GfxInfoBase::GetFeatureStatus;
|
||||
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
|
||||
|
@ -52,6 +52,7 @@ class GfxInfo : public GfxInfoBase {
|
||||
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
|
||||
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
|
||||
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
|
||||
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
|
||||
|
||||
using GfxInfoBase::GetFeatureStatus;
|
||||
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
|
@ -389,6 +389,9 @@ GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
/* readonly attribute boolean isGPU2Active; */
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) { return NS_ERROR_FAILURE; }
|
||||
|
@ -201,21 +201,24 @@ bool nsDMABufDevice::Configure() {
|
||||
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";
|
||||
nsAutoCString drm_render_node(getenv("MOZ_WAYLAND_DRM_DEVICE"));
|
||||
if (drm_render_node.IsEmpty()) {
|
||||
drm_render_node.Assign(gfx::gfxVars::DrmRenderDevice());
|
||||
if (drm_render_node.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mGbmFd = open(drm_render_node, O_RDWR);
|
||||
mGbmFd = open(drm_render_node.get(), O_RDWR);
|
||||
if (mGbmFd < 0) {
|
||||
LOGDMABUF(("Failed to open drm render node %s\n", drm_render_node));
|
||||
LOGDMABUF(("Failed to open drm render node %s\n", drm_render_node.get()));
|
||||
return false;
|
||||
}
|
||||
|
||||
mGbmDevice = nsGbmLib::CreateDevice(mGbmFd);
|
||||
if (mGbmDevice == nullptr) {
|
||||
LOGDMABUF(("Failed to create drm render device %s\n", drm_render_node));
|
||||
if (!mGbmDevice) {
|
||||
LOGDMABUF(
|
||||
("Failed to create drm render device %s\n", drm_render_node.get()));
|
||||
close(mGbmFd);
|
||||
mGbmFd = -1;
|
||||
return false;
|
||||
|
@ -77,6 +77,8 @@ interface nsIGfxInfo : nsISupports
|
||||
|
||||
readonly attribute boolean isGPU2Active;
|
||||
|
||||
readonly attribute ACString drmRenderDevice;
|
||||
|
||||
/**
|
||||
* Information about display devices
|
||||
*/
|
||||
|
@ -1094,6 +1094,11 @@ GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* Cisco's VPN software can cause corruption of the floating point state.
|
||||
* Make a note of this in our crash reports so that some weird crashes
|
||||
* make more sense */
|
||||
|
@ -53,6 +53,7 @@ class GfxInfo : public GfxInfoBase {
|
||||
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
|
||||
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
|
||||
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
|
||||
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
|
||||
using GfxInfoBase::GetFeatureStatus;
|
||||
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user