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.c91
1 files changed, 51 insertions, 40 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index c6e29b86..618274a6 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -92,13 +92,13 @@ static uint32_t get_fb_for_bo(int fd, struct gbm_bo *bo) {
return *id;
}
-static void wlr_drm_output_begin(struct wlr_output_state *output) {
+static void wlr_drm_output_make_current(struct wlr_output_state *output) {
struct wlr_drm_renderer *renderer = output->renderer;
eglMakeCurrent(renderer->egl.display, output->egl,
output->egl, renderer->egl.context);
}
-static void wlr_drm_output_end(struct wlr_output_state *output) {
+static void wlr_drm_output_swap_buffers(struct wlr_output_state *output) {
struct wlr_drm_renderer *renderer = output->renderer;
if (!eglSwapBuffers(renderer->egl.display, output->egl)) {
@@ -207,10 +207,10 @@ static void wlr_drm_output_enable(struct wlr_output_state *output, bool enable)
DRM_MODE_DPMS_ON);
// Start rendering loop again by drawing a black frame
- wlr_drm_output_begin(output);
+ wlr_drm_output_make_current(output);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
- wlr_drm_output_end(output);
+ wlr_drm_output_swap_buffers(output);
} else {
drmModeConnectorSetProperty(state->fd, output->connector, output->props.dpms,
DRM_MODE_DPMS_STANDBY);
@@ -296,54 +296,65 @@ 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);
+ 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);
+
+ uint64_t bo_width, bo_height;
+ int ret;
+
+ ret = drmGetCap(state->fd, DRM_CAP_CURSOR_WIDTH, &bo_width);
+ bo_width = ret ? 64 : bo_width;
+ ret = drmGetCap(state->fd, DRM_CAP_CURSOR_HEIGHT, &bo_height);
+ bo_height = ret ? 64 : bo_height;
+
+ if (width > bo_width || height > bo_width) {
+ wlr_log(L_INFO, "Cursor too large (max %dx%d)", (int)bo_width, (int)bo_height);
+ return false;
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ if (output->cursor_bo[i]) {
+ continue;
+ }
+
+ output->cursor_bo[i] = gbm_bo_create(state->renderer.gbm, bo_width, bo_height,
+ GBM_FORMAT_RGBA8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
+
+ if (!output->cursor_bo[i]) {
+ wlr_log(L_ERROR, "Failed to create cursor bo");
+ return false;
+ }
+ }
+
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));
+
+ uint32_t bo_stride = gbm_bo_get_stride(bo);
+ uint8_t tmp[bo_stride * height];
+ memset(tmp, 0, sizeof(tmp));
+
for (size_t i = 0; i < height; ++i) {
- memcpy(_buf + i * width,
- buf + i * stride,
- width * 4);
+ memcpy(tmp + i * bo_stride, buf + i * stride * 4, width * 4);
}
- if (gbm_bo_write(bo, _buf, sizeof(_buf)) < 0) {
+
+ if (gbm_bo_write(bo, tmp, sizeof(tmp)) < 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);
+
+ uint32_t bo_handle = gbm_bo_get_handle(bo).u32;
+ if (drmModeSetCursor(state->fd, output->crtc, bo_handle, bo_width, bo_height)) {
+ wlr_log_errno(L_INFO, "Failed to set hardware cursor");
+ return false;
+ }
+
+ return true;
}
static bool wlr_drm_output_move_cursor(struct wlr_output_state *output,
@@ -365,6 +376,8 @@ static struct wlr_output_impl output_impl = {
.set_cursor = wlr_drm_output_set_cursor,
.move_cursor = wlr_drm_output_move_cursor,
.destroy = wlr_drm_output_destroy,
+ .make_current = wlr_drm_output_make_current,
+ .swap_buffers = wlr_drm_output_swap_buffers,
};
static int32_t calculate_refresh_rate(drmModeModeInfo *mode) {
@@ -625,9 +638,7 @@ static void page_flip_handler(int fd, unsigned seq,
output->pageflip_pending = false;
if (output->state == DRM_OUTPUT_CONNECTED && state->session->active) {
- wlr_drm_output_begin(output);
wl_signal_emit(&output->wlr_output->events.frame, output->wlr_output);
- wlr_drm_output_end(output);
}
}