From 2cdb646531d949e08b8a0538b05bd38af3157408 Mon Sep 17 00:00:00 2001 From: Markus Ongyerth Date: Mon, 29 Jan 2018 11:29:54 +0100 Subject: [PATCH 01/10] relases gbm buffers on init The wlr_drm_surface_init function is called (upon others) when the drm mode is changed. When the surface was used previously this replaced the gbm_surface, but did not replace the gbm buffers (front/back). With this, wlr_drm_surface_get_from never set up the new buffers with the new glViewport because surf->front existed. This frees the buffers to get new buffers on the new surface with the new viewport. --- backend/drm/renderer.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 00182c59..d28164aa 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -66,6 +66,17 @@ bool wlr_drm_surface_init(struct wlr_drm_surface *surf, surf->width = width; surf->height = height; + if (surf->gbm) { + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + surf->front = NULL; + } + if (surf->back) { + gbm_surface_release_buffer(surf->gbm, surf->back); + surf->back = NULL; + } + } + surf->gbm = gbm_surface_create(renderer->gbm, width, height, format, GBM_BO_USE_RENDERING | flags); if (!surf->gbm) { From cde0f454b376703e68662f9552b38fc10e97b74a Mon Sep 17 00:00:00 2001 From: Markus Ongyerth Date: Mon, 29 Jan 2018 11:49:31 +0100 Subject: [PATCH 02/10] Clean up the gbm/egl as well --- backend/drm/renderer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index d28164aa..350bfce4 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -75,6 +75,10 @@ bool wlr_drm_surface_init(struct wlr_drm_surface *surf, gbm_surface_release_buffer(surf->gbm, surf->back); surf->back = NULL; } + gbm_surface_destroy(surf->gbm); + } + if (surf->egl) { + eglDestroySurface(surf->renderer->egl.display, surf->egl); } surf->gbm = gbm_surface_create(renderer->gbm, width, height, From c5aac776929cd5abed96463b635f0382d3047fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 30 Jan 2018 16:06:45 +0100 Subject: [PATCH 03/10] Fix some typos Prefer initialize over initialise since used more often in the sources. --- backend/drm/backend.c | 2 +- backend/drm/drm.c | 6 +++--- meson.build | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index de69dad5..4ca5718a 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -119,7 +119,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, char *name = drmGetDeviceNameFromFd2(gpu_fd); drmVersion *version = drmGetVersion(gpu_fd); - wlr_log(L_INFO, "Initalizing DRM backend for %s (%s)", name, version->name); + wlr_log(L_INFO, "Initializing DRM backend for %s (%s)", name, version->name); free(name); drmFreeVersion(version); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 63a6e2da..cdd2f57e 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -469,7 +469,7 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, wlr_output_update_mode(&conn->output, mode); // Since realloc_crtcs can deallocate planes on OTHER outputs, - // we actually need to reinitalise any than has changed + // we actually need to reinitialize any than has changed ssize_t output_index = -1; wl_list_for_each(conn, &drm->outputs, link) { output_index += 1; @@ -483,7 +483,7 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, if (!wlr_drm_plane_surfaces_init(crtc->primary, drm, mode->width, mode->height, GBM_FORMAT_XRGB8888)) { - wlr_log(L_ERROR, "Failed to initalise renderer for plane"); + wlr_log(L_ERROR, "Failed to initialize renderer for plane"); goto error_conn; } @@ -949,7 +949,7 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { conn->possible_crtc = 0; /* Fallthrough */ case WLR_DRM_CONN_NEEDS_MODESET: - wlr_log(L_INFO, "Emmiting destruction signal for '%s'", + wlr_log(L_INFO, "Emitting destruction signal for '%s'", conn->output.name); wl_signal_emit(&drm->backend.events.output_remove, &conn->output); break; diff --git a/meson.build b/meson.build index 55b07efa..236abd6b 100644 --- a/meson.build +++ b/meson.build @@ -36,7 +36,7 @@ wlr_inc = include_directories('include') cc = meson.get_compiler('c') -# Clang complains about some zeroed initialiser lists (= {0}), even though they +# Clang complains about some zeroed initializer lists (= {0}), even though they # are valid if cc.get_id() == 'clang' add_project_arguments('-Wno-missing-field-initializers', language: 'c') From 4afc933ea4946e00977c18dbed5dea47ddf8b204 Mon Sep 17 00:00:00 2001 From: Markus Ongyerth Date: Wed, 31 Jan 2018 12:54:57 +0100 Subject: [PATCH 04/10] fixes 90 degree rotation screenshots This fixes the screenshot example application when an output is rotated by 90 degrees. Other tranformations are not taken into account yet. --- examples/screenshot.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/examples/screenshot.c b/examples/screenshot.c index ba225023..12892476 100644 --- a/examples/screenshot.c +++ b/examples/screenshot.c @@ -48,6 +48,7 @@ struct screenshooter_output { struct wl_output *output; struct wl_buffer *buffer; int width, height, offset_x, offset_y; + int transform; void *data; struct wl_list link; }; @@ -60,6 +61,7 @@ static void output_handle_geometry(void *data, struct wl_output *wl_output, if (wl_output == output->output) { output->offset_x = x; output->offset_y = y; + output->transform = transform; } } @@ -163,10 +165,21 @@ static void write_image(const char *filename, int width, int height) { void *d = data + (output->offset_y - min_y) * buffer_stride + (output->offset_x - min_x) * 4; - for (int i = 0; i < output->height; i++) { - memcpy(d, s, output_stride); - d += buffer_stride; - s += output_stride; + if (output->transform == WL_OUTPUT_TRANSFORM_90) { + uint32_t *ss = s; + uint32_t *sd = d; + for (int i = 0; i < output->width; ++i) { + for (int j = 0; j < output->height; ++j) { + sd[i * width + j] + = ss[j * output->width + (output->width - i)]; + } + } + } else { + for (int i = 0; i < output->height; i++) { + memcpy(d, s, output_stride); + d += buffer_stride; + s += output_stride; + } } free(output); @@ -211,15 +224,23 @@ static void write_image(const char *filename, int width, int height) { } static int set_buffer_size(int *width, int *height) { + int owidth, oheight; min_x = min_y = INT_MAX; max_x = max_y = INT_MIN; struct screenshooter_output *output; wl_list_for_each(output, &output_list, link) { + if (output->transform & 0x1) { + owidth = output->height; + oheight = output->width; + } else { + owidth = output->width; + oheight = output->height; + } min_x = MIN(min_x, output->offset_x); min_y = MIN(min_y, output->offset_y); - max_x = MAX(max_x, output->offset_x + output->width); - max_y = MAX(max_y, output->offset_y + output->height); + max_x = MAX(max_x, output->offset_x + owidth); + max_y = MAX(max_y, output->offset_y + oheight); } if (max_x <= min_x || max_y <= min_y) { From 3a404e4f8d722bb6fbde0bdcd9a560179f9a52c6 Mon Sep 17 00:00:00 2001 From: Markus Ongyerth Date: Wed, 31 Jan 2018 16:05:33 +0100 Subject: [PATCH 05/10] handle the other transformations for screenshots This handles all current transformations for outputs properly. This ensures an output is drawn in readable orientation/flipping no matter the actual transformations applied to it. --- examples/screenshot.c | 78 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/examples/screenshot.c b/examples/screenshot.c index 12892476..b305e56f 100644 --- a/examples/screenshot.c +++ b/examples/screenshot.c @@ -48,7 +48,7 @@ struct screenshooter_output { struct wl_output *output; struct wl_buffer *buffer; int width, height, offset_x, offset_y; - int transform; + enum wl_output_transform transform; void *data; struct wl_list link; }; @@ -161,25 +161,75 @@ static void write_image(const char *filename, int width, int height) { struct screenshooter_output *output, *next; wl_list_for_each_safe(output, next, &output_list, link) { int output_stride = output->width * 4; - void *s = output->data; - void *d = data + (output->offset_y - min_y) * buffer_stride + - (output->offset_x - min_x) * 4; + uint32_t *src = (uint32_t *)output->data; + uint32_t *dst = (uint32_t *)(data + + (output->offset_y - min_y) * buffer_stride + + (output->offset_x - min_x) * 4); - if (output->transform == WL_OUTPUT_TRANSFORM_90) { - uint32_t *ss = s; - uint32_t *sd = d; + switch (output->transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + for (int i = 0; i < output->height; i++) { + memcpy(dst, src, output_stride); + dst += width; + src += output->width; + } + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + for (int i = 0; i < output->height; ++i) { + for (int j = 0; j < output->width; ++j) { + dst[i * width + j] = + src[i * output->width + output->width - j]; + } + } + break; + case WL_OUTPUT_TRANSFORM_90: for (int i = 0; i < output->width; ++i) { for (int j = 0; j < output->height; ++j) { - sd[i * width + j] - = ss[j * output->width + (output->width - i)]; + dst[i * width + j] = + src[j * output->width + output->width - i]; } } - } else { - for (int i = 0; i < output->height; i++) { - memcpy(d, s, output_stride); - d += buffer_stride; - s += output_stride; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + for (int i = 0; i < output->width; ++i) { + for (int j = 0; j < output->height; ++j) { + dst[i * width + j] = + src[(output->height - j) * output->width + output->width - i]; + } + } + break; + case WL_OUTPUT_TRANSFORM_180: + for (int i = 0; i < output->height; ++i) { + for (int j = 0; j < output->width; ++j) { + dst[i * width + j] = + src[(output->height - i) * output->width + output->width - j]; + } + } + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + for (int i = 0; i < output->height; ++i) { + for (int j = 0; j < output->width; ++j) { + dst[i * width + j] = + src[(output->height - i) * output->width + j]; + } + } + break; + case WL_OUTPUT_TRANSFORM_270: + for (int i = 0; i < output->width; ++i) { + for (int j = 0; j < output->height; ++j) { + dst[i * width + j] = + src[(output->height - j) * output->width + i]; + } + } + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + for (int i = 0; i < output->width; ++i) { + for (int j = 0; j < output->height; ++j) { + dst[i * width + j] = + src[j * output->width + i]; + } } + break; } free(output); From 8eed857292cd5b473a07920b1a5698f1e641da22 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 1 Feb 2018 12:08:35 +0100 Subject: [PATCH 06/10] output: add destroy signal for wlr_output_cursor --- include/wlr/types/wlr_output.h | 4 ++++ types/wlr_output.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 55431ab1..9df2001e 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -29,6 +29,10 @@ struct wlr_output_cursor { struct wlr_surface *surface; struct wl_listener surface_commit; struct wl_listener surface_destroy; + + struct { + struct wl_signal destroy; + } events; }; struct wlr_output_impl; diff --git a/types/wlr_output.c b/types/wlr_output.c index 426926ac..2bdbbfee 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -694,6 +694,7 @@ struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) { return NULL; } cursor->output = output; + wl_signal_init(&cursor->events.destroy); wl_list_init(&cursor->surface_commit.link); cursor->surface_commit.notify = output_cursor_handle_commit; wl_list_init(&cursor->surface_destroy.link); @@ -707,6 +708,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) { return; } output_cursor_reset(cursor); + wl_signal_emit(&cursor->events.destroy, cursor); if (cursor->output->hardware_cursor == cursor) { // If this cursor was the hardware cursor, disable it if (cursor->output->impl->set_cursor) { From cd925f496c2e1f644de0ff7f79f7dce49759e769 Mon Sep 17 00:00:00 2001 From: Markus Ongyerth Date: Thu, 1 Feb 2018 21:36:14 +0100 Subject: [PATCH 07/10] fixes the off by one errors in examples/screenshot The inverse loop iterations for the transformed outputs had an off by one error, iterating 1 based, not 0 based. This commit fixes that. --- examples/screenshot.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/screenshot.c b/examples/screenshot.c index b305e56f..7de2ab8e 100644 --- a/examples/screenshot.c +++ b/examples/screenshot.c @@ -178,7 +178,7 @@ static void write_image(const char *filename, int width, int height) { for (int i = 0; i < output->height; ++i) { for (int j = 0; j < output->width; ++j) { dst[i * width + j] = - src[i * output->width + output->width - j]; + src[i * output->width + output->width - 1 - j]; } } break; @@ -186,7 +186,7 @@ static void write_image(const char *filename, int width, int height) { for (int i = 0; i < output->width; ++i) { for (int j = 0; j < output->height; ++j) { dst[i * width + j] = - src[j * output->width + output->width - i]; + src[j * output->width + output->width - 1 - i]; } } break; @@ -194,7 +194,7 @@ static void write_image(const char *filename, int width, int height) { for (int i = 0; i < output->width; ++i) { for (int j = 0; j < output->height; ++j) { dst[i * width + j] = - src[(output->height - j) * output->width + output->width - i]; + src[(output->height - 1 - j) * output->width + output->width - 1 - i]; } } break; @@ -202,7 +202,7 @@ static void write_image(const char *filename, int width, int height) { for (int i = 0; i < output->height; ++i) { for (int j = 0; j < output->width; ++j) { dst[i * width + j] = - src[(output->height - i) * output->width + output->width - j]; + src[(output->height - 1 - i) * output->width + output->width - 1 - j]; } } break; @@ -210,7 +210,7 @@ static void write_image(const char *filename, int width, int height) { for (int i = 0; i < output->height; ++i) { for (int j = 0; j < output->width; ++j) { dst[i * width + j] = - src[(output->height - i) * output->width + j]; + src[(output->height - 1 - i) * output->width + j]; } } break; @@ -218,7 +218,7 @@ static void write_image(const char *filename, int width, int height) { for (int i = 0; i < output->width; ++i) { for (int j = 0; j < output->height; ++j) { dst[i * width + j] = - src[(output->height - j) * output->width + i]; + src[(output->height - 1 - j) * output->width + i]; } } break; From 8cf622f0746c3d30774a9eace357eee1fb916db1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 1 Feb 2018 20:30:18 -0500 Subject: [PATCH 08/10] Improve xcursor docs --- include/wlr/types/wlr_xcursor_manager.h | 30 ++++++++++++++++--------- include/wlr/xcursor.h | 17 ++++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/include/wlr/types/wlr_xcursor_manager.h b/include/wlr/types/wlr_xcursor_manager.h index 2a2c9035..c7fa83be 100644 --- a/include/wlr/types/wlr_xcursor_manager.h +++ b/include/wlr/types/wlr_xcursor_manager.h @@ -6,7 +6,7 @@ #include /** - * A scaled XCursor theme. + * An XCursor theme at a particular scale factor of the base size. */ struct wlr_xcursor_manager_theme { float scale; @@ -15,11 +15,10 @@ struct wlr_xcursor_manager_theme { }; /** - * Manage multiple XCursor themes with different scales and set `wlr_cursor` - * images. - * - * This manager can be used to display cursor images on multiple outputs having - * different scale factors. + * wlr_xcursor_manager dynamically loads xcursor themes at sizes necessary for + * use on outputs at arbitrary scale factors. You should call + * wlr_xcursor_manager_load for each output you will show your cursor on, with + * the scale factor parameter set to that output's scale factor. */ struct wlr_xcursor_manager { char *name; @@ -28,24 +27,33 @@ struct wlr_xcursor_manager { }; /** - * Create a new XCursor manager. After initialization, scaled themes need to be - * loaded with `wlr_xcursor_manager_load`. `size` is the unscaled cursor theme - * size. + * Creates a new XCursor manager with the given xcursor theme name and base size + * (for use when scale=1). */ struct wlr_xcursor_manager *wlr_xcursor_manager_create(const char *name, uint32_t size); void wlr_xcursor_manager_destroy(struct wlr_xcursor_manager *manager); +/** + * Ensures an xcursor theme at the given scale factor is loaded in the manager. + */ int wlr_xcursor_manager_load(struct wlr_xcursor_manager *manager, float scale); +/** + * Retrieves a wlr_xcursor reference for the given cursor name at the given + * scale factor, or NULL if this wlr_xcursor_manager has not loaded a cursor + * theme at the requested scale. + */ struct wlr_xcursor *wlr_xcursor_manager_get_xcursor( struct wlr_xcursor_manager *manager, const char *name, float scale); /** - * Set a `wlr_cursor` image. The manager uses all currently loaded scaled - * themes. + * Set a wlr_cursor's cursor image to the specified cursor name for all scale + * factors. wlr_cursor will take over from this point and ensure the correct + * cursor is used on each output, assuming a wlr_output_layout is attached to + * it. */ void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager, const char *name, struct wlr_cursor *cursor); diff --git a/include/wlr/xcursor.h b/include/wlr/xcursor.h index 42fcedb9..c7c89e02 100644 --- a/include/wlr/xcursor.h +++ b/include/wlr/xcursor.h @@ -50,6 +50,9 @@ struct wlr_xcursor { uint32_t total_delay; /* length of the animation in ms */ }; +/** + * Contanier for an Xcursor theme. + */ struct wlr_xcursor_theme { unsigned int cursor_count; struct wlr_xcursor **cursors; @@ -57,13 +60,27 @@ struct wlr_xcursor_theme { int size; }; +/** + * Loads the named xcursor theme at the given cursor size (in pixels). This is + * useful if you need cursor images for your compositor to use when a + * client-side cursors is not available or you wish to override client-side + * cursors for a particular UI interaction (such as using a grab cursor when + * moving a window around). + */ struct wlr_xcursor_theme *wlr_xcursor_theme_load(const char *name, int size); void wlr_xcursor_theme_destroy(struct wlr_xcursor_theme *theme); +/** + * Obtains a wlr_xcursor image for the specified cursor name (e.g. "left_ptr"). + */ struct wlr_xcursor *wlr_xcursor_theme_get_cursor( struct wlr_xcursor_theme *theme, const char *name); +/** + * Returns the current frame number for an animated cursor give a monotonic time + * reference. + */ int wlr_xcursor_frame(struct wlr_xcursor *cursor, uint32_t time); /** From 39d5e78d37033d439e1eac9176e4e3bd8829f071 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 2 Feb 2018 08:48:01 -0500 Subject: [PATCH 09/10] Fix typo in xcursor.h --- include/wlr/xcursor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/wlr/xcursor.h b/include/wlr/xcursor.h index c7c89e02..d97469f8 100644 --- a/include/wlr/xcursor.h +++ b/include/wlr/xcursor.h @@ -51,7 +51,7 @@ struct wlr_xcursor { }; /** - * Contanier for an Xcursor theme. + * Container for an Xcursor theme. */ struct wlr_xcursor_theme { unsigned int cursor_count; From bb39277e9772b0943e8e292e2a7eed9c5aac59e2 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 2 Feb 2018 22:27:18 +0100 Subject: [PATCH 10/10] backend/drm: update output enabled property on modeset --- backend/drm/drm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index cdd2f57e..f6cc084e 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -207,6 +207,7 @@ static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { conn->pageflip_pending = true; + wlr_output_update_enabled(output, true); } else { wl_event_source_timer_update(conn->retry_pageflip, 1000.0f / conn->output.current_mode->refresh); @@ -245,6 +246,7 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, &mode->drm_mode)) { conn->pageflip_pending = true; + wlr_output_update_enabled(&conn->output, true); } else { wl_event_source_timer_update(conn->retry_pageflip, 1000.0f / conn->output.current_mode->refresh);