Add (broken) DRM hardware cursors
This commit is contained in:
parent
def3d7c64f
commit
7e038a6110
|
@ -112,8 +112,8 @@ static void wlr_drm_output_end(struct wlr_output_state *output) {
|
||||||
drmModePageFlip(renderer->fd, output->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output);
|
drmModePageFlip(renderer->fd, output->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output);
|
||||||
output->pageflip_pending = true;
|
output->pageflip_pending = true;
|
||||||
|
|
||||||
output->bo_last = output->bo_current;
|
output->bo[1] = output->bo[0];
|
||||||
output->bo_current = bo;
|
output->bo[0] = bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
|
void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
|
||||||
|
@ -141,8 +141,8 @@ void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
|
||||||
drmModePageFlip(renderer->fd, output->crtc, fb_id,
|
drmModePageFlip(renderer->fd, output->crtc, fb_id,
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, output);
|
DRM_MODE_PAGE_FLIP_EVENT, output);
|
||||||
|
|
||||||
output->bo_last = NULL;
|
output->bo[1] = NULL;
|
||||||
output->bo_current = bo;
|
output->bo[0] = bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool display_init_renderer(struct wlr_drm_renderer *renderer,
|
static bool display_init_renderer(struct wlr_drm_renderer *renderer,
|
||||||
|
@ -280,6 +280,59 @@ static void wlr_drm_output_transform(struct wlr_output_state *output,
|
||||||
output->wlr_output->transform = transform;
|
output->wlr_output->transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wlr_drm_cursor_bo_update(struct wlr_output_state *output,
|
||||||
|
uint32_t width, uint32_t height) {
|
||||||
|
if (output->cursor_width == width && output->cursor_height == height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wlr_log(L_DEBUG, "Allocating new cursor bos");
|
||||||
|
struct wlr_backend_state *state =
|
||||||
|
wl_container_of(output->renderer, state, renderer);
|
||||||
|
for (size_t i = 0; i < 2; ++i) {
|
||||||
|
output->cursor_bo[i] = gbm_bo_create(state->renderer.gbm,
|
||||||
|
width, height, GBM_FORMAT_ARGB8888,
|
||||||
|
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||||
|
if (!output->cursor_bo[i]) {
|
||||||
|
wlr_log(L_ERROR, "Failed to create cursor bo");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wlr_drm_output_set_cursor(struct wlr_output_state *output,
|
||||||
|
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) {
|
||||||
|
struct wlr_backend_state *state =
|
||||||
|
wl_container_of(output->renderer, state, renderer);
|
||||||
|
if (!buf) {
|
||||||
|
drmModeSetCursor(state->fd, output->crtc, 0, 0, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
wlr_drm_cursor_bo_update(output, width, height);
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
output->current_cursor ^= 1;
|
||||||
|
bo = output->cursor_bo[output->current_cursor];
|
||||||
|
uint32_t _buf[width * height];
|
||||||
|
memset(_buf, 0, sizeof(_buf));
|
||||||
|
for (size_t i = 0; i < height; ++i) {
|
||||||
|
memcpy(_buf + i * width,
|
||||||
|
buf + i * stride,
|
||||||
|
width * 4);
|
||||||
|
}
|
||||||
|
if (gbm_bo_write(bo, _buf, sizeof(_buf)) < 0) {
|
||||||
|
wlr_log(L_ERROR, "Failed to write cursor to bo");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !drmModeSetCursor(state->fd, output->crtc,
|
||||||
|
gbm_bo_get_handle(bo).s32, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wlr_drm_output_move_cursor(struct wlr_output_state *output,
|
||||||
|
int x, int y) {
|
||||||
|
struct wlr_backend_state *state =
|
||||||
|
wl_container_of(output->renderer, state, renderer);
|
||||||
|
return !drmModeMoveCursor(state->fd, output->crtc, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
static void wlr_drm_output_destroy(struct wlr_output_state *output) {
|
static void wlr_drm_output_destroy(struct wlr_output_state *output) {
|
||||||
wlr_drm_output_cleanup(output, true);
|
wlr_drm_output_cleanup(output, true);
|
||||||
free(output);
|
free(output);
|
||||||
|
@ -289,6 +342,8 @@ static struct wlr_output_impl output_impl = {
|
||||||
.enable = wlr_drm_output_enable,
|
.enable = wlr_drm_output_enable,
|
||||||
.set_mode = wlr_drm_output_set_mode,
|
.set_mode = wlr_drm_output_set_mode,
|
||||||
.transform = wlr_drm_output_transform,
|
.transform = wlr_drm_output_transform,
|
||||||
|
.set_cursor = wlr_drm_output_set_cursor,
|
||||||
|
.move_cursor = wlr_drm_output_move_cursor,
|
||||||
.destroy = wlr_drm_output_destroy,
|
.destroy = wlr_drm_output_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -480,8 +535,6 @@ void wlr_drm_scan_connectors(struct wlr_backend_state *state) {
|
||||||
wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_NONE;
|
wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
strcpy(wlr_output->make, "drm");
|
|
||||||
strcpy(wlr_output->model, "unknown");
|
|
||||||
|
|
||||||
drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id);
|
drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id);
|
||||||
if (curr_enc) {
|
if (curr_enc) {
|
||||||
|
@ -544,9 +597,9 @@ static void page_flip_handler(int fd, unsigned seq,
|
||||||
struct wlr_backend_state *state =
|
struct wlr_backend_state *state =
|
||||||
wl_container_of(output->renderer, state, renderer);
|
wl_container_of(output->renderer, state, renderer);
|
||||||
|
|
||||||
if (output->bo_last) {
|
if (output->bo[1]) {
|
||||||
gbm_surface_release_buffer(output->gbm, output->bo_last);
|
gbm_surface_release_buffer(output->gbm, output->bo[1]);
|
||||||
output->bo_last = NULL;
|
output->bo[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->pageflip_pending = false;
|
output->pageflip_pending = false;
|
||||||
|
|
4381
example/cat.c
4381
example/cat.c
File diff suppressed because it is too large
Load Diff
|
@ -92,6 +92,18 @@ static void handle_pointer_axis(struct pointer_state *pstate,
|
||||||
sizeof(sample->clear_color));
|
sizeof(sample->clear_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_output_add(struct output_state *ostate) {
|
||||||
|
struct wlr_output *wlr_output = ostate->output;
|
||||||
|
if (!wlr_output_set_cursor(wlr_output, cat_tex.pixel_data,
|
||||||
|
cat_tex.width * 4, cat_tex.width, cat_tex.height)) {
|
||||||
|
fprintf(stderr, "Failed to set cursor\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!wlr_output_move_cursor(wlr_output, 0, 0)) {
|
||||||
|
fprintf(stderr, "Failed to move cursor\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
struct sample_state state = {
|
struct sample_state state = {
|
||||||
.default_color = { 0.25f, 0.25f, 0.25f, 1 },
|
.default_color = { 0.25f, 0.25f, 0.25f, 1 },
|
||||||
|
@ -100,6 +112,7 @@ int main(int argc, char *argv[]) {
|
||||||
struct compositor_state compositor;
|
struct compositor_state compositor;
|
||||||
|
|
||||||
compositor_init(&compositor);
|
compositor_init(&compositor);
|
||||||
|
compositor.output_add_cb = handle_output_add;
|
||||||
compositor.output_frame_cb = handle_output_frame;
|
compositor.output_frame_cb = handle_output_frame;
|
||||||
compositor.keyboard_key_cb = handle_keyboard_key;
|
compositor.keyboard_key_cb = handle_keyboard_key;
|
||||||
compositor.pointer_motion_cb = handle_pointer_motion;
|
compositor.pointer_motion_cb = handle_pointer_motion;
|
||||||
|
@ -108,7 +121,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
state.renderer = wlr_gles3_renderer_init();
|
state.renderer = wlr_gles3_renderer_init();
|
||||||
state.cat_texture = wlr_render_surface_init(state.renderer);
|
state.cat_texture = wlr_render_surface_init(state.renderer);
|
||||||
wlr_surface_attach_pixels(state.cat_texture, GL_RGB,
|
wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
|
||||||
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||||
|
|
||||||
compositor.data = &state;
|
compositor.data = &state;
|
||||||
|
|
|
@ -205,7 +205,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
state.renderer = wlr_gles3_renderer_init();
|
state.renderer = wlr_gles3_renderer_init();
|
||||||
state.cat_texture = wlr_render_surface_init(state.renderer);
|
state.cat_texture = wlr_render_surface_init(state.renderer);
|
||||||
wlr_surface_attach_pixels(state.cat_texture, GL_RGB,
|
wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
|
||||||
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||||
|
|
||||||
compositor.data = &state;
|
compositor.data = &state;
|
||||||
|
|
|
@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
state.renderer = wlr_gles3_renderer_init();
|
state.renderer = wlr_gles3_renderer_init();
|
||||||
state.cat_texture = wlr_render_surface_init(state.renderer);
|
state.cat_texture = wlr_render_surface_init(state.renderer);
|
||||||
wlr_surface_attach_pixels(state.cat_texture, GL_RGB,
|
wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
|
||||||
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||||
|
|
||||||
compositor.data = &state;
|
compositor.data = &state;
|
||||||
|
|
|
@ -73,10 +73,12 @@ struct wlr_output_state {
|
||||||
drmModeCrtc *old_crtc;
|
drmModeCrtc *old_crtc;
|
||||||
|
|
||||||
struct wlr_drm_renderer *renderer;
|
struct wlr_drm_renderer *renderer;
|
||||||
struct gbm_surface *gbm;
|
|
||||||
struct gbm_bo *bo_last;
|
|
||||||
struct gbm_bo *bo_current;
|
|
||||||
EGLSurface *egl;
|
EGLSurface *egl;
|
||||||
|
struct gbm_surface *gbm;
|
||||||
|
struct gbm_bo *bo[2];
|
||||||
|
struct gbm_bo *cursor_bo[2];
|
||||||
|
int current_cursor;
|
||||||
|
uint32_t cursor_width, cursor_height;
|
||||||
|
|
||||||
bool pageflip_pending;
|
bool pageflip_pending;
|
||||||
bool cleanup;
|
bool cleanup;
|
||||||
|
|
|
@ -11,6 +11,9 @@ struct wlr_output_impl {
|
||||||
struct wlr_output_mode *mode);
|
struct wlr_output_mode *mode);
|
||||||
void (*transform)(struct wlr_output_state *state,
|
void (*transform)(struct wlr_output_state *state,
|
||||||
enum wl_output_transform transform);
|
enum wl_output_transform transform);
|
||||||
|
bool (*set_cursor)(struct wlr_output_state *state,
|
||||||
|
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height);
|
||||||
|
bool (*move_cursor)(struct wlr_output_state *state, int x, int y);
|
||||||
void (*destroy)(struct wlr_output_state *state);
|
void (*destroy)(struct wlr_output_state *state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ bool wlr_output_set_mode(struct wlr_output *output,
|
||||||
struct wlr_output_mode *mode);
|
struct wlr_output_mode *mode);
|
||||||
void wlr_output_transform(struct wlr_output *output,
|
void wlr_output_transform(struct wlr_output *output,
|
||||||
enum wl_output_transform transform);
|
enum wl_output_transform transform);
|
||||||
|
bool wlr_output_set_cursor(struct wlr_output *output,
|
||||||
|
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height);
|
||||||
|
bool wlr_output_move_cursor(struct wlr_output *output, int x, int y);
|
||||||
void wlr_output_destroy(struct wlr_output *output);
|
void wlr_output_destroy(struct wlr_output *output);
|
||||||
void wlr_output_effective_resolution(struct wlr_output *output,
|
void wlr_output_effective_resolution(struct wlr_output *output,
|
||||||
int *width, int *height);
|
int *width, int *height);
|
||||||
|
|
|
@ -91,6 +91,15 @@ void wlr_output_transform(struct wlr_output *output,
|
||||||
output->impl->transform(output->state, transform);
|
output->impl->transform(output->state, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wlr_output_set_cursor(struct wlr_output *output,
|
||||||
|
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) {
|
||||||
|
return output->impl->set_cursor(output->state, buf, stride, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_output_move_cursor(struct wlr_output *output, int x, int y) {
|
||||||
|
return output->impl->move_cursor(output->state, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
void wlr_output_destroy(struct wlr_output *output) {
|
void wlr_output_destroy(struct wlr_output *output) {
|
||||||
if (!output) return;
|
if (!output) return;
|
||||||
output->impl->destroy(output->state);
|
output->impl->destroy(output->state);
|
||||||
|
|
Loading…
Reference in New Issue