mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-12-15 08:56:26 -05:00
backend/x11: switch to wlr_swapchain
This commit is contained in:
parent
16a51bbab2
commit
d79a00bf02
4 changed files with 413 additions and 34 deletions
|
|
@ -6,12 +6,16 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <wlr/config.h>
|
||||
|
||||
#include <drm_fourcc.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri3.h>
|
||||
#include <xcb/present.h>
|
||||
#include <xcb/xfixes.h>
|
||||
#include <xcb/xinput.h>
|
||||
|
||||
|
|
@ -25,8 +29,26 @@
|
|||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/x11.h"
|
||||
#include "render/drm_format_set.h"
|
||||
#include "render/gbm_allocator.h"
|
||||
#include "render/wlr_renderer.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
// See dri2_format_for_depth in mesa
|
||||
const struct wlr_x11_format formats[] = {
|
||||
{ .drm = DRM_FORMAT_XRGB8888, .depth = 24, .bpp = 32 },
|
||||
{ .drm = DRM_FORMAT_ARGB8888, .depth = 32, .bpp = 32 },
|
||||
};
|
||||
|
||||
static const struct wlr_x11_format *x11_format_from_depth(uint8_t depth) {
|
||||
for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) {
|
||||
if (formats[i].depth == depth) {
|
||||
return &formats[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_x11_output *get_x11_output_from_window_id(
|
||||
struct wlr_x11_backend *x11, xcb_window_t window) {
|
||||
struct wlr_x11_output *output;
|
||||
|
|
@ -82,6 +104,8 @@ static void handle_x11_event(struct wlr_x11_backend *x11,
|
|||
xcb_ge_generic_event_t *ev = (xcb_ge_generic_event_t *)event;
|
||||
if (ev->extension == x11->xinput_opcode) {
|
||||
handle_x11_xinput_event(x11, ev);
|
||||
} else if (ev->extension == x11->present_opcode) {
|
||||
handle_x11_present_event(x11, ev);
|
||||
} else {
|
||||
handle_x11_unknown_event(x11, event);
|
||||
}
|
||||
|
|
@ -157,6 +181,7 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
|
||||
wlr_renderer_destroy(x11->renderer);
|
||||
wlr_egl_finish(&x11->egl);
|
||||
free(x11->drm_format);
|
||||
|
||||
#if WLR_HAS_XCB_ERRORS
|
||||
xcb_errors_context_free(x11->errors_context);
|
||||
|
|
@ -190,6 +215,27 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
|||
backend_destroy(&x11->backend);
|
||||
}
|
||||
|
||||
static xcb_depth_t *get_depth(xcb_screen_t *screen, uint8_t depth) {
|
||||
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
|
||||
while (iter.rem > 0) {
|
||||
if (iter.data->depth == depth) {
|
||||
return iter.data;
|
||||
}
|
||||
xcb_depth_next(&iter);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static xcb_visualid_t pick_visualid(xcb_depth_t *depth) {
|
||||
xcb_visualtype_t *visuals = xcb_depth_visuals(depth);
|
||||
for (int i = 0; i < xcb_depth_visuals_length(depth); i++) {
|
||||
if (visuals[i]._class == XCB_VISUAL_CLASS_TRUE_COLOR) {
|
||||
return visuals[i].visual_id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
||||
const char *x11_display,
|
||||
wlr_renderer_create_func_t create_renderer_func) {
|
||||
|
|
@ -247,6 +293,47 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
|||
|
||||
const xcb_query_extension_reply_t *ext;
|
||||
|
||||
// DRI3 extension
|
||||
|
||||
ext = xcb_get_extension_data(x11->xcb, &xcb_dri3_id);
|
||||
if (!ext || !ext->present) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support DRI3 extension");
|
||||
goto error_display;
|
||||
}
|
||||
|
||||
xcb_dri3_query_version_cookie_t dri3_cookie =
|
||||
xcb_dri3_query_version(x11->xcb, 1, 2);
|
||||
xcb_dri3_query_version_reply_t *dri3_reply =
|
||||
xcb_dri3_query_version_reply(x11->xcb, dri3_cookie, NULL);
|
||||
if (!dri3_reply || dri3_reply->major_version < 1 ||
|
||||
dri3_reply->minor_version < 2) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support required DRI3 version");
|
||||
goto error_display;
|
||||
}
|
||||
free(dri3_reply);
|
||||
|
||||
// Present extension
|
||||
|
||||
ext = xcb_get_extension_data(x11->xcb, &xcb_present_id);
|
||||
if (!ext || !ext->present) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support Present extension");
|
||||
goto error_display;
|
||||
}
|
||||
x11->present_opcode = ext->major_opcode;
|
||||
|
||||
xcb_present_query_version_cookie_t present_cookie =
|
||||
xcb_present_query_version(x11->xcb, 1, 2);
|
||||
xcb_present_query_version_reply_t *present_reply =
|
||||
xcb_present_query_version_reply(x11->xcb, present_cookie, NULL);
|
||||
if (!present_reply || present_reply->major_version < 1) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support required Present version");
|
||||
free(present_reply);
|
||||
goto error_display;
|
||||
}
|
||||
free(present_reply);
|
||||
|
||||
// Xfixes extension
|
||||
|
||||
ext = xcb_get_extension_data(x11->xcb, &xcb_xfixes_id);
|
||||
if (!ext || !ext->present) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support Xfixes extension");
|
||||
|
|
@ -265,6 +352,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
|||
}
|
||||
free(fixes_reply);
|
||||
|
||||
// Xinput extension
|
||||
|
||||
ext = xcb_get_extension_data(x11->xcb, &xcb_input_id);
|
||||
if (!ext || !ext->present) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support Xinput extension");
|
||||
|
|
@ -295,6 +384,32 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
|||
wl_event_source_check(x11->event_source);
|
||||
|
||||
x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb)).data;
|
||||
if (!x11->screen) {
|
||||
wlr_log(WLR_ERROR, "Failed to get X11 screen");
|
||||
goto error_display;
|
||||
}
|
||||
|
||||
x11->depth = get_depth(x11->screen, 32);
|
||||
if (!x11->depth) {
|
||||
wlr_log(WLR_ERROR, "Failed to get 32-bit depth for X11 screen");
|
||||
goto error_display;
|
||||
}
|
||||
|
||||
x11->visualid = pick_visualid(x11->depth);
|
||||
if (!x11->visualid) {
|
||||
wlr_log(WLR_ERROR, "Failed to pick X11 visual");
|
||||
goto error_display;
|
||||
}
|
||||
|
||||
x11->x11_format = x11_format_from_depth(x11->depth->depth);
|
||||
if (!x11->x11_format) {
|
||||
wlr_log(WLR_ERROR, "Unsupported depth %"PRIu8, x11->depth->depth);
|
||||
goto error_display;
|
||||
}
|
||||
|
||||
x11->colormap = xcb_generate_id(x11->xcb);
|
||||
xcb_create_colormap(x11->xcb, XCB_COLORMAP_ALLOC_NONE, x11->colormap,
|
||||
x11->screen->root, x11->visualid);
|
||||
|
||||
if (!create_renderer_func) {
|
||||
create_renderer_func = wlr_renderer_autocreate;
|
||||
|
|
@ -306,18 +421,53 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
|||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_ALPHA_SIZE, 0,
|
||||
EGL_ALPHA_SIZE, 1,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
x11->renderer = create_renderer_func(&x11->egl, EGL_PLATFORM_X11_KHR,
|
||||
x11->xlib_conn, config_attribs, x11->screen->root_visual);
|
||||
|
||||
if (x11->renderer == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create renderer");
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
// TODO: we can use DRI3Open instead
|
||||
int drm_fd = wlr_renderer_get_drm_fd(x11->renderer);
|
||||
if (fd < 0) {
|
||||
wlr_log(WLR_ERROR, "Failed to get DRM device FD from renderer");
|
||||
return false;
|
||||
}
|
||||
|
||||
drm_fd = dup(drm_fd);
|
||||
if (fd < 0) {
|
||||
wlr_log_errno(WLR_ERROR, "dup failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_gbm_allocator *alloc = wlr_gbm_allocator_create(drm_fd);
|
||||
if (alloc == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create GBM allocator");
|
||||
return false;
|
||||
}
|
||||
x11->allocator = &alloc->base;
|
||||
|
||||
const struct wlr_drm_format_set *formats =
|
||||
wlr_renderer_get_dmabuf_render_formats(x11->renderer);
|
||||
if (formats == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to get available DMA-BUF formats from renderer");
|
||||
return false;
|
||||
}
|
||||
const struct wlr_drm_format *format =
|
||||
wlr_drm_format_set_get(formats, x11->x11_format->drm);
|
||||
if (format == NULL) {
|
||||
wlr_log(WLR_ERROR, "Renderer doesn't support DRM format 0x%"PRIX32,
|
||||
x11->x11_format->drm);
|
||||
return false;
|
||||
}
|
||||
// TODO intersect modifiers with DRI3GetSupportedModifiers
|
||||
x11->drm_format = wlr_drm_format_dup(format);
|
||||
|
||||
#if WLR_HAS_XCB_ERRORS
|
||||
if (xcb_errors_context_new(x11->xcb, &x11->errors_context) != 0) {
|
||||
wlr_log(WLR_ERROR, "Failed to create error context");
|
||||
|
|
@ -325,6 +475,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
|||
}
|
||||
#endif
|
||||
|
||||
x11->present_event_id = xcb_generate_id(x11->xcb);
|
||||
|
||||
wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD,
|
||||
&input_device_impl, "X11 keyboard", 0, 0);
|
||||
wlr_keyboard_init(&x11->keyboard, &keyboard_impl);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue