diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 2e4a33528..1a471d28f 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -53,6 +53,7 @@ #include "window.h" +#include "single-pixel-buffer-v1-client-protocol.h" #include "tablet-unstable-v2-client-protocol.h" #include "weston-desktop-shell-client-protocol.h" @@ -782,94 +783,139 @@ enum { BACKGROUND_CENTERED }; +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + wl_buffer_destroy(buffer); +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + static void background_draw(struct widget *widget, void *data) { struct background *background = data; - cairo_surface_t *surface, *image; - cairo_pattern_t *pattern; - cairo_matrix_t matrix; - cairo_t *cr; - double im_w, im_h; - double sx, sy, s; - double tx, ty; - struct rectangle allocation; - surface = window_get_surface(background->window); + if (!background->image && background->color) { + struct display *display = window_get_display(background->window); + struct wp_single_pixel_buffer_manager_v1 *sp_manager; + struct wl_surface *wl_surface; + struct wl_buffer *wl_buffer; + uint32_t r8, g8, b8; + uint32_t r32, g32, b32; - cr = widget_cairo_create(background->widget); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - if (background->color == 0) - cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0); - else - set_hex_color(cr, background->color); - cairo_paint(cr); + sp_manager = display_get_single_pixel_buffer_manager(display); + assert(sp_manager); + wl_surface = widget_get_wl_surface(background->widget); + assert(wl_surface); - widget_get_allocation(widget, &allocation); - image = NULL; - if (background->image) - image = load_cairo_surface(background->image); - else if (background->color == 0) { - char *name = file_name_with_datadir("pattern.png"); + r8 = (background->color >> 16) & 0xff; + g8 = (background->color >> 8) & 0xff; + b8 = (background->color >> 0) & 0xff; - image = load_cairo_surface(name); - free(name); - } + r32 = r8 << 24 | r8 << 16 | r8 << 8 | r8; + g32 = g8 << 24 | g8 << 16 | g8 << 8 | g8; + b32 = b8 << 24 | b8 << 16 | b8 << 8 | b8; - if (image && background->type != -1) { - im_w = cairo_image_surface_get_width(image); - im_h = cairo_image_surface_get_height(image); - sx = im_w / allocation.width; - sy = im_h / allocation.height; + wl_buffer = + wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(sp_manager, + r32, + g32, + b32, + 0xffffffff); + assert(wl_buffer); - pattern = cairo_pattern_create_for_surface(image); + wl_surface_attach(wl_surface, wl_buffer, 0, 0); + wl_buffer_add_listener(wl_buffer, &buffer_listener, NULL); + widget_surface_flush(widget); + } else { + cairo_surface_t *surface, *image; + cairo_pattern_t *pattern; + cairo_matrix_t matrix; + cairo_t *cr; + double im_w, im_h; + double sx, sy, s; + double tx, ty; + struct rectangle allocation; - switch (background->type) { - case BACKGROUND_SCALE: - cairo_matrix_init_scale(&matrix, sx, sy); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); - break; - case BACKGROUND_SCALE_CROP: - case BACKGROUND_SCALE_FIT: - if (background->type == BACKGROUND_SCALE_CROP) - s = (sx < sy) ? sx : sy; - else - s = (sx > sy) ? sx : sy; - /* align center */ - tx = (im_w - s * allocation.width) * 0.5; - ty = (im_h - s * allocation.height) * 0.5; - cairo_matrix_init_translate(&matrix, tx, ty); - cairo_matrix_scale(&matrix, s, s); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); - break; - case BACKGROUND_TILE: - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - break; - case BACKGROUND_CENTERED: - s = (sx < sy) ? sx : sy; - if (s < 1.0) - s = 1.0; + surface = window_get_surface(background->window); - /* align center */ - tx = (im_w - s * allocation.width) * 0.5; - ty = (im_h - s * allocation.height) * 0.5; + cr = widget_cairo_create(background->widget); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + if (background->color == 0) + cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0); + else + set_hex_color(cr, background->color); + cairo_paint(cr); - cairo_matrix_init_translate(&matrix, tx, ty); - cairo_matrix_scale(&matrix, s, s); - cairo_pattern_set_matrix(pattern, &matrix); - break; + widget_get_allocation(widget, &allocation); + image = NULL; + if (background->image) + image = load_cairo_surface(background->image); + else if (background->color == 0) { + char *name = file_name_with_datadir("pattern.png"); + + image = load_cairo_surface(name); + free(name); } - cairo_set_source(cr, pattern); - cairo_pattern_destroy (pattern); - cairo_surface_destroy(image); - cairo_mask(cr, pattern); - } + if (image && background->type != -1) { + im_w = cairo_image_surface_get_width(image); + im_h = cairo_image_surface_get_height(image); + sx = im_w / allocation.width; + sy = im_h / allocation.height; - cairo_destroy(cr); - cairo_surface_destroy(surface); + pattern = cairo_pattern_create_for_surface(image); + + switch (background->type) { + case BACKGROUND_SCALE: + cairo_matrix_init_scale(&matrix, sx, sy); + cairo_pattern_set_matrix(pattern, &matrix); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); + break; + case BACKGROUND_SCALE_CROP: + case BACKGROUND_SCALE_FIT: + if (background->type == BACKGROUND_SCALE_CROP) + s = (sx < sy) ? sx : sy; + else + s = (sx > sy) ? sx : sy; + /* align center */ + tx = (im_w - s * allocation.width) * 0.5; + ty = (im_h - s * allocation.height) * 0.5; + cairo_matrix_init_translate(&matrix, tx, ty); + cairo_matrix_scale(&matrix, s, s); + cairo_pattern_set_matrix(pattern, &matrix); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); + break; + case BACKGROUND_TILE: + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); + break; + case BACKGROUND_CENTERED: + s = (sx < sy) ? sx : sy; + if (s < 1.0) + s = 1.0; + + /* align center */ + tx = (im_w - s * allocation.width) * 0.5; + ty = (im_h - s * allocation.height) * 0.5; + + cairo_matrix_init_translate(&matrix, tx, ty); + cairo_matrix_scale(&matrix, s, s); + cairo_pattern_set_matrix(pattern, &matrix); + break; + } + + cairo_set_source(cr, pattern); + cairo_pattern_destroy (pattern); + cairo_surface_destroy(image); + cairo_mask(cr, pattern); + } + + cairo_destroy(cr); + cairo_surface_destroy(surface); + } background->painted = 1; check_desktop_ready(background->window); @@ -897,6 +943,7 @@ background_configure(void *data, } if (!background->image && background->color) { + widget_set_use_cairo(background->widget, 0); widget_set_viewport_destination(background->widget, width, height); width = 1; height = 1; diff --git a/clients/meson.build b/clients/meson.build index d81b05337..9c10dcb0b 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -14,6 +14,8 @@ srcs_toytoolkit = [ relative_pointer_unstable_v1_protocol_c, pointer_constraints_unstable_v1_client_protocol_h, pointer_constraints_unstable_v1_protocol_c, + single_pixel_buffer_v1_client_protocol_h, + single_pixel_buffer_v1_protocol_c, tablet_unstable_v2_client_protocol_h, tablet_unstable_v2_protocol_c, ivi_application_client_protocol_h, diff --git a/clients/window.c b/clients/window.c index 104bb3991..bd0ecba90 100644 --- a/clients/window.c +++ b/clients/window.c @@ -55,6 +55,7 @@ #include #include "xdg-shell-client-protocol.h" #include "color-management-v1-client-protocol.h" +#include "single-pixel-buffer-v1-client-protocol.h" #include "text-cursor-position-client-protocol.h" #include "pointer-constraints-unstable-v1-client-protocol.h" #include "relative-pointer-unstable-v1-client-protocol.h" @@ -93,6 +94,7 @@ struct display { struct zwp_tablet_manager_v2 *tablet_manager; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; struct zwp_pointer_constraints_v1 *pointer_constraints; + struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager; uint32_t serial; uint32_t color_manager_features; @@ -1447,6 +1449,35 @@ surface_flush(struct surface *surface) surface->cairo_surface = NULL; } +void +widget_surface_flush(struct widget *widget) +{ + struct surface *surface = widget->surface; + + if (surface->opaque_region) { + wl_surface_set_opaque_region(surface->surface, + surface->opaque_region); + wl_region_destroy(surface->opaque_region); + surface->opaque_region = NULL; + } + + if (surface->input_region) { + wl_surface_set_input_region(surface->surface, + surface->input_region); + wl_region_destroy(surface->input_region); + surface->input_region = NULL; + } + + if (surface->viewport) { + wp_viewport_set_destination(surface->viewport, + widget->viewport_dest_width, + widget->viewport_dest_height); + } + + wl_surface_damage(surface->surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_commit(surface->surface); +} + int window_has_focus(struct window *window) { @@ -6807,6 +6838,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, &wp_color_manager_v1_interface, 1); wp_color_manager_v1_add_listener(d->color_manager, &cm_listener, d); + } else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) { + d->single_pixel_buffer_manager = + wl_registry_bind(registry, id, + &wp_single_pixel_buffer_manager_v1_interface, + 1); } if (d->global_handler) @@ -7095,6 +7131,12 @@ display_get_compositor(struct display *display) return display->compositor; } +struct wp_single_pixel_buffer_manager_v1 * +display_get_single_pixel_buffer_manager(struct display *display) +{ + return display->single_pixel_buffer_manager; +} + uint32_t display_get_serial(struct display *display) { diff --git a/clients/window.h b/clients/window.h index 9426fb36b..8b3d9d1f3 100644 --- a/clients/window.h +++ b/clients/window.h @@ -76,6 +76,9 @@ display_has_subcompositor(struct display *display); struct wl_compositor * display_get_compositor(struct display *display); +struct wp_single_pixel_buffer_manager_v1 * +display_get_single_pixel_buffer_manager(struct display *display); + struct output * display_get_output(struct display *display); @@ -610,6 +613,9 @@ widget_cairo_create(struct widget *widget); struct wl_surface * widget_get_wl_surface(struct widget *widget); +void +widget_surface_flush(struct widget *widget); + uint32_t widget_get_last_time(struct widget *widget);