backend: add preliminary support for driver detection

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2019-04-20 00:21:38 +01:00
parent a2d0d5c826
commit 685a583f84
7 changed files with 132 additions and 1 deletions

View File

@ -5,6 +5,7 @@
#include <stdbool.h>
#include "driver.h"
#include "compiler.h"
#include "kernel.h"
#include "region.h"
@ -176,6 +177,9 @@ struct backend_operations {
// =========== Hooks ============
/// Let the backend hook into the event handling queue
// =========== Misc ============
/// Return the driver that is been used by the backend
enum driver (*detect_driver)(backend_t *backend_data);
};
typedef backend_t *(*backend_init_fn)(session_t *ps)attr_nonnull(1);

62
src/backend/driver.c Normal file
View File

@ -0,0 +1,62 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#include <xcb/randr.h>
#include <xcb/xcb.h>
#include "backend/backend.h"
#include "backend/driver.h"
#include "common.h"
enum driver detect_driver(xcb_connection_t *c, backend_t *backend_data, xcb_window_t window) {
enum driver ret = 0;
// First we try doing backend agnostic detection using RANDR
// There's no way to query the X server about what driver is loaded, so RANDR is
// our best shot.
auto randr_version = xcb_randr_query_version_reply(
c, xcb_randr_query_version(c, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION),
NULL);
if (randr_version &&
(randr_version->major_version > 1 || randr_version->minor_version >= 4)) {
auto r = xcb_randr_get_providers_reply(
c, xcb_randr_get_providers(c, window), NULL);
if (r == NULL) {
log_warn("Failed to get RANDR providers");
return 0;
}
auto providers = xcb_randr_get_providers_providers(r);
for (auto i = 0; i < xcb_randr_get_providers_providers_length(r); i++) {
auto r2 = xcb_randr_get_provider_info_reply(
c, xcb_randr_get_provider_info(c, providers[i], r->timestamp), NULL);
if (r2 == NULL) {
continue;
}
if (r2->num_outputs == 0) {
free(r2);
continue;
}
auto name = xcb_randr_get_provider_info_name(r2);
if (strcasestr(name, "modesetting") != NULL) {
ret |= DRIVER_MODESETTING;
} else if (strcasestr(name, "Radeon") != NULL) {
// Be conservative, add both radeon drivers
ret |= DRIVER_AMDGPU | DRIVER_RADEON;
} else if (strcasestr(name, "NVIDIA") != NULL) {
ret |= DRIVER_NVIDIA;
} else if (strcasestr(name, "nouveau") != NULL) {
ret |= DRIVER_NOUVEAU;
} else if (strcasestr(name, "Intel") != NULL) {
ret |= DRIVER_INTEL;
}
}
free(r);
}
// If the backend supports driver detection, use that as well
if (backend_data && backend_data->ops->detect_driver) {
ret |= backend_data->ops->detect_driver(backend_data);
}
return ret;
}

55
src/backend/driver.h Normal file
View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#pragma once
#include <stdio.h>
#include <xcb/xcb.h>
struct session;
struct backend_base;
/// A list of possible drivers.
/// The driver situation is a bit complicated. There are two drivers we care about: the
/// DDX, and the OpenGL driver. They are usually paired, but not always, since there is
/// also the generic modesetting driver.
/// This enum represents _both_ drivers.
enum driver {
DRIVER_AMDGPU = 1, // AMDGPU for DDX, radeonsi for OpenGL
DRIVER_RADEON = 2, // ATI for DDX, mesa r600 for OpenGL
DRIVER_FGLRX = 4,
DRIVER_NVIDIA = 8,
DRIVER_NOUVEAU = 16,
DRIVER_INTEL = 32,
DRIVER_MODESETTING = 64,
};
/// Return a list of drivers currently in use by the X server.
/// Note, this is a best-effort test, so no guarantee all drivers will be detected.
enum driver detect_driver(xcb_connection_t *, struct backend_base *, xcb_window_t);
// Print driver names to stdout, for diagnostics
static inline void print_drivers(enum driver drivers) {
if (drivers & DRIVER_AMDGPU) {
printf("AMDGPU, ");
}
if (drivers & DRIVER_RADEON) {
printf("Radeon, ");
}
if (drivers & DRIVER_FGLRX) {
printf("fglrx, ");
}
if (drivers & DRIVER_NVIDIA) {
printf("NVIDIA, ");
}
if (drivers & DRIVER_NOUVEAU) {
printf("nouveau, ");
}
if (drivers & DRIVER_INTEL) {
printf("Intel, ");
}
if (drivers & DRIVER_MODESETTING) {
printf("modesetting, ");
}
printf("\b\b \n");
}

View File

@ -1,5 +1,5 @@
# enable xrender
srcs += [ files('backend_common.c', 'xrender/xrender.c', 'backend.c') ]
srcs += [ files('backend_common.c', 'xrender/xrender.c', 'backend.c', 'driver.c') ]
# enable opengl
if get_option('opengl')