Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

output: take a wlr_buffer in set_cursor #2507

Merged
merged 7 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 42 additions & 73 deletions backend/drm/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#include "backend/drm/iface.h"
#include "backend/drm/util.h"
#include "render/pixel_format.h"
#include "render/drm_format_set.h"
#include "render/swapchain.h"
#include "render/wlr_renderer.h"
#include "types/wlr_buffer.h"
#include "util/signal.h"

Expand Down Expand Up @@ -329,7 +331,7 @@ static bool drm_connector_attach_render(struct wlr_output *output,
static void drm_plane_set_committed(struct wlr_drm_plane *plane) {
drm_fb_move(&plane->queued_fb, &plane->pending_fb);

if (plane->queued_fb) {
if (plane->queued_fb && plane->surf.swapchain) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random bugfix?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously all planes had a swapchain. Now that the cursor plane swapchain has been moved in common code in wlr_output.c, the cursor plane no longer has a swapchain.

wlr_swapchain_set_buffer_submitted(plane->surf.swapchain,
plane->queued_fb->wlr_buf);
}
Expand Down Expand Up @@ -834,9 +836,7 @@ struct wlr_output_mode *wlr_drm_connector_add_mode(struct wlr_output *output,
}

static bool drm_connector_set_cursor(struct wlr_output *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_buffer *buffer, int hotspot_x, int hotspot_y) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
struct wlr_drm_backend *drm = conn->backend;
struct wlr_drm_crtc *crtc = conn->crtc;
Expand All @@ -850,90 +850,59 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
return false;
}

if (!plane->surf.swapchain) {
int ret;
uint64_t w, h;
ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &w);
w = ret ? 64 : w;
ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h);
h = ret ? 64 : h;

if (!drm_plane_init_surface(plane, drm, w, h, true)) {
wlr_drm_conn_log(conn, WLR_ERROR, "Cannot allocate cursor resources");
return false;
}
}

struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
wlr_box_transform(&hotspot, &hotspot,
wlr_output_transform_invert(output->transform),
plane->surf.width, plane->surf.height);

if (plane->cursor_hotspot_x != hotspot.x ||
plane->cursor_hotspot_y != hotspot.y) {
if (plane->cursor_hotspot_x != hotspot_x ||
plane->cursor_hotspot_y != hotspot_y) {
// Update cursor hotspot
conn->cursor_x -= hotspot.x - plane->cursor_hotspot_x;
conn->cursor_y -= hotspot.y - plane->cursor_hotspot_y;
plane->cursor_hotspot_x = hotspot.x;
plane->cursor_hotspot_y = hotspot.y;
conn->cursor_x -= hotspot_x - plane->cursor_hotspot_x;
conn->cursor_y -= hotspot_y - plane->cursor_hotspot_y;
plane->cursor_hotspot_x = hotspot_x;
plane->cursor_hotspot_y = hotspot_y;

wlr_output_update_needs_frame(output);
}

if (!update_texture) {
// Don't update cursor image
return true;
}

plane->cursor_enabled = false;
if (texture != NULL) {
int width = texture->width * output->scale / scale;
int height = texture->height * output->scale / scale;

if (width > (int)plane->surf.width || height > (int)plane->surf.height) {
wlr_drm_conn_log(conn, WLR_ERROR, "Cursor too large (max %dx%d)",
(int)plane->surf.width, (int)plane->surf.height);
return false;
}

if (!drm_surface_make_current(&plane->surf, NULL)) {
if (buffer != NULL) {
if ((uint64_t)buffer->width != drm->cursor_width ||
(uint64_t)buffer->height != drm->cursor_height) {
wlr_drm_conn_log(conn, WLR_DEBUG, "Cursor buffer size mismatch");
return false;
}

struct wlr_renderer *rend = plane->surf.renderer->wlr_rend;

struct wlr_box cursor_box = { .width = width, .height = height };
struct wlr_buffer *local_buf;
if (drm->parent) {
struct wlr_drm_format *format =
drm_plane_pick_render_format(plane, &drm->renderer);
if (format == NULL) {
wlr_log(WLR_ERROR, "Failed to pick cursor plane format");
return false;
}

float output_matrix[9];
wlr_matrix_identity(output_matrix);
if (output->transform != WL_OUTPUT_TRANSFORM_NORMAL) {
struct wlr_box tr_size = {
.width = plane->surf.width,
.height = plane->surf.height,
};
wlr_box_transform(&tr_size, &tr_size, output->transform, 0, 0);
bool ok = init_drm_surface(&plane->mgpu_surf, &drm->renderer,
buffer->width, buffer->height, format);
free(format);
if (!ok) {
return false;
}

wlr_matrix_translate(output_matrix, plane->surf.width / 2.0,
plane->surf.height / 2.0);
wlr_matrix_transform(output_matrix, output->transform);
wlr_matrix_translate(output_matrix, - tr_size.width / 2.0,
- tr_size.height / 2.0);
local_buf = drm_surface_blit(&plane->mgpu_surf, buffer);
if (local_buf == NULL) {
return false;
}
} else {
local_buf = wlr_buffer_lock(buffer);
}

float matrix[9];
wlr_matrix_project_box(matrix, &cursor_box, transform, 0,
output_matrix);

wlr_renderer_begin(rend, plane->surf.width, plane->surf.height);
wlr_renderer_clear(rend, (float[]){ 0.0, 0.0, 0.0, 0.0 });
wlr_render_texture_with_matrix(rend, texture, matrix, 1.0);
wlr_renderer_end(rend);

if (!drm_plane_lock_surface(plane, drm)) {
bool ok = drm_fb_import(&plane->pending_fb, drm, local_buf,
&plane->formats);
wlr_buffer_unlock(local_buf);
if (!ok) {
return false;
}

plane->cursor_enabled = true;
plane->cursor_width = buffer->width;
plane->cursor_height = buffer->height;
}

wlr_output_update_needs_frame(output);
Expand Down Expand Up @@ -977,8 +946,8 @@ bool drm_connector_is_cursor_visible(struct wlr_drm_connector *conn) {
return plane->cursor_enabled &&
conn->cursor_x < conn->output.width &&
conn->cursor_y < conn->output.height &&
conn->cursor_x + (int)plane->surf.width >= 0 &&
conn->cursor_y + (int)plane->surf.height >= 0;
conn->cursor_x + plane->cursor_width >= 0 &&
conn->cursor_y + plane->cursor_height >= 0;
}

static void dealloc_crtc(struct wlr_drm_connector *conn);
Expand Down
6 changes: 3 additions & 3 deletions backend/drm/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void finish_drm_renderer(struct wlr_drm_renderer *renderer) {
gbm_device_destroy(renderer->gbm);
}

static bool init_drm_surface(struct wlr_drm_surface *surf,
bool init_drm_surface(struct wlr_drm_surface *surf,
struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height,
const struct wlr_drm_format *drm_format) {
if (surf->width == width && surf->height == height) {
Expand Down Expand Up @@ -126,7 +126,7 @@ void drm_surface_unset_current(struct wlr_drm_surface *surf) {
surf->back_buffer = NULL;
}

static struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
struct wlr_buffer *buffer) {
struct wlr_renderer *renderer = surf->renderer->wlr_rend;

Expand Down Expand Up @@ -191,7 +191,7 @@ static struct wlr_drm_format *create_linear_format(uint32_t format) {
return fmt;
}

static struct wlr_drm_format *drm_plane_pick_render_format(
struct wlr_drm_format *drm_plane_pick_render_format(
struct wlr_drm_plane *plane, struct wlr_drm_renderer *renderer) {
const struct wlr_drm_format_set *render_formats =
wlr_renderer_get_render_formats(renderer->wlr_rend);
Expand Down
81 changes: 4 additions & 77 deletions backend/wayland/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,87 +406,20 @@ static void output_rollback_render(struct wlr_output *wlr_output) {
}

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_buffer *wlr_buffer, int hotspot_x, int hotspot_y) {
struct wlr_wl_output *output = get_wl_output_from_output(wlr_output);
struct wlr_wl_backend *backend = output->backend;
struct wlr_renderer *renderer = wlr_backend_get_renderer(&backend->backend);
struct wlr_allocator *allocator = backend_get_allocator(&backend->backend);

struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
wlr_box_transform(&hotspot, &hotspot,
wlr_output_transform_invert(wlr_output->transform),
output->cursor.width, output->cursor.height);

// TODO: use output->wlr_output.transform to transform pixels and hotpot
output->cursor.hotspot_x = hotspot.x;
output->cursor.hotspot_y = hotspot.y;

if (!update_texture) {
// Update hotspot without changing cursor image
update_wl_output_cursor(output);
return true;
}
output->cursor.hotspot_x = hotspot_x;
output->cursor.hotspot_y = hotspot_y;

if (output->cursor.surface == NULL) {
output->cursor.surface =
wl_compositor_create_surface(backend->compositor);
}
struct wl_surface *surface = output->cursor.surface;

if (texture != NULL) {
int width = texture->width * wlr_output->scale / scale;
int height = texture->height * wlr_output->scale / scale;

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(allocator,
width, height, output->backend->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(renderer, wlr_buffer)) {
return false;
}

struct wlr_box cursor_box = {
.width = width,
.height = height,
};

float output_matrix[9];
wlr_matrix_identity(output_matrix);
if (wlr_output->transform != WL_OUTPUT_TRANSFORM_NORMAL) {
struct wlr_box tr_size = { .width = width, .height = height };
wlr_box_transform(&tr_size, &tr_size, wlr_output->transform, 0, 0);

wlr_matrix_translate(output_matrix, width / 2.0, height / 2.0);
wlr_matrix_transform(output_matrix, wlr_output->transform);
wlr_matrix_translate(output_matrix,
- tr_size.width / 2.0, - tr_size.height / 2.0);
}

float matrix[9];
wlr_matrix_project_box(matrix, &cursor_box, transform, 0, output_matrix);

wlr_renderer_begin(renderer, width, height);
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0);
wlr_renderer_end(renderer);

wlr_renderer_bind_buffer(renderer, NULL);

if (wlr_buffer != NULL) {
struct wlr_wl_buffer *buffer =
get_or_create_wl_buffer(output->backend, wlr_buffer);
if (buffer == NULL) {
Expand All @@ -496,11 +429,6 @@ static bool output_set_cursor(struct wlr_output *wlr_output,
wl_surface_attach(surface, buffer->wl_buffer, 0, 0);
wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(surface);

wlr_buffer_unlock(wlr_buffer);

output->cursor.width = width;
output->cursor.height = height;
} else {
wl_surface_attach(surface, NULL, 0, 0);
wl_surface_commit(surface);
Expand Down Expand Up @@ -530,7 +458,6 @@ static void output_destroy(struct wlr_output *wlr_output) {

wl_list_remove(&output->link);

wlr_swapchain_destroy(output->cursor.swapchain);
if (output->cursor.surface) {
wl_surface_destroy(output->cursor.surface);
}
Expand Down
Loading