Merge remote-tracking branch 'upstream/master' into output-damage

This commit is contained in:
emersion 2018-02-03 00:15:44 +01:00
commit 3d3ea32137
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
9 changed files with 144 additions and 25 deletions

View file

@ -123,7 +123,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
char *name = drmGetDeviceNameFromFd2(gpu_fd); char *name = drmGetDeviceNameFromFd2(gpu_fd);
drmVersion *version = drmGetVersion(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); free(name);
drmFreeVersion(version); drmFreeVersion(version);

View file

@ -218,6 +218,7 @@ static bool wlr_drm_connector_swap_buffers(struct wlr_output *output) {
} }
conn->pageflip_pending = true; conn->pageflip_pending = true;
wlr_output_update_enabled(output, true);
return true; return true;
} }
@ -253,6 +254,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; 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)) { if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, &mode->drm_mode)) {
conn->pageflip_pending = true; conn->pageflip_pending = true;
wlr_output_update_enabled(&conn->output, true);
} else { } else {
wl_event_source_timer_update(conn->retry_pageflip, wl_event_source_timer_update(conn->retry_pageflip,
1000000.0f / conn->output.current_mode->refresh); 1000000.0f / conn->output.current_mode->refresh);
@ -477,7 +479,7 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output,
wlr_output_update_mode(&conn->output, mode); wlr_output_update_mode(&conn->output, mode);
// Since realloc_crtcs can deallocate planes on OTHER outputs, // 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; ssize_t output_index = -1;
wl_list_for_each(conn, &drm->outputs, link) { wl_list_for_each(conn, &drm->outputs, link) {
output_index += 1; output_index += 1;
@ -491,7 +493,7 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output,
if (!wlr_drm_plane_surfaces_init(crtc->primary, drm, if (!wlr_drm_plane_surfaces_init(crtc->primary, drm,
mode->width, mode->height, GBM_FORMAT_XRGB8888)) { 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; goto error_conn;
} }
@ -975,7 +977,7 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) {
conn->possible_crtc = 0; conn->possible_crtc = 0;
/* Fallthrough */ /* Fallthrough */
case WLR_DRM_CONN_NEEDS_MODESET: 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); conn->output.name);
wl_signal_emit(&drm->backend.events.output_remove, &conn->output); wl_signal_emit(&drm->backend.events.output_remove, &conn->output);
break; break;

View file

@ -66,6 +66,21 @@ bool wlr_drm_surface_init(struct wlr_drm_surface *surf,
surf->width = width; surf->width = width;
surf->height = height; 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;
}
gbm_surface_destroy(surf->gbm);
}
if (surf->egl) {
eglDestroySurface(surf->renderer->egl.display, surf->egl);
}
surf->gbm = gbm_surface_create(renderer->gbm, width, height, surf->gbm = gbm_surface_create(renderer->gbm, width, height,
format, GBM_BO_USE_RENDERING | flags); format, GBM_BO_USE_RENDERING | flags);
if (!surf->gbm) { if (!surf->gbm) {

View file

@ -48,6 +48,7 @@ struct screenshooter_output {
struct wl_output *output; struct wl_output *output;
struct wl_buffer *buffer; struct wl_buffer *buffer;
int width, height, offset_x, offset_y; int width, height, offset_x, offset_y;
enum wl_output_transform transform;
void *data; void *data;
struct wl_list link; 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) { if (wl_output == output->output) {
output->offset_x = x; output->offset_x = x;
output->offset_y = y; output->offset_y = y;
output->transform = transform;
} }
} }
@ -159,14 +161,75 @@ static void write_image(const char *filename, int width, int height) {
struct screenshooter_output *output, *next; struct screenshooter_output *output, *next;
wl_list_for_each_safe(output, next, &output_list, link) { wl_list_for_each_safe(output, next, &output_list, link) {
int output_stride = output->width * 4; int output_stride = output->width * 4;
void *s = output->data; uint32_t *src = (uint32_t *)output->data;
void *d = data + (output->offset_y - min_y) * buffer_stride + uint32_t *dst = (uint32_t *)(data +
(output->offset_x - min_x) * 4; (output->offset_y - min_y) * buffer_stride +
(output->offset_x - min_x) * 4);
for (int i = 0; i < output->height; i++) { switch (output->transform) {
memcpy(d, s, output_stride); case WL_OUTPUT_TRANSFORM_NORMAL:
d += buffer_stride; for (int i = 0; i < output->height; i++) {
s += output_stride; 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 - 1 - j];
}
}
break;
case WL_OUTPUT_TRANSFORM_90:
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 - 1 - i];
}
}
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 - 1 - j) * output->width + output->width - 1 - 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 - 1 - i) * output->width + output->width - 1 - 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 - 1 - 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 - 1 - 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); free(output);
@ -211,15 +274,23 @@ static void write_image(const char *filename, int width, int height) {
} }
static int set_buffer_size(int *width, int *height) { static int set_buffer_size(int *width, int *height) {
int owidth, oheight;
min_x = min_y = INT_MAX; min_x = min_y = INT_MAX;
max_x = max_y = INT_MIN; max_x = max_y = INT_MIN;
struct screenshooter_output *output; struct screenshooter_output *output;
wl_list_for_each(output, &output_list, link) { 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_x = MIN(min_x, output->offset_x);
min_y = MIN(min_y, output->offset_y); min_y = MIN(min_y, output->offset_y);
max_x = MAX(max_x, output->offset_x + output->width); max_x = MAX(max_x, output->offset_x + owidth);
max_y = MAX(max_y, output->offset_y + output->height); max_y = MAX(max_y, output->offset_y + oheight);
} }
if (max_x <= min_x || max_y <= min_y) { if (max_x <= min_x || max_y <= min_y) {

View file

@ -31,6 +31,10 @@ struct wlr_output_cursor {
struct wlr_surface *surface; struct wlr_surface *surface;
struct wl_listener surface_commit; struct wl_listener surface_commit;
struct wl_listener surface_destroy; struct wl_listener surface_destroy;
struct {
struct wl_signal destroy;
} events;
}; };
struct wlr_output_impl; struct wlr_output_impl;

View file

@ -6,7 +6,7 @@
#include <wlr/xcursor.h> #include <wlr/xcursor.h>
/** /**
* A scaled XCursor theme. * An XCursor theme at a particular scale factor of the base size.
*/ */
struct wlr_xcursor_manager_theme { struct wlr_xcursor_manager_theme {
float scale; float scale;
@ -15,11 +15,10 @@ struct wlr_xcursor_manager_theme {
}; };
/** /**
* Manage multiple XCursor themes with different scales and set `wlr_cursor` * wlr_xcursor_manager dynamically loads xcursor themes at sizes necessary for
* images. * use on outputs at arbitrary scale factors. You should call
* * wlr_xcursor_manager_load for each output you will show your cursor on, with
* This manager can be used to display cursor images on multiple outputs having * the scale factor parameter set to that output's scale factor.
* different scale factors.
*/ */
struct wlr_xcursor_manager { struct wlr_xcursor_manager {
char *name; char *name;
@ -28,24 +27,33 @@ struct wlr_xcursor_manager {
}; };
/** /**
* Create a new XCursor manager. After initialization, scaled themes need to be * Creates a new XCursor manager with the given xcursor theme name and base size
* loaded with `wlr_xcursor_manager_load`. `size` is the unscaled cursor theme * (for use when scale=1).
* size.
*/ */
struct wlr_xcursor_manager *wlr_xcursor_manager_create(const char *name, struct wlr_xcursor_manager *wlr_xcursor_manager_create(const char *name,
uint32_t size); uint32_t size);
void wlr_xcursor_manager_destroy(struct wlr_xcursor_manager *manager); 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, int wlr_xcursor_manager_load(struct wlr_xcursor_manager *manager,
float scale); 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 *wlr_xcursor_manager_get_xcursor(
struct wlr_xcursor_manager *manager, const char *name, float scale); struct wlr_xcursor_manager *manager, const char *name, float scale);
/** /**
* Set a `wlr_cursor` image. The manager uses all currently loaded scaled * Set a wlr_cursor's cursor image to the specified cursor name for all scale
* themes. * 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, void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager,
const char *name, struct wlr_cursor *cursor); const char *name, struct wlr_cursor *cursor);

View file

@ -50,6 +50,9 @@ struct wlr_xcursor {
uint32_t total_delay; /* length of the animation in ms */ uint32_t total_delay; /* length of the animation in ms */
}; };
/**
* Container for an Xcursor theme.
*/
struct wlr_xcursor_theme { struct wlr_xcursor_theme {
unsigned int cursor_count; unsigned int cursor_count;
struct wlr_xcursor **cursors; struct wlr_xcursor **cursors;
@ -57,13 +60,27 @@ struct wlr_xcursor_theme {
int size; 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); struct wlr_xcursor_theme *wlr_xcursor_theme_load(const char *name, int size);
void wlr_xcursor_theme_destroy(struct wlr_xcursor_theme *theme); 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 *wlr_xcursor_theme_get_cursor(
struct wlr_xcursor_theme *theme, const char *name); 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); int wlr_xcursor_frame(struct wlr_xcursor *cursor, uint32_t time);
/** /**

View file

@ -36,7 +36,7 @@ wlr_inc = include_directories('include')
cc = meson.get_compiler('c') 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 # are valid
if cc.get_id() == 'clang' if cc.get_id() == 'clang'
add_project_arguments('-Wno-missing-field-initializers', language: 'c') add_project_arguments('-Wno-missing-field-initializers', language: 'c')

View file

@ -873,6 +873,7 @@ struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) {
return NULL; return NULL;
} }
cursor->output = output; cursor->output = output;
wl_signal_init(&cursor->events.destroy);
wl_list_init(&cursor->surface_commit.link); wl_list_init(&cursor->surface_commit.link);
cursor->surface_commit.notify = output_cursor_handle_commit; cursor->surface_commit.notify = output_cursor_handle_commit;
wl_list_init(&cursor->surface_destroy.link); wl_list_init(&cursor->surface_destroy.link);
@ -886,6 +887,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
return; return;
} }
output_cursor_reset(cursor); output_cursor_reset(cursor);
wl_signal_emit(&cursor->events.destroy, cursor);
if (cursor->output->hardware_cursor == cursor) { if (cursor->output->hardware_cursor == cursor) {
// If this cursor was the hardware cursor, disable it // If this cursor was the hardware cursor, disable it
if (cursor->output->impl->set_cursor) { if (cursor->output->impl->set_cursor) {