aboutsummaryrefslogtreecommitdiff
path: root/backend/drm/drm.c
diff options
context:
space:
mode:
authornyorain <nyorain@gmail.com>2017-06-19 17:49:26 +0200
committernyorain <nyorain@gmail.com>2017-06-19 17:49:26 +0200
commit41a477375cf5fc2cfafc97fb6d98e4e3457dfa62 (patch)
tree93e318287fb70b21dd0f5d7f90551810fa85a7dd /backend/drm/drm.c
parent904739c40596cb4e9e9d48c89b1d864051237441 (diff)
parent7e038a6110501a51e7f3d3366e8bc54a02766f22 (diff)
Merge branch 'libinput' into wayland-backend
Diffstat (limited to 'backend/drm/drm.c')
-rw-r--r--backend/drm/drm.c92
1 files changed, 85 insertions, 7 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index d6a3f8a2..00b45bce 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,59 @@ 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;
+ }
+ }
+}
+
+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 +342,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 +512,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 +597,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;