backend: add preliminary support for driver detection
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
a2d0d5c826
commit
685a583f84
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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')
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
|
||||
// FIXME This list of includes should get shorter
|
||||
#include "backend/backend.h"
|
||||
#include "backend/driver.h"
|
||||
#include "compiler.h"
|
||||
#include "config.h"
|
||||
#include "kernel.h"
|
||||
|
@ -294,6 +295,7 @@ typedef struct session {
|
|||
ev_signal int_signal;
|
||||
/// backend data
|
||||
backend_t *backend_data;
|
||||
enum driver drivers;
|
||||
/// libev mainloop
|
||||
struct ev_loop *loop;
|
||||
|
||||
|
|
|
@ -1311,6 +1311,9 @@ static bool redir_start(session_t *ps) {
|
|||
|
||||
ps->redirected = true;
|
||||
|
||||
// Re-detect driver since we now have a backend
|
||||
ps->drivers = detect_driver(ps->c, ps->backend_data, ps->root);
|
||||
|
||||
root_damaged(ps);
|
||||
|
||||
// Repaint the whole screen
|
||||
|
@ -1985,6 +1988,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
|||
// of OpenGL context.
|
||||
init_overlay(ps);
|
||||
|
||||
ps->drivers = detect_driver(ps->c, ps->backend_data, ps->root);
|
||||
|
||||
// Initialize filters, must be preceded by OpenGL context creation
|
||||
if (!ps->o.experimental_backends && !init_render(ps)) {
|
||||
log_fatal("Failed to initialize the backend");
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdio.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "backend/driver.h"
|
||||
#include "diagnostic.h"
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
|
@ -21,6 +22,8 @@ void print_diagnostics(session_t *ps, const char *config_file) {
|
|||
printf("* Fast Math: Yes\n");
|
||||
#endif
|
||||
printf("* Config file used: %s\n", config_file ?: "None");
|
||||
printf("\n### Drivers (inaccurate):\n\n");
|
||||
print_drivers(ps->drivers);
|
||||
}
|
||||
|
||||
// vim: set noet sw=8 ts=8 :
|
||||
|
|
Loading…
Reference in New Issue