aboutsummaryrefslogtreecommitdiff
path: root/backend/drm/drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/drm/drm.c')
-rw-r--r--backend/drm/drm.c96
1 files changed, 89 insertions, 7 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index d6a3f8a2..befbfb94 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -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);
output->pageflip_pending = true;
- output->bo_last = output->bo_current;
- output->bo_current = bo;
+ output->bo[1] = output->bo[0];
+ output->bo[0] = bo;
}
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,
DRM_MODE_PAGE_FLIP_EVENT, output);
- output->bo_last = NULL;
- output->bo_current = bo;
+ output->bo[1] = NULL;
+ output->bo[0] = bo;
}
static bool display_init_renderer(struct wlr_drm_renderer *renderer,
@@ -280,6 +280,63 @@ static void wlr_drm_output_transform(struct wlr_output_state *output,
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;
+ }
+ if (!get_fb_for_bo(state->fd, output->cursor_bo[i])) {
+ wlr_log(L_ERROR, "Failed to create cursor fb");
+ 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) {
wlr_drm_output_cleanup(output, true);
free(output);
@@ -289,6 +346,8 @@ static struct wlr_output_impl output_impl = {
.enable = wlr_drm_output_enable,
.set_mode = wlr_drm_output_set_mode,
.transform = wlr_drm_output_transform,
+ .set_cursor = wlr_drm_output_set_cursor,
+ .move_cursor = wlr_drm_output_move_cursor,
.destroy = wlr_drm_output_destroy,
};
@@ -457,6 +516,29 @@ void wlr_drm_scan_connectors(struct wlr_backend_state *state) {
snprintf(wlr_output->name, sizeof(wlr_output->name), "%s-%"PRIu32,
conn_name[conn->connector_type],
conn->connector_type_id);
+ wlr_output->phys_width = conn->mmWidth;
+ wlr_output->phys_height = conn->mmHeight;
+ switch (conn->subpixel) {
+ case DRM_MODE_SUBPIXEL_UNKNOWN:
+ wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
+ break;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
+ wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
+ break;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
+ wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
+ break;
+ case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
+ wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
+ break;
+ case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
+ wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
+ break;
+ case DRM_MODE_SUBPIXEL_NONE:
+ default:
+ wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_NONE;
+ break;
+ }
drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id);
if (curr_enc) {
@@ -519,9 +601,9 @@ static void page_flip_handler(int fd, unsigned seq,
struct wlr_backend_state *state =
wl_container_of(output->renderer, state, renderer);
- if (output->bo_last) {
- gbm_surface_release_buffer(output->gbm, output->bo_last);
- output->bo_last = NULL;
+ if (output->bo[1]) {
+ gbm_surface_release_buffer(output->gbm, output->bo[1]);
+ output->bo[1] = NULL;
}
output->pageflip_pending = false;