parent
8ad078f46f
commit
ef94e7e847
|
@ -11,6 +11,7 @@ packages:
|
||||||
- wayland-dev
|
- wayland-dev
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- xcb-util-image-dev
|
- xcb-util-image-dev
|
||||||
|
- xcb-util-renderutil-dev
|
||||||
- xcb-util-wm-dev
|
- xcb-util-wm-dev
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/swaywm/wlroots
|
- https://github.com/swaywm/wlroots
|
||||||
|
|
|
@ -11,6 +11,7 @@ packages:
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- xcb-util-errors
|
- xcb-util-errors
|
||||||
- xcb-util-image
|
- xcb-util-image
|
||||||
|
- xcb-util-renderutil
|
||||||
- xcb-util-wm
|
- xcb-util-wm
|
||||||
- seatd
|
- seatd
|
||||||
sources:
|
sources:
|
||||||
|
|
|
@ -18,6 +18,7 @@ packages:
|
||||||
- x11/libxkbcommon
|
- x11/libxkbcommon
|
||||||
- x11/pixman
|
- x11/pixman
|
||||||
- x11/xcb-util-errors
|
- x11/xcb-util-errors
|
||||||
|
- x11/xcb-util-renderutil
|
||||||
- x11/xcb-util-wm
|
- x11/xcb-util-wm
|
||||||
- sysutils/seatd
|
- sysutils/seatd
|
||||||
- gmake
|
- gmake
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/dri3.h>
|
#include <xcb/dri3.h>
|
||||||
#include <xcb/present.h>
|
#include <xcb/present.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
|
#include <xcb/xcb_renderutil.h>
|
||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
#include <xcb/xinput.h>
|
#include <xcb/xinput.h>
|
||||||
|
|
||||||
|
@ -355,6 +357,29 @@ static bool query_dri3_formats(struct wlr_x11_backend *x11) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void x11_get_argb32(struct wlr_x11_backend *x11) {
|
||||||
|
xcb_render_query_pict_formats_cookie_t cookie =
|
||||||
|
xcb_render_query_pict_formats(x11->xcb);
|
||||||
|
xcb_render_query_pict_formats_reply_t *reply =
|
||||||
|
xcb_render_query_pict_formats_reply(x11->xcb, cookie, NULL);
|
||||||
|
if (!reply) {
|
||||||
|
wlr_log(WLR_ERROR, "Did not get any reply from xcb_render_query_pict_formats");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_render_pictforminfo_t *format =
|
||||||
|
xcb_render_util_find_standard_format(reply, XCB_PICT_STANDARD_ARGB_32);
|
||||||
|
|
||||||
|
if (format == NULL) {
|
||||||
|
wlr_log(WLR_DEBUG, "No ARGB_32 render format");
|
||||||
|
free(reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x11->argb32 = format->id;
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
||||||
const char *x11_display) {
|
const char *x11_display) {
|
||||||
wlr_log(WLR_INFO, "Creating X11 backend");
|
wlr_log(WLR_INFO, "Creating X11 backend");
|
||||||
|
@ -629,13 +654,15 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
||||||
xcb_rectangle_t rect = { .x = 0, .y = 0, .width = 1, .height = 1 };
|
xcb_rectangle_t rect = { .x = 0, .y = 0, .width = 1, .height = 1 };
|
||||||
xcb_poly_fill_rectangle(x11->xcb, blank, gc, 1, &rect);
|
xcb_poly_fill_rectangle(x11->xcb, blank, gc, 1, &rect);
|
||||||
|
|
||||||
x11->cursor = xcb_generate_id(x11->xcb);
|
x11->transparent_cursor = xcb_generate_id(x11->xcb);
|
||||||
xcb_create_cursor(x11->xcb, x11->cursor, blank, blank,
|
xcb_create_cursor(x11->xcb, x11->transparent_cursor, blank, blank,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0);
|
0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
xcb_free_gc(x11->xcb, gc);
|
xcb_free_gc(x11->xcb, gc);
|
||||||
xcb_free_pixmap(x11->xcb, blank);
|
xcb_free_pixmap(x11->xcb, blank);
|
||||||
|
|
||||||
|
x11_get_argb32(x11);
|
||||||
|
|
||||||
return &x11->backend;
|
return &x11->backend;
|
||||||
|
|
||||||
error_event:
|
error_event:
|
||||||
|
|
|
@ -4,6 +4,8 @@ x11_required = [
|
||||||
'xcb',
|
'xcb',
|
||||||
'xcb-dri3',
|
'xcb-dri3',
|
||||||
'xcb-present',
|
'xcb-present',
|
||||||
|
'xcb-render',
|
||||||
|
'xcb-renderutil',
|
||||||
'xcb-xfixes',
|
'xcb-xfixes',
|
||||||
'xcb-xinput',
|
'xcb-xinput',
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,12 +7,14 @@
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
#include <xcb/dri3.h>
|
#include <xcb/dri3.h>
|
||||||
#include <xcb/present.h>
|
#include <xcb/present.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xinput.h>
|
#include <xcb/xinput.h>
|
||||||
|
|
||||||
#include <wlr/interfaces/wlr_output.h>
|
#include <wlr/interfaces/wlr_output.h>
|
||||||
#include <wlr/interfaces/wlr_pointer.h>
|
#include <wlr/interfaces/wlr_pointer.h>
|
||||||
#include <wlr/interfaces/wlr_touch.h>
|
#include <wlr/interfaces/wlr_touch.h>
|
||||||
|
#include <wlr/types/wlr_matrix.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
||||||
#include "backend/x11.h"
|
#include "backend/x11.h"
|
||||||
|
@ -79,6 +81,11 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
||||||
wl_list_remove(&output->link);
|
wl_list_remove(&output->link);
|
||||||
wlr_buffer_unlock(output->back_buffer);
|
wlr_buffer_unlock(output->back_buffer);
|
||||||
wlr_swapchain_destroy(output->swapchain);
|
wlr_swapchain_destroy(output->swapchain);
|
||||||
|
wlr_swapchain_destroy(output->cursor.swapchain);
|
||||||
|
if (output->cursor.pic != XCB_NONE) {
|
||||||
|
xcb_render_free_picture(x11->xcb, output->cursor.pic);
|
||||||
|
}
|
||||||
|
|
||||||
// A zero event mask deletes the event context
|
// A zero event mask deletes the event context
|
||||||
xcb_present_select_input(x11->xcb, output->present_event_id, output->win, 0);
|
xcb_present_select_input(x11->xcb, output->present_event_id, output->win, 0);
|
||||||
xcb_destroy_window(x11->xcb, output->win);
|
xcb_destroy_window(x11->xcb, output->win);
|
||||||
|
@ -336,12 +343,177 @@ static void output_rollback_render(struct wlr_output *wlr_output) {
|
||||||
wlr_renderer_bind_buffer(x11->renderer, NULL);
|
wlr_renderer_bind_buffer(x11->renderer, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_x11_output_cursor(struct wlr_x11_output *output,
|
||||||
|
int32_t hotspot_x, int32_t hotspot_y) {
|
||||||
|
struct wlr_x11_backend *x11 = output->x11;
|
||||||
|
|
||||||
|
xcb_cursor_t cursor = x11->transparent_cursor;
|
||||||
|
|
||||||
|
if (output->cursor.pic != XCB_NONE) {
|
||||||
|
cursor = xcb_generate_id(x11->xcb);
|
||||||
|
xcb_render_create_cursor(x11->xcb, cursor, output->cursor.pic,
|
||||||
|
hotspot_x, hotspot_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t values[] = {cursor};
|
||||||
|
xcb_change_window_attributes(x11->xcb, output->win,
|
||||||
|
XCB_CW_CURSOR, values);
|
||||||
|
xcb_flush(x11->xcb);
|
||||||
|
|
||||||
|
if (cursor != x11->transparent_cursor) {
|
||||||
|
xcb_free_cursor(x11->xcb, cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_cursor_to_picture(struct wlr_x11_output *output,
|
||||||
|
struct wlr_texture *texture, enum wl_output_transform transform,
|
||||||
|
int width, int height) {
|
||||||
|
struct wlr_x11_backend *x11 = output->x11;
|
||||||
|
int depth = 32;
|
||||||
|
int stride = width * 4;
|
||||||
|
|
||||||
|
if (output->cursor.pic != XCB_NONE) {
|
||||||
|
xcb_render_free_picture(x11->xcb, output->cursor.pic);
|
||||||
|
}
|
||||||
|
output->cursor.pic = XCB_NONE;
|
||||||
|
|
||||||
|
if (texture == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output->cursor.swapchain == NULL ||
|
||||||
|
output->cursor.swapchain->width != width ||
|
||||||
|
output->cursor.swapchain->height != height) {
|
||||||
|
wlr_swapchain_destroy(output->cursor.swapchain);
|
||||||
|
output->cursor.swapchain = wlr_swapchain_create(
|
||||||
|
x11->allocator, width, height,
|
||||||
|
x11->drm_format);
|
||||||
|
if (output->cursor.swapchain == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_buffer *wlr_buffer =
|
||||||
|
wlr_swapchain_acquire(output->cursor.swapchain, NULL);
|
||||||
|
if (wlr_buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wlr_renderer_bind_buffer(x11->renderer, wlr_buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data = malloc(width * height * 4);
|
||||||
|
if (data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_box cursor_box = {
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
|
float projection[9];
|
||||||
|
wlr_matrix_projection(projection, width, height, output->wlr_output.transform);
|
||||||
|
|
||||||
|
float matrix[9];
|
||||||
|
wlr_matrix_project_box(matrix, &cursor_box, transform, 0, projection);
|
||||||
|
|
||||||
|
wlr_renderer_begin(x11->renderer, width, height);
|
||||||
|
wlr_renderer_clear(x11->renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
||||||
|
wlr_render_texture_with_matrix(x11->renderer, texture, matrix, 1.0);
|
||||||
|
wlr_renderer_end(x11->renderer);
|
||||||
|
|
||||||
|
bool result = wlr_renderer_read_pixels(
|
||||||
|
x11->renderer, WL_SHM_FORMAT_ARGB8888, NULL,
|
||||||
|
width * 4, width, height, 0, 0, 0, 0,
|
||||||
|
data);
|
||||||
|
|
||||||
|
wlr_renderer_bind_buffer(x11->renderer, NULL);
|
||||||
|
|
||||||
|
wlr_buffer_unlock(wlr_buffer);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
free(data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_pixmap_t pix = xcb_generate_id(x11->xcb);
|
||||||
|
xcb_create_pixmap(x11->xcb, depth, pix, output->win,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
output->cursor.pic = xcb_generate_id(x11->xcb);
|
||||||
|
xcb_render_create_picture(x11->xcb, output->cursor.pic,
|
||||||
|
pix, x11->argb32, 0, 0);
|
||||||
|
|
||||||
|
xcb_gcontext_t gc = xcb_generate_id(x11->xcb);
|
||||||
|
xcb_create_gc(x11->xcb, gc, pix, 0, NULL);
|
||||||
|
|
||||||
|
xcb_put_image(x11->xcb, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||||
|
pix, gc, width, height, 0, 0, 0, depth,
|
||||||
|
stride * height * sizeof(uint8_t),
|
||||||
|
data);
|
||||||
|
free(data);
|
||||||
|
xcb_free_gc(x11->xcb, gc);
|
||||||
|
xcb_free_pixmap(x11->xcb, pix);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_set_cursor(struct wlr_output *wlr_output,
|
||||||
|
struct wlr_texture *texture, float scale,
|
||||||
|
enum wl_output_transform transform,
|
||||||
|
int32_t hotspot_x, int32_t hotspot_y, bool update_texture) {
|
||||||
|
struct wlr_x11_output *output = get_x11_output_from_output(wlr_output);
|
||||||
|
struct wlr_x11_backend *x11 = output->x11;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
|
||||||
|
if (x11->argb32 == XCB_NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture != NULL) {
|
||||||
|
width = texture->width * wlr_output->scale / scale;
|
||||||
|
height = texture->height * wlr_output->scale / scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
|
||||||
|
wlr_box_transform(&hotspot, &hotspot,
|
||||||
|
wlr_output_transform_invert(wlr_output->transform),
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
if (!update_texture) {
|
||||||
|
// This means we previously had a failure of some sort.
|
||||||
|
if (texture != NULL && output->cursor.pic == XCB_NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update hotspot without changing cursor image
|
||||||
|
update_x11_output_cursor(output, hotspot.x, hotspot.y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = output_cursor_to_picture(output, texture, transform,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
update_x11_output_cursor(output, hotspot.x, hotspot.y);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_move_cursor(struct wlr_output *_output, int x, int y) {
|
||||||
|
// TODO: only return true if x == current x and y == current y
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_output_impl output_impl = {
|
static const struct wlr_output_impl output_impl = {
|
||||||
.destroy = output_destroy,
|
.destroy = output_destroy,
|
||||||
.attach_render = output_attach_render,
|
.attach_render = output_attach_render,
|
||||||
.test = output_test,
|
.test = output_test,
|
||||||
.commit = output_commit,
|
.commit = output_commit,
|
||||||
.rollback_render = output_rollback_render,
|
.rollback_render = output_rollback_render,
|
||||||
|
.set_cursor = output_set_cursor,
|
||||||
|
.move_cursor = output_move_cursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
|
struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
|
||||||
|
@ -390,7 +562,7 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
|
||||||
0,
|
0,
|
||||||
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
||||||
x11->colormap,
|
x11->colormap,
|
||||||
x11->cursor,
|
x11->transparent_cursor,
|
||||||
};
|
};
|
||||||
output->win = xcb_generate_id(x11->xcb);
|
output->win = xcb_generate_id(x11->xcb);
|
||||||
xcb_create_window(x11->xcb, x11->depth->depth, output->win,
|
xcb_create_window(x11->xcb, x11->depth->depth, output->win,
|
||||||
|
|
|
@ -51,6 +51,11 @@ struct wlr_x11_output {
|
||||||
pixman_region32_t exposed;
|
pixman_region32_t exposed;
|
||||||
|
|
||||||
uint64_t last_msc;
|
uint64_t last_msc;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wlr_swapchain *swapchain;
|
||||||
|
xcb_render_picture_t pic;
|
||||||
|
} cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_x11_touchpoint {
|
struct wlr_x11_touchpoint {
|
||||||
|
@ -70,7 +75,8 @@ struct wlr_x11_backend {
|
||||||
xcb_depth_t *depth;
|
xcb_depth_t *depth;
|
||||||
xcb_visualid_t visualid;
|
xcb_visualid_t visualid;
|
||||||
xcb_colormap_t colormap;
|
xcb_colormap_t colormap;
|
||||||
xcb_cursor_t cursor;
|
xcb_cursor_t transparent_cursor;
|
||||||
|
xcb_render_pictformat_t argb32;
|
||||||
uint32_t dri3_major_version, dri3_minor_version;
|
uint32_t dri3_major_version, dri3_minor_version;
|
||||||
|
|
||||||
size_t requested_outputs;
|
size_t requested_outputs;
|
||||||
|
|
Loading…
Reference in New Issue