From 531f0dfbbc525507b0894116daaf275451e9cf23 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 29 May 2022 11:50:47 +0200 Subject: [PATCH 01/20] render: replace wlr_texture_write_pixels with update_from_buffer This lets the renderer handle the wlr_buffer directly, just like it does in texture_from_buffer. This also allows the renderer to batch the rectangle updates, and update more than the damage region if desirable (e.g. too many rects), so can be more efficient. --- include/wlr/render/interface.h | 6 ++-- include/wlr/render/wlr_texture.h | 17 +++++++---- include/wlr/types/wlr_buffer.h | 3 -- render/gles2/texture.c | 46 ++++++++++++++++++++++-------- render/vulkan/texture.c | 47 +++++++++++++++++++++++++----- render/wlr_texture.c | 20 ++++++++----- types/wlr_buffer.c | 49 +------------------------------- 7 files changed, 101 insertions(+), 87 deletions(-) diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 7e923353e..20d755f9d 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -54,10 +54,8 @@ void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl); struct wlr_texture_impl { - bool (*write_pixels)(struct wlr_texture *texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data); + bool (*update_from_buffer)(struct wlr_texture *texture, + struct wlr_buffer *buffer, pixman_region32_t *damage); void (*destroy)(struct wlr_texture *texture); }; diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 0f39b8a89..5d4b0b618 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -9,6 +9,7 @@ #ifndef WLR_RENDER_WLR_TEXTURE_H #define WLR_RENDER_WLR_TEXTURE_H +#include #include #include #include @@ -37,13 +38,17 @@ struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, struct wlr_dmabuf_attributes *attribs); /** - * Update a texture with raw pixels. The texture must be mutable, and the input - * data must have the same pixel format that the texture was created with. + * Update a texture with a struct wlr_buffer's contents. + * + * The update might be rejected (in case the texture is immutable, the buffer + * has an unsupported type/format, etc), so callers must be prepared to fall + * back to re-creating the texture from scratch via wlr_texture_from_buffer(). + * + * The damage can be used by the renderer as an optimization: only the supplied + * region needs to be updated. */ -bool wlr_texture_write_pixels(struct wlr_texture *texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data); +bool wlr_texture_update_from_buffer(struct wlr_texture *texture, + struct wlr_buffer *buffer, pixman_region32_t *damage); /** * Destroys the texture. diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 17b93e5c4..b24c0ccd1 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -151,9 +151,6 @@ struct wlr_client_buffer { // private state struct wl_listener source_destroy; - - // If the client buffer has been created from a wl_shm buffer - uint32_t shm_source_format; }; /** diff --git a/render/gles2/texture.c b/render/gles2/texture.c index d794e436b..8b4ce6739 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -44,14 +44,24 @@ static bool check_stride(const struct wlr_pixel_format_info *fmt, return true; } -static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data) { +static bool gles2_texture_update_from_buffer(struct wlr_texture *wlr_texture, + struct wlr_buffer *buffer, pixman_region32_t *damage) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); if (texture->target != GL_TEXTURE_2D || texture->image != EGL_NO_IMAGE_KHR) { - wlr_log(WLR_ERROR, "Cannot write pixels to immutable texture"); + return false; + } + + void *data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + return false; + } + + if (format != texture->drm_format) { + wlr_buffer_end_data_ptr_access(buffer); return false; } @@ -63,7 +73,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, drm_get_pixel_format_info(texture->drm_format); assert(drm_fmt); - if (!check_stride(drm_fmt, stride, width)) { + if (!check_stride(drm_fmt, stride, buffer->width)) { + wlr_buffer_end_data_ptr_access(buffer); return false; } @@ -75,12 +86,21 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, glBindTexture(GL_TEXTURE_2D, texture->tex); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8)); - glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, src_x); - glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, src_y); + int rects_len = 0; + pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len); - glTexSubImage2D(GL_TEXTURE_2D, 0, dst_x, dst_y, width, height, - fmt->gl_format, fmt->gl_type, data); + for (int i = 0; i < rects_len; i++) { + pixman_box32_t rect = rects[i]; + + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8)); + glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1); + glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1); + + int width = rect.x2 - rect.x1; + int height = rect.y2 - rect.y1; + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, + fmt->gl_format, fmt->gl_type, data); + } glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); @@ -92,6 +112,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, wlr_egl_restore_context(&prev_ctx); + wlr_buffer_end_data_ptr_access(buffer); + return true; } @@ -156,7 +178,7 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .write_pixels = gles2_texture_write_pixels, + .update_from_buffer = gles2_texture_update_from_buffer, .destroy = gles2_texture_unref, }; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 35b9562e7..88298d93a 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -136,12 +136,45 @@ static bool write_pixels(struct wlr_texture *wlr_texture, return true; } -static bool vulkan_texture_write_pixels(struct wlr_texture *wlr_texture, - uint32_t stride, uint32_t width, uint32_t height, uint32_t src_x, - uint32_t src_y, uint32_t dst_x, uint32_t dst_y, const void *vdata) { - return write_pixels(wlr_texture, stride, width, height, src_x, src_y, - dst_x, dst_y, vdata, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); +static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture, + struct wlr_buffer *buffer, pixman_region32_t *damage) { + struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); + + void *data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + return false; + } + + bool ok = true; + + if (format != texture->format->drm_format) { + ok = false; + goto out; + } + + int rects_len = 0; + pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len); + + for (int i = 0; i < rects_len; i++) { + pixman_box32_t rect = rects[i]; + uint32_t width = rect.x2 - rect.x1; + uint32_t height = rect.y2 - rect.y1; + + // TODO: only map memory once + ok = write_pixels(wlr_texture, stride, width, height, rect.x1, rect.y1, + rect.x1, rect.y1, data, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); + if (!ok) { + goto out; + } + } + +out: + wlr_buffer_end_data_ptr_access(buffer); + return ok; } void vulkan_texture_destroy(struct wlr_vk_texture *texture) { @@ -191,7 +224,7 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .write_pixels = vulkan_texture_write_pixels, + .update_from_buffer = vulkan_texture_update_from_buffer, .destroy = vulkan_texture_unref, }; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index fa864d02b..7a59af30d 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -71,13 +71,19 @@ struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, return renderer->impl->texture_from_buffer(renderer, buffer); } -bool wlr_texture_write_pixels(struct wlr_texture *texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data) { - if (!texture->impl->write_pixels) { +bool wlr_texture_update_from_buffer(struct wlr_texture *texture, + struct wlr_buffer *buffer, pixman_region32_t *damage) { + if (!texture->impl->update_from_buffer) { return false; } - return texture->impl->write_pixels(texture, stride, width, height, - src_x, src_y, dst_x, dst_y, data); + if (texture->width != (uint32_t)buffer->width || + texture->height != (uint32_t)buffer->height) { + return false; + } + const pixman_box32_t *extents = pixman_region32_extents(damage); + if (extents->x1 < 0 || extents->y1 < 0 || extents->x2 > buffer->width || + extents->y2 > buffer->height) { + return false; + } + return texture->impl->update_from_buffer(texture, buffer, damage); } diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 49e205f3c..b63ce88ad 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -285,14 +285,6 @@ struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy); client_buffer->source_destroy.notify = client_buffer_handle_source_destroy; - if (buffer_is_shm_client_buffer(buffer)) { - struct wlr_shm_client_buffer *shm_client_buffer = - shm_client_buffer_from_buffer(buffer); - client_buffer->shm_source_format = shm_client_buffer->format; - } else { - client_buffer->shm_source_format = DRM_FORMAT_INVALID; - } - // Ensure the buffer will be released before being destroyed wlr_buffer_lock(&client_buffer->base); wlr_buffer_drop(&client_buffer->base); @@ -307,46 +299,7 @@ bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer, return false; } - if ((uint32_t)next->width != client_buffer->texture->width || - (uint32_t)next->height != client_buffer->texture->height) { - return false; - } - - if (client_buffer->shm_source_format == DRM_FORMAT_INVALID) { - // Uploading only damaged regions only works for wl_shm buffers and - // mutable textures (created from wl_shm buffer) - return false; - } - - void *data; - uint32_t format; - size_t stride; - if (!wlr_buffer_begin_data_ptr_access(next, WLR_BUFFER_DATA_PTR_ACCESS_READ, - &data, &format, &stride)) { - return false; - } - - if (format != client_buffer->shm_source_format) { - // Uploading to textures can't change the format - wlr_buffer_end_data_ptr_access(next); - return false; - } - - int n; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &n); - for (int i = 0; i < n; ++i) { - pixman_box32_t *r = &rects[i]; - if (!wlr_texture_write_pixels(client_buffer->texture, stride, - r->x2 - r->x1, r->y2 - r->y1, r->x1, r->y1, - r->x1, r->y1, data)) { - wlr_buffer_end_data_ptr_access(next); - return false; - } - } - - wlr_buffer_end_data_ptr_access(next); - - return true; + return wlr_texture_update_from_buffer(client_buffer->texture, next, damage); } static const struct wlr_buffer_impl shm_client_buffer_impl; From 31bc571e989da569b978c390fdf3e300de8d81ea Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 28 Jun 2022 13:10:23 -0400 Subject: [PATCH 02/20] wlr_raster: Introduce new abstraction --- include/wlr/render/wlr_texture.h | 4 ++ include/wlr/types/wlr_raster.h | 78 ++++++++++++++++++++++++++++++ render/wlr_texture.c | 12 ++++- types/meson.build | 1 + types/wlr_raster.c | 83 ++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 include/wlr/types/wlr_raster.h create mode 100644 types/wlr_raster.c diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 5d4b0b618..b5060d3c4 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -13,6 +13,7 @@ #include #include #include +#include struct wlr_buffer; struct wlr_renderer; @@ -21,6 +22,9 @@ struct wlr_texture_impl; struct wlr_texture { const struct wlr_texture_impl *impl; uint32_t width, height; + + struct wlr_raster *raster; + struct wl_list link; }; /** diff --git a/include/wlr/types/wlr_raster.h b/include/wlr/types/wlr_raster.h new file mode 100644 index 000000000..1cc9cabc3 --- /dev/null +++ b/include/wlr/types/wlr_raster.h @@ -0,0 +1,78 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_TYPES_WLR_RASTER_H +#define WLR_TYPES_WLR_RASTER_H + +#include +#include +#include + +struct wlr_buffer; +struct wlr_texture; + +struct wlr_raster { + // May be NULL + struct wlr_buffer *buffer; + uint32_t width, height; + + struct wl_list sources; // struct wlr_texture + + struct { + struct wl_signal destroy; + } events; + + // private state + + size_t n_locks; +}; + +/** + * Creates a new wlr_raster being backed by the given buffer. + * The creation funciton is referenced: once the creator is done with the raster, + * wlr_raster_unlock must be called. + */ +struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer); + +/** + * Removes and unlocks the buffer assolated with this raster. A raster must be + * created with a buffer so that there is a source of information for textures + * to be created from it, but once there is a texture, that can be used + * as the source of truth and so the buffer can be removed early for other + * purposes. + */ +void wlr_raster_remove_buffer(struct wlr_raster *raster); + +/** + * Lock the raster for use. As long as the raster has at least one lock, it + * will not be destroyed. The raster will be created with a reference count at 1 + * meaning that whatever produced the raster, must call this funciton. + */ +struct wlr_raster *wlr_raster_lock(struct wlr_raster *raster); + +/** + * Unlock the raster. This must be called after wlr_raster_lock once the raster + * has been finished being used. + */ +void wlr_raster_unlock(struct wlr_raster *raster); + +/** + * Attaches a wlr_texture to the raster. Consumers of the raster can use the + * given texture for their rendering if needed. The pixel contents of the texture + * must be the same as the source buffer and other textures in the raster. + */ +void wlr_raster_attach(struct wlr_raster *raster, struct wlr_texture *texture); + +/** + * Detaches a wlr_texture from the raster. Once the texture is detached, ownership + * of the texture is given to the caller such that the caller may mutate the + * raster if it wishes. + */ +void wlr_raster_detach(struct wlr_raster *raster, struct wlr_texture *texture); + +#endif diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 7a59af30d..162656c16 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "types/wlr_buffer.h" void wlr_texture_init(struct wlr_texture *texture, @@ -15,7 +16,16 @@ void wlr_texture_init(struct wlr_texture *texture, } void wlr_texture_destroy(struct wlr_texture *texture) { - if (texture && texture->impl && texture->impl->destroy) { + if (!texture) { + return; + } + + if (texture->raster) { + wlr_raster_detach(texture->raster, texture); + texture->raster = NULL; + } + + if (texture->impl && texture->impl->destroy) { texture->impl->destroy(texture); } else { free(texture); diff --git a/types/meson.build b/types/meson.build index 53bf852b8..4b86c00b3 100644 --- a/types/meson.build +++ b/types/meson.build @@ -58,6 +58,7 @@ wlr_files += files( 'wlr_presentation_time.c', 'wlr_primary_selection_v1.c', 'wlr_primary_selection.c', + 'wlr_raster.c', 'wlr_region.c', 'wlr_relative_pointer_v1.c', 'wlr_screencopy_v1.c', diff --git a/types/wlr_raster.c b/types/wlr_raster.c new file mode 100644 index 000000000..63ccf9bf4 --- /dev/null +++ b/types/wlr_raster.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include "util/signal.h" + +struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer) { + struct wlr_raster *raster = calloc(1, sizeof(*raster)); + if (!raster) { + return NULL; + } + + wl_list_init(&raster->sources); + wl_signal_init(&raster->events.destroy); + + assert(buffer); + raster->width = buffer->width; + raster->height = buffer->height; + raster->buffer = wlr_buffer_lock(buffer); + + raster->n_locks = 1; + + return raster; +} + +void wlr_raster_remove_buffer(struct wlr_raster *raster) { + assert(raster->buffer); + assert(!wl_list_empty(&raster->sources)); + + wlr_buffer_unlock(raster->buffer); + raster->buffer = NULL; +} + +static void raster_consider_destroy(struct wlr_raster *raster) { + if (raster->n_locks > 0) { + return; + } + + wlr_signal_emit_safe(&raster->events.destroy, NULL); + + struct wlr_texture *texture, *texture_tmp; + wl_list_for_each_safe(texture, texture_tmp, &raster->sources, link) { + wlr_texture_destroy(texture); + } + + wlr_buffer_unlock(raster->buffer); + free(raster); +} + +struct wlr_raster *wlr_raster_lock(struct wlr_raster *raster) { + raster->n_locks++; + return raster; +} + +void wlr_raster_unlock(struct wlr_raster *raster) { + if (!raster) { + return; + } + + assert(raster->n_locks > 0); + + raster->n_locks--; + raster_consider_destroy(raster); +} + +void wlr_raster_attach(struct wlr_raster *raster, struct wlr_texture *texture) { + assert(texture); + assert(!texture->raster); + assert(texture->width == raster->width && texture->height == raster->height); + + wl_list_insert(&raster->sources, &texture->link); + texture->raster = raster; +} + +void wlr_raster_detach(struct wlr_raster *raster, struct wlr_texture *texture) { + if (!texture) { + return; + } + + assert(texture->raster == raster); + texture->raster = NULL; + wl_list_remove(&texture->link); +} From bc53c79048b48f8d84a9246bf98b5f3201eb2a71 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 23 Jun 2022 19:28:05 -0400 Subject: [PATCH 03/20] wlr_raster: Introduce wlr_raster_from_pixels --- include/wlr/types/wlr_raster.h | 6 ++++++ types/wlr_raster.c | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/wlr/types/wlr_raster.h b/include/wlr/types/wlr_raster.h index 1cc9cabc3..f10a09b3b 100644 --- a/include/wlr/types/wlr_raster.h +++ b/include/wlr/types/wlr_raster.h @@ -75,4 +75,10 @@ void wlr_raster_attach(struct wlr_raster *raster, struct wlr_texture *texture); */ void wlr_raster_detach(struct wlr_raster *raster, struct wlr_texture *texture); +/** + * Create a new raster from raw pixel data. `stride` is in bytes. + */ +struct wlr_raster *wlr_raster_from_pixels(uint32_t fmt, uint32_t stride, + uint32_t width, uint32_t height, const void *data); + #endif diff --git a/types/wlr_raster.c b/types/wlr_raster.c index 63ccf9bf4..3bc408ef2 100644 --- a/types/wlr_raster.c +++ b/types/wlr_raster.c @@ -2,6 +2,7 @@ #include #include #include +#include "types/wlr_buffer.h" #include "util/signal.h" struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer) { @@ -81,3 +82,22 @@ void wlr_raster_detach(struct wlr_raster *raster, struct wlr_texture *texture) { texture->raster = NULL; wl_list_remove(&texture->link); } + +struct wlr_raster *wlr_raster_from_pixels(uint32_t fmt, uint32_t stride, + uint32_t width, uint32_t height, const void *data) { + assert(data); + + struct wlr_readonly_data_buffer *buffer = + readonly_data_buffer_create(fmt, stride, width, height, data); + if (buffer == NULL) { + return NULL; + } + + struct wlr_raster *raster = wlr_raster_create(&buffer->base); + + // By this point, the renderer should have locked the buffer if it still + // needs to access it in the future. + readonly_data_buffer_drop(buffer); + + return raster; +} From 5dd7c00a7c1c705c1db66f81e957790ba2414928 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 20 Jun 2022 03:26:53 -0400 Subject: [PATCH 04/20] renderer/pixman: Nuke wlr_pixman_texture_get_image Consumers can just get the image from the wlr_pixman_texture. Getting rid of this will make the transition to use wlr_raster easier. --- include/wlr/render/pixman.h | 1 - render/pixman/renderer.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/include/wlr/render/pixman.h b/include/wlr/render/pixman.h index 9a7be8774..255948f85 100644 --- a/include/wlr/render/pixman.h +++ b/include/wlr/render/pixman.h @@ -22,6 +22,5 @@ pixman_image_t *wlr_pixman_renderer_get_current_image( bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer); bool wlr_texture_is_pixman(struct wlr_texture *texture); -pixman_image_t *wlr_pixman_texture_get_image(struct wlr_texture *wlr_texture); #endif diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 2853b7047..5874cc8c9 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -528,11 +528,6 @@ struct wlr_renderer *wlr_pixman_renderer_create(void) { return &renderer->wlr_renderer; } -pixman_image_t *wlr_pixman_texture_get_image(struct wlr_texture *wlr_texture) { - struct wlr_pixman_texture *texture = get_texture(wlr_texture); - return texture->image; -} - pixman_image_t *wlr_pixman_renderer_get_current_image( struct wlr_renderer *wlr_renderer) { struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); From d8def1aa652f81d5653a6e9b58673fa754764187 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 24 Jun 2022 23:14:12 -0400 Subject: [PATCH 05/20] wlr_renderer: Introduce wlr_renderer_raster_upload --- include/render/gles2.h | 2 + include/render/vulkan.h | 2 + include/wlr/render/interface.h | 2 + include/wlr/render/wlr_renderer.h | 8 ++ render/gles2/renderer.c | 8 ++ render/gles2/texture.c | 29 +++++ render/pixman/renderer.c | 171 ++++++++++++++++++------------ render/vulkan/renderer.c | 8 ++ render/vulkan/texture.c | 29 +++++ render/wlr_renderer.c | 6 ++ 10 files changed, 198 insertions(+), 67 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 714bacf56..5ae43500b 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -125,6 +125,8 @@ struct wlr_gles2_renderer *gles2_get_renderer( struct wlr_renderer *wlr_renderer); struct wlr_gles2_texture *gles2_get_texture( struct wlr_texture *wlr_texture); +struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer, + struct wlr_raster *wlr_raster); struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, struct wl_resource *data); diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 1cba5a192..492b44823 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -256,6 +256,8 @@ struct wlr_vk_texture { }; struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture); +struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer, + struct wlr_raster *wlr_raster); VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer, const struct wlr_dmabuf_attributes *attribs, VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems, diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 20d755f9d..bf5cd58a3 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -27,6 +27,8 @@ struct wlr_renderer_impl { void (*end)(struct wlr_renderer *renderer); void (*clear)(struct wlr_renderer *renderer, const float color[static 4]); void (*scissor)(struct wlr_renderer *renderer, struct wlr_box *box); + bool (*raster_upload)(struct wlr_renderer *renderer, + struct wlr_raster *raster); bool (*render_subtexture_with_matrix)(struct wlr_renderer *renderer, struct wlr_texture *texture, const struct wlr_fbox *box, const float matrix[static 9], float alpha); diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index 50ba6b215..b14c2b4fb 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -48,6 +48,14 @@ void wlr_renderer_clear(struct wlr_renderer *r, const float color[static 4]); * box. */ void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box); + +/** + * The renderer will attempt to upload the raster using an available compatible + * source found in the raster to the device that the renderer is running on. + * If the raster is already uploaded to said device, then this is a no-op. + */ +bool wlr_renderer_raster_upload(struct wlr_renderer *r, + struct wlr_raster *raster); /** * Renders the requested texture. */ diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 5a2f31b55..48d293d13 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -534,6 +534,13 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) { free(renderer); } +static bool _gles2_raster_upload(struct wlr_renderer *wlr_renderer, + struct wlr_raster *raster) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + struct wlr_gles2_texture *texture = gles2_raster_upload(renderer, raster); + return texture; +} + static const struct wlr_renderer_impl renderer_impl = { .destroy = gles2_destroy, .bind_buffer = gles2_bind_buffer, @@ -541,6 +548,7 @@ static const struct wlr_renderer_impl renderer_impl = { .end = gles2_end, .clear = gles2_clear, .scissor = gles2_scissor, + .raster_upload = _gles2_raster_upload, .render_subtexture_with_matrix = gles2_render_subtexture_with_matrix, .render_quad_with_matrix = gles2_render_quad_with_matrix, .get_shm_texture_formats = gles2_get_shm_texture_formats, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 8b4ce6739..94ded6b17 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -376,6 +376,35 @@ struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer, } } +struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer, + struct wlr_raster *wlr_raster) { + struct wlr_texture *texture; + wl_list_for_each(texture, &wlr_raster->sources, link) { + if (wlr_texture_is_gles2(texture)) { + struct wlr_gles2_texture *gles2_tex = + (struct wlr_gles2_texture *)texture; + if (gles2_tex->renderer != renderer) { + continue; + } + return gles2_tex; + } + } + + if (!wlr_raster->buffer) { + // we could possibly do a blit with another texture from another renderer, + // but this is unsupported currently. + return NULL; + } + + texture = gles2_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer); + if (!texture) { + return NULL; + } + + wlr_raster_attach(wlr_raster, texture); + return (struct wlr_gles2_texture *)texture; +} + void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture, struct wlr_gles2_texture_attribs *attribs) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 5874cc8c9..fbda32c01 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -46,8 +46,103 @@ static struct wlr_pixman_texture *get_texture( return (struct wlr_pixman_texture *)wlr_texture; } +static struct wlr_pixman_texture *pixman_texture_create( + struct wlr_pixman_renderer *renderer, uint32_t drm_format, + uint32_t width, uint32_t height) { + struct wlr_pixman_texture *texture = + calloc(1, sizeof(struct wlr_pixman_texture)); + if (texture == NULL) { + wlr_log_errno(WLR_ERROR, "Failed to allocate pixman texture"); + return NULL; + } + + wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height); + texture->renderer = renderer; + + texture->format_info = drm_get_pixel_format_info(drm_format); + if (!texture->format_info) { + wlr_log(WLR_ERROR, "Unsupported drm format 0x%"PRIX32, drm_format); + free(texture); + return NULL; + } + + texture->format = get_pixman_format_from_drm(drm_format); + if (texture->format == 0) { + wlr_log(WLR_ERROR, "Unsupported pixman drm format 0x%"PRIX32, + drm_format); + free(texture); + return NULL; + } + + wl_list_insert(&renderer->textures, &texture->link); + + return texture; +} + +static struct wlr_texture *pixman_texture_from_buffer( + struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer) { + struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); + + void *data = NULL; + uint32_t drm_format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buffer, WLR_BUFFER_DATA_PTR_ACCESS_READ, + &data, &drm_format, &stride)) { + return NULL; + } + wlr_buffer_end_data_ptr_access(buffer); + + struct wlr_pixman_texture *texture = pixman_texture_create(renderer, + drm_format, buffer->width, buffer->height); + if (texture == NULL) { + return NULL; + } + + texture->image = pixman_image_create_bits_no_clear(texture->format, + buffer->width, buffer->height, data, stride); + if (!texture->image) { + wlr_log(WLR_ERROR, "Failed to create pixman image"); + wl_list_remove(&texture->link); + free(texture); + return NULL; + } + + texture->buffer = wlr_buffer_lock(buffer); + + return &texture->wlr_texture; +} + +static struct wlr_pixman_texture *raster_upload( + struct wlr_pixman_renderer *renderer, struct wlr_raster *wlr_raster) { + struct wlr_texture *texture; + wl_list_for_each(texture, &wlr_raster->sources, link) { + if (wlr_texture_is_pixman(texture)) { + struct wlr_pixman_texture *pixman_tex = + (struct wlr_pixman_texture *)texture; + if (pixman_tex->renderer != renderer) { + continue; + } + return pixman_tex; + } + } + + if (!wlr_raster->buffer) { + // we could possibly do a blit with another texture from another renderer, + // but this is unsupported currently. + return NULL; + } + + texture = pixman_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer); + if (!texture) { + return NULL; + } + + wlr_raster_attach(wlr_raster, texture); + return (struct wlr_pixman_texture *)texture; +} + static void texture_destroy(struct wlr_texture *wlr_texture) { - struct wlr_pixman_texture *texture = get_texture(wlr_texture); + struct wlr_pixman_texture *texture = (struct wlr_pixman_texture *)wlr_texture; wl_list_remove(&texture->link); pixman_image_unref(texture->image); wlr_buffer_unlock(texture->buffer); @@ -334,72 +429,6 @@ static const struct wlr_drm_format_set *pixman_get_render_formats( return &renderer->drm_formats; } -static struct wlr_pixman_texture *pixman_texture_create( - struct wlr_pixman_renderer *renderer, uint32_t drm_format, - uint32_t width, uint32_t height) { - struct wlr_pixman_texture *texture = - calloc(1, sizeof(struct wlr_pixman_texture)); - if (texture == NULL) { - wlr_log_errno(WLR_ERROR, "Failed to allocate pixman texture"); - return NULL; - } - - wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height); - texture->renderer = renderer; - - texture->format_info = drm_get_pixel_format_info(drm_format); - if (!texture->format_info) { - wlr_log(WLR_ERROR, "Unsupported drm format 0x%"PRIX32, drm_format); - free(texture); - return NULL; - } - - texture->format = get_pixman_format_from_drm(drm_format); - if (texture->format == 0) { - wlr_log(WLR_ERROR, "Unsupported pixman drm format 0x%"PRIX32, - drm_format); - free(texture); - return NULL; - } - - wl_list_insert(&renderer->textures, &texture->link); - - return texture; -} - -static struct wlr_texture *pixman_texture_from_buffer( - struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer) { - struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); - - void *data = NULL; - uint32_t drm_format; - size_t stride; - if (!wlr_buffer_begin_data_ptr_access(buffer, WLR_BUFFER_DATA_PTR_ACCESS_READ, - &data, &drm_format, &stride)) { - return NULL; - } - wlr_buffer_end_data_ptr_access(buffer); - - struct wlr_pixman_texture *texture = pixman_texture_create(renderer, - drm_format, buffer->width, buffer->height); - if (texture == NULL) { - return NULL; - } - - texture->image = pixman_image_create_bits_no_clear(texture->format, - buffer->width, buffer->height, data, stride); - if (!texture->image) { - wlr_log(WLR_ERROR, "Failed to create pixman image"); - wl_list_remove(&texture->link); - free(texture); - return NULL; - } - - texture->buffer = wlr_buffer_lock(buffer); - - return &texture->wlr_texture; -} - static bool pixman_bind_buffer(struct wlr_renderer *wlr_renderer, struct wlr_buffer *wlr_buffer) { struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); @@ -488,11 +517,19 @@ static uint32_t pixman_get_render_buffer_caps(struct wlr_renderer *renderer) { return WLR_BUFFER_CAP_DATA_PTR; } +static bool pixman_raster_upload(struct wlr_renderer *wlr_renderer, + struct wlr_raster *raster) { + struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); + struct wlr_pixman_texture *texture = raster_upload(renderer, raster); + return texture; +} + static const struct wlr_renderer_impl renderer_impl = { .begin = pixman_begin, .end = pixman_end, .clear = pixman_clear, .scissor = pixman_scissor, + .raster_upload = pixman_raster_upload, .render_subtexture_with_matrix = pixman_render_subtexture_with_matrix, .render_quad_with_matrix = pixman_render_quad_with_matrix, .get_shm_texture_formats = pixman_get_shm_texture_formats, diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index c373269df..a4be726b1 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -976,12 +976,20 @@ static uint32_t vulkan_get_render_buffer_caps(struct wlr_renderer *wlr_renderer) return WLR_BUFFER_CAP_DMABUF; } +static bool _vulkan_raster_upload(struct wlr_renderer *wlr_renderer, + struct wlr_raster *raster) { + struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); + struct wlr_vk_texture *texture = vulkan_raster_upload(renderer, raster); + return texture; +} + static const struct wlr_renderer_impl renderer_impl = { .bind_buffer = vulkan_bind_buffer, .begin = vulkan_begin, .end = vulkan_end, .clear = vulkan_clear, .scissor = vulkan_scissor, + .raster_upload = _vulkan_raster_upload, .render_subtexture_with_matrix = vulkan_render_subtexture_with_matrix, .render_quad_with_matrix = vulkan_render_quad_with_matrix, .get_shm_texture_formats = vulkan_get_shm_texture_formats, diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 88298d93a..a4c2b4366 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -742,3 +742,32 @@ struct wlr_texture *vulkan_texture_from_buffer( return NULL; } } + +struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer, + struct wlr_raster *wlr_raster) { + struct wlr_texture *texture; + wl_list_for_each(texture, &wlr_raster->sources, link) { + if (wlr_texture_is_vk(texture)) { + struct wlr_vk_texture *vk_tex = + (struct wlr_vk_texture *)texture; + if (vk_tex->renderer != renderer) { + continue; + } + return vk_tex; + } + } + + if (!wlr_raster->buffer) { + // we could possibly do a blit with another texture from another renderer, + // but this is unsupported currently. + return NULL; + } + + texture = vulkan_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer); + if (!texture) { + return NULL; + } + + wlr_raster_attach(wlr_raster, texture); + return (struct wlr_vk_texture *)texture; +} diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 478db7453..a4965b538 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -35,6 +35,7 @@ void wlr_renderer_init(struct wlr_renderer *renderer, assert(impl->begin); assert(impl->clear); assert(impl->scissor); + assert(impl->raster_upload); assert(impl->render_subtexture_with_matrix); assert(impl->render_quad_with_matrix); assert(impl->get_shm_texture_formats); @@ -113,6 +114,11 @@ void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box) { r->impl->scissor(r, box); } +bool wlr_renderer_raster_upload(struct wlr_renderer *r, + struct wlr_raster *raster) { + return r->impl->raster_upload(r, raster); +} + bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture, const float projection[static 9], int x, int y, float alpha) { struct wlr_box box = { From ba8230b00a599fff64b06bede1a6dcd3ed8d9374 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 20 Jun 2022 02:44:32 -0400 Subject: [PATCH 06/20] Nuke wlr_client_buffer This abstraction is incompatible with wlr_raster in every way, let's just use the client submitted buffers directly. This will regress a couple of things until wlr_raster has been fully integrated. --- backend/drm/drm.c | 3 +- examples/fullscreen-shell.c | 5 +- include/wlr/types/wlr_buffer.h | 41 -------------- include/wlr/types/wlr_compositor.h | 14 ----- types/output/cursor.c | 20 ++++--- types/scene/surface.c | 4 +- types/scene/wlr_scene.c | 6 --- types/wlr_buffer.c | 87 ------------------------------ types/wlr_compositor.c | 44 +-------------- 9 files changed, 21 insertions(+), 203 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 262a533e6..723beee24 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1508,8 +1508,7 @@ static void handle_page_flip(int fd, unsigned seq, * data between the GPUs, even if we were using the direct scanout * interface. */ - if (!drm->parent && plane->current_fb && - wlr_client_buffer_get(plane->current_fb->wlr_buf)) { + if (!drm->parent && plane->current_fb && false) { present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY; } diff --git a/examples/fullscreen-shell.c b/examples/fullscreen-shell.c index bc4bb7a86..de4ba4dc8 100644 --- a/examples/fullscreen-shell.c +++ b/examples/fullscreen-shell.c @@ -56,7 +56,8 @@ static void render_surface(struct wlr_surface *surface, struct render_data *rdata = data; struct wlr_output *output = rdata->output; - struct wlr_texture *texture = wlr_surface_get_texture(surface); + struct wlr_texture *texture = wlr_texture_from_buffer(output->renderer, + surface->current.buffer); if (texture == NULL) { return; } @@ -77,6 +78,8 @@ static void render_surface(struct wlr_surface *surface, wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); wlr_surface_send_frame_done(surface, rdata->when); + + wlr_texture_destroy(texture); } static void output_handle_frame(struct wl_listener *listener, void *data) { diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index b24c0ccd1..46a9198bc 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -132,50 +132,9 @@ bool wlr_buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride); void wlr_buffer_end_data_ptr_access(struct wlr_buffer *buffer); -/** - * A client buffer. - */ -struct wlr_client_buffer { - struct wlr_buffer base; - - /** - * The buffer's texture, if any. A buffer will not have a texture if the - * client destroys the buffer before it has been released. - */ - struct wlr_texture *texture; - /** - * The buffer this client buffer was created from. NULL if destroyed. - */ - struct wlr_buffer *source; - - // private state - - struct wl_listener source_destroy; -}; - -/** - * Creates a struct wlr_client_buffer from a given struct wlr_buffer by creating - * a texture from it, and copying its struct wl_resource. - */ -struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, - struct wlr_renderer *renderer); - -/** - * Get a client buffer from a generic buffer. If the buffer isn't a client - * buffer, returns NULL. - */ -struct wlr_client_buffer *wlr_client_buffer_get(struct wlr_buffer *buffer); /** * Check if a resource is a wl_buffer resource. */ bool wlr_resource_is_buffer(struct wl_resource *resource); -/** - * Try to update the buffer's content. - * - * Fails if there's more than one reference to the buffer or if the texture - * isn't mutable. - */ -bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer, - struct wlr_buffer *next, pixman_region32_t *damage); #endif diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 034b075b1..a8577087d 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -89,13 +89,6 @@ struct wlr_surface_output { struct wlr_surface { struct wl_resource *resource; struct wlr_renderer *renderer; - /** - * The surface's buffer, if any. A surface has an attached buffer when it - * commits with a non-null buffer in its pending state. A surface will not - * have a buffer if it has never committed one, has committed a null buffer, - * or something went wrong with uploading the buffer. - */ - struct wlr_client_buffer *buffer; /** * The buffer position, in surface-local units. */ @@ -199,13 +192,6 @@ bool wlr_surface_set_role(struct wlr_surface *surface, */ bool wlr_surface_has_buffer(struct wlr_surface *surface); -/** - * Get the texture of the buffer currently attached to this surface. Returns - * NULL if no buffer is currently attached or if something went wrong with - * uploading the buffer. - */ -struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface); - /** * Get the root of the subsurface tree for this surface. Can return NULL if * a surface in the tree has been destroyed. diff --git a/types/output/cursor.c b/types/output/cursor.c index 85973ce93..995af5c8a 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -94,9 +94,6 @@ static void output_cursor_render(struct wlr_output_cursor *cursor, assert(renderer); struct wlr_texture *texture = cursor->texture; - if (cursor->surface != NULL) { - texture = wlr_surface_get_texture(cursor->surface); - } if (texture == NULL) { return; } @@ -236,7 +233,6 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor) enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; struct wlr_texture *texture = cursor->texture; if (cursor->surface != NULL) { - texture = wlr_surface_get_texture(cursor->surface); scale = cursor->surface->current.scale; transform = cursor->surface->current.transform; } @@ -337,11 +333,8 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { return false; } + // TODO: try using the surface buffer directly struct wlr_texture *texture = cursor->texture; - if (cursor->surface != NULL) { - // TODO: try using the surface buffer directly - texture = wlr_surface_get_texture(cursor->surface); - } // If the cursor was hidden or was a software cursor, the hardware // cursor position is outdated @@ -445,6 +438,17 @@ static void output_cursor_commit(struct wlr_output_cursor *cursor, struct wlr_surface *surface = cursor->surface; assert(surface != NULL); + wlr_texture_destroy(cursor->texture); + cursor->texture = NULL; + + if (surface->current.buffer) { + cursor->texture = wlr_texture_from_buffer(cursor->output->renderer, + surface->current.buffer); + if (cursor->texture == NULL) { + return; + } + } + // Some clients commit a cursor surface with a NULL buffer to hide it. cursor->enabled = wlr_surface_has_buffer(surface); cursor->width = surface->current.width * cursor->output->scale; diff --git a/types/scene/surface.c b/types/scene/surface.c index d3a0b035f..e06e77312 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -66,9 +66,9 @@ static void set_buffer_with_surface_state(struct wlr_scene_buffer *scene_buffer, wlr_scene_buffer_set_dest_size(scene_buffer, state->width, state->height); wlr_scene_buffer_set_transform(scene_buffer, state->transform); - if (surface->buffer) { + if (surface->current.buffer) { wlr_scene_buffer_set_buffer_with_damage(scene_buffer, - &surface->buffer->base, &surface->buffer_damage); + surface->current.buffer, &surface->buffer_damage); } else { wlr_scene_buffer_set_buffer(scene_buffer, NULL); } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 68b05b7c8..4306410b4 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -477,12 +477,6 @@ void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, static struct wlr_texture *scene_buffer_get_texture( struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { - struct wlr_client_buffer *client_buffer = - wlr_client_buffer_get(scene_buffer->buffer); - if (client_buffer != NULL) { - return client_buffer->texture; - } - if (scene_buffer->texture != NULL) { return scene_buffer->texture; } diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index b63ce88ad..800a3f992 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -109,54 +109,6 @@ bool wlr_resource_is_buffer(struct wl_resource *resource) { return strcmp(wl_resource_get_class(resource), wl_buffer_interface.name) == 0; } -static const struct wlr_buffer_impl client_buffer_impl; - -struct wlr_client_buffer *wlr_client_buffer_get(struct wlr_buffer *buffer) { - if (buffer->impl != &client_buffer_impl) { - return NULL; - } - return (struct wlr_client_buffer *)buffer; -} - -static struct wlr_client_buffer *client_buffer_from_buffer( - struct wlr_buffer *buffer) { - struct wlr_client_buffer *client_buffer = wlr_client_buffer_get(buffer); - assert(client_buffer != NULL); - return client_buffer; -} - -static void client_buffer_destroy(struct wlr_buffer *buffer) { - struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer); - wl_list_remove(&client_buffer->source_destroy.link); - wlr_texture_destroy(client_buffer->texture); - free(client_buffer); -} - -static bool client_buffer_get_dmabuf(struct wlr_buffer *buffer, - struct wlr_dmabuf_attributes *attribs) { - struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer); - - if (client_buffer->source == NULL) { - return false; - } - - return wlr_buffer_get_dmabuf(client_buffer->source, attribs); -} - -static const struct wlr_buffer_impl client_buffer_impl = { - .destroy = client_buffer_destroy, - .get_dmabuf = client_buffer_get_dmabuf, -}; - -static void client_buffer_handle_source_destroy(struct wl_listener *listener, - void *data) { - struct wlr_client_buffer *client_buffer = - wl_container_of(listener, client_buffer, source_destroy); - wl_list_remove(&client_buffer->source_destroy.link); - wl_list_init(&client_buffer->source_destroy.link); - client_buffer->source = NULL; -} - static struct wlr_shm_client_buffer *shm_client_buffer_get_or_create( struct wl_resource *resource); static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer); @@ -263,45 +215,6 @@ bool buffer_is_opaque(struct wlr_buffer *buffer) { return !format_info->has_alpha; } -struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, - struct wlr_renderer *renderer) { - struct wlr_texture *texture = wlr_texture_from_buffer(renderer, buffer); - if (texture == NULL) { - wlr_log(WLR_ERROR, "Failed to create texture"); - return NULL; - } - - struct wlr_client_buffer *client_buffer = - calloc(1, sizeof(struct wlr_client_buffer)); - if (client_buffer == NULL) { - wlr_texture_destroy(texture); - return NULL; - } - wlr_buffer_init(&client_buffer->base, &client_buffer_impl, - texture->width, texture->height); - client_buffer->source = buffer; - client_buffer->texture = texture; - - wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy); - client_buffer->source_destroy.notify = client_buffer_handle_source_destroy; - - // Ensure the buffer will be released before being destroyed - wlr_buffer_lock(&client_buffer->base); - wlr_buffer_drop(&client_buffer->base); - - return client_buffer; -} - -bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer, - struct wlr_buffer *next, pixman_region32_t *damage) { - if (client_buffer->base.n_locks > 1) { - // Someone else still has a reference to the buffer - return false; - } - - return wlr_texture_update_from_buffer(client_buffer->texture, next, damage); -} - static const struct wlr_buffer_impl shm_client_buffer_impl; static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer) { diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index c1cdc3b05..fc00abb2f 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -333,45 +333,15 @@ static void surface_state_move(struct wlr_surface_state *state, static void surface_apply_damage(struct wlr_surface *surface) { if (surface->current.buffer == NULL) { // NULL commit - if (surface->buffer != NULL) { - wlr_buffer_unlock(&surface->buffer->base); - } - surface->buffer = NULL; surface->opaque = false; return; } surface->opaque = buffer_is_opaque(surface->current.buffer); - - if (surface->buffer != NULL) { - if (wlr_client_buffer_apply_damage(surface->buffer, - surface->current.buffer, &surface->buffer_damage)) { - wlr_buffer_unlock(surface->current.buffer); - surface->current.buffer = NULL; - return; - } - } - - struct wlr_client_buffer *buffer = wlr_client_buffer_create( - surface->current.buffer, surface->renderer); - - wlr_buffer_unlock(surface->current.buffer); - surface->current.buffer = NULL; - - if (buffer == NULL) { - wlr_log(WLR_ERROR, "Failed to upload buffer"); - return; - } - - if (surface->buffer != NULL) { - wlr_buffer_unlock(&surface->buffer->base); - } - surface->buffer = buffer; } static void surface_update_opaque_region(struct wlr_surface *surface) { - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (texture == NULL) { + if (!wlr_surface_has_buffer(surface)) { pixman_region32_clear(&surface->opaque_region); return; } @@ -660,9 +630,6 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { pixman_region32_fini(&surface->external_damage); pixman_region32_fini(&surface->opaque_region); pixman_region32_fini(&surface->input_region); - if (surface->buffer != NULL) { - wlr_buffer_unlock(&surface->buffer->base); - } free(surface); } @@ -716,15 +683,8 @@ static struct wlr_surface *surface_create(struct wl_client *client, return surface; } -struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface) { - if (surface->buffer == NULL) { - return NULL; - } - return surface->buffer->texture; -} - bool wlr_surface_has_buffer(struct wlr_surface *surface) { - return wlr_surface_get_texture(surface) != NULL; + return surface->current.buffer != NULL; } bool wlr_surface_set_role(struct wlr_surface *surface, From 45ad3d47ade3ab45ac70c18d26b0cea193802821 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 24 Jun 2022 23:31:20 -0400 Subject: [PATCH 07/20] backend/drm: Report ZERO_COPY hint when direct scanning a client dmabuf. Since wlr_client_buffer is gone, we are now dealing with client dmabufs directly. --- backend/drm/drm.c | 4 +++- include/wlr/types/wlr_linux_dmabuf_v1.h | 6 ++++++ types/wlr_linux_dmabuf_v1.c | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 723beee24..2a2e0a412 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -1508,7 +1509,8 @@ static void handle_page_flip(int fd, unsigned seq, * data between the GPUs, even if we were using the direct scanout * interface. */ - if (!drm->parent && plane->current_fb && false) { + if (!drm->parent && plane->current_fb && + wlr_dmabuf_v1_buffer_is_buffer(plane->current_fb->wlr_buf)) { present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY; } diff --git a/include/wlr/types/wlr_linux_dmabuf_v1.h b/include/wlr/types/wlr_linux_dmabuf_v1.h index 6b5f0d682..1222d8e29 100644 --- a/include/wlr/types/wlr_linux_dmabuf_v1.h +++ b/include/wlr/types/wlr_linux_dmabuf_v1.h @@ -34,6 +34,12 @@ struct wlr_dmabuf_v1_buffer { */ bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *buffer_resource); +/** + * Returns true if the given buffer was created via the linux-dmabuf + * buffer protocol, false otherwise + */ +bool wlr_dmabuf_v1_buffer_is_buffer(struct wlr_buffer *buffer); + /** * Returns the struct wlr_dmabuf_buffer if the given resource was created * via the linux-dmabuf buffer protocol. diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index a124d5212..1b1b7b3b8 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -86,6 +86,10 @@ struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_buffer_resource( static const struct wlr_buffer_impl buffer_impl; +bool wlr_dmabuf_v1_buffer_is_buffer(struct wlr_buffer *buffer) { + return buffer->impl == &buffer_impl; +} + static struct wlr_dmabuf_v1_buffer *dmabuf_v1_buffer_from_buffer( struct wlr_buffer *buffer) { assert(buffer->impl == &buffer_impl); From 248a33a026ce50c30bdbbdc5517256f0e334d470 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 26 Jun 2022 22:29:22 -0400 Subject: [PATCH 08/20] wlr_renderer: Switch texture rendering functions to take wlr_raster Implements automatic texture uploading as both wlr_scene and cursor handling both are simplified as a result. --- backend/drm/renderer.c | 13 +++--- examples/fullscreen-shell.c | 9 ++--- examples/output-layout.c | 11 +++-- examples/rotation.c | 13 +++--- examples/touch.c | 17 ++++---- include/render/gles2.h | 2 - include/render/vulkan.h | 1 - include/wlr/render/interface.h | 5 ++- include/wlr/render/wlr_renderer.h | 16 ++++---- include/wlr/types/wlr_output.h | 2 +- include/wlr/types/wlr_scene.h | 3 +- render/gles2/renderer.c | 20 ++++----- render/gles2/texture.c | 2 +- render/pixman/renderer.c | 17 ++++---- render/vulkan/renderer.c | 21 +++++----- render/vulkan/texture.c | 2 +- render/wlr_renderer.c | 26 ++++++------ types/output/cursor.c | 67 +++++++++++++------------------ types/scene/wlr_scene.c | 38 ++++++------------ types/wlr_screencopy_v1.c | 23 ++++++----- 20 files changed, 142 insertions(+), 166 deletions(-) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 9e1de3d0a..7df99656f 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -90,14 +90,14 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, return NULL; } - struct wlr_texture *tex = wlr_texture_from_buffer(renderer, buffer); - if (tex == NULL) { + struct wlr_raster *raster = wlr_raster_create(buffer); + if (!raster) { return NULL; } struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain, NULL); if (!dst) { - wlr_texture_destroy(tex); + wlr_raster_unlock(raster); return NULL; } @@ -107,16 +107,15 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, if (!wlr_renderer_begin_with_buffer(renderer, dst)) { wlr_buffer_unlock(dst); - wlr_texture_destroy(tex); + wlr_raster_unlock(raster); return NULL; } wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 }); - wlr_render_texture_with_matrix(renderer, tex, mat, 1.0f); + wlr_render_raster_with_matrix(renderer, raster, mat, 1.0f); wlr_renderer_end(renderer); - - wlr_texture_destroy(tex); + wlr_raster_unlock(raster); return dst; } diff --git a/examples/fullscreen-shell.c b/examples/fullscreen-shell.c index de4ba4dc8..e514649ff 100644 --- a/examples/fullscreen-shell.c +++ b/examples/fullscreen-shell.c @@ -56,9 +56,8 @@ static void render_surface(struct wlr_surface *surface, struct render_data *rdata = data; struct wlr_output *output = rdata->output; - struct wlr_texture *texture = wlr_texture_from_buffer(output->renderer, - surface->current.buffer); - if (texture == NULL) { + struct wlr_raster *raster = wlr_raster_create(surface->current.buffer); + if (raster == NULL) { return; } @@ -75,11 +74,11 @@ static void render_surface(struct wlr_surface *surface, wlr_matrix_project_box(matrix, &box, transform, 0, output->transform_matrix); - wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1); + wlr_render_raster_with_matrix(rdata->renderer, raster, matrix, 1); wlr_surface_send_frame_done(surface, rdata->when); - wlr_texture_destroy(texture); + wlr_raster_unlock(raster); } static void output_handle_frame(struct wl_listener *listener, void *data) { diff --git a/examples/output-layout.c b/examples/output-layout.c index 97939953f..66bef2ab1 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -29,7 +29,7 @@ struct sample_state { struct wl_listener new_input; struct wlr_renderer *renderer; struct wlr_allocator *allocator; - struct wlr_texture *cat_texture; + struct wlr_raster *cat_raster; struct wlr_output_layout *layout; float x_offs, y_offs; float x_vel, y_vel; @@ -134,7 +134,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { wlr_output_layout_output_coords(sample->layout, output->output, &local_x, &local_y); - wlr_render_texture(sample->renderer, sample->cat_texture, + wlr_render_raster(sample->renderer, sample->cat_raster, wlr_output->transform_matrix, local_x, local_y, 1.0f); } @@ -279,9 +279,8 @@ int main(int argc, char *argv[]) { state.new_input.notify = new_input_notify; state.renderer = wlr_renderer_autocreate(wlr); - state.cat_texture = wlr_texture_from_pixels(state.renderer, - DRM_FORMAT_ABGR8888, cat_tex.width * 4, cat_tex.width, cat_tex.height, - cat_tex.pixel_data); + state.cat_raster = wlr_raster_from_pixels(DRM_FORMAT_ABGR8888, + cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data); state.allocator = wlr_allocator_autocreate(wlr, state.renderer); @@ -292,7 +291,7 @@ int main(int argc, char *argv[]) { } wl_display_run(display); - wlr_texture_destroy(state.cat_texture); + wlr_raster_unlock(state.cat_raster); wl_display_destroy(state.display); wlr_output_layout_destroy(state.layout); diff --git a/examples/rotation.c b/examples/rotation.c index 087fa8d18..9ef822fb3 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -27,7 +27,7 @@ struct sample_state { struct timespec last_frame; struct wlr_renderer *renderer; struct wlr_allocator *allocator; - struct wlr_texture *cat_texture; + struct wlr_raster *cat_raster; struct wl_list outputs; enum wl_output_transform transform; }; @@ -65,7 +65,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { for (int y = -128 + (int)sample_output->y_offs; y < height; y += 128) { for (int x = -128 + (int)sample_output->x_offs; x < width; x += 128) { - wlr_render_texture(sample->renderer, sample->cat_texture, + wlr_render_raster(sample->renderer, sample->cat_raster, wlr_output->transform_matrix, x, y, 1.0f); } } @@ -256,10 +256,9 @@ int main(int argc, char *argv[]) { wlr_backend_destroy(wlr); exit(EXIT_FAILURE); } - state.cat_texture = wlr_texture_from_pixels(state.renderer, - DRM_FORMAT_ABGR8888, cat_tex.width * 4, cat_tex.width, cat_tex.height, - cat_tex.pixel_data); - if (!state.cat_texture) { + state.cat_raster = wlr_raster_from_pixels(DRM_FORMAT_ABGR8888, + cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data); + if (!state.cat_raster) { wlr_log(WLR_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); } @@ -273,6 +272,6 @@ int main(int argc, char *argv[]) { } wl_display_run(display); - wlr_texture_destroy(state.cat_texture); + wlr_raster_unlock(state.cat_raster); wl_display_destroy(display); } diff --git a/examples/touch.c b/examples/touch.c index d33e148aa..ca2c03dbb 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -25,7 +25,7 @@ struct sample_state { struct wl_display *display; struct wlr_renderer *renderer; struct wlr_allocator *allocator; - struct wlr_texture *cat_texture; + struct wlr_raster *cat_raster; struct wl_list touch_points; struct timespec last_frame; struct wl_listener new_output; @@ -81,9 +81,9 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct touch_point *p; wl_list_for_each(p, &sample->touch_points, link) { - int x = (int)(p->x * width) - sample->cat_texture->width / 2; - int y = (int)(p->y * height) - sample->cat_texture->height / 2; - wlr_render_texture(sample->renderer, sample->cat_texture, + int x = (int)(p->x * width) - sample->cat_raster->width / 2; + int y = (int)(p->y * height) - sample->cat_raster->height / 2; + wlr_render_raster(sample->renderer, sample->cat_raster, wlr_output->transform_matrix, x, y, 1.0f); } @@ -264,10 +264,9 @@ int main(int argc, char *argv[]) { wlr_log(WLR_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); } - state.cat_texture = wlr_texture_from_pixels(state.renderer, - DRM_FORMAT_ARGB8888, cat_tex.width * 4, cat_tex.width, cat_tex.height, - cat_tex.pixel_data); - if (!state.cat_texture) { + state.cat_raster = wlr_raster_from_pixels(DRM_FORMAT_ARGB8888, + cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data); + if (!state.cat_raster) { wlr_log(WLR_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); } @@ -281,6 +280,6 @@ int main(int argc, char *argv[]) { } wl_display_run(display); - wlr_texture_destroy(state.cat_texture); + wlr_raster_unlock(state.cat_raster); wl_display_destroy(display); } diff --git a/include/render/gles2.h b/include/render/gles2.h index 5ae43500b..d311f434d 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -123,8 +123,6 @@ const uint32_t *get_gles2_shm_formats(const struct wlr_gles2_renderer *renderer, struct wlr_gles2_renderer *gles2_get_renderer( struct wlr_renderer *wlr_renderer); -struct wlr_gles2_texture *gles2_get_texture( - struct wlr_texture *wlr_texture); struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer, struct wlr_raster *wlr_raster); diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 492b44823..2af72e50d 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -255,7 +255,6 @@ struct wlr_vk_texture { struct wl_listener buffer_destroy; }; -struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture); struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer, struct wlr_raster *wlr_raster); VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer, diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index bf5cd58a3..532a5ad3c 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -14,6 +14,7 @@ #include #include #include +#include #include struct wlr_box; @@ -29,8 +30,8 @@ struct wlr_renderer_impl { void (*scissor)(struct wlr_renderer *renderer, struct wlr_box *box); bool (*raster_upload)(struct wlr_renderer *renderer, struct wlr_raster *raster); - bool (*render_subtexture_with_matrix)(struct wlr_renderer *renderer, - struct wlr_texture *texture, const struct wlr_fbox *box, + bool (*render_subraster_with_matrix)(struct wlr_renderer *renderer, + struct wlr_raster *raster, const struct wlr_fbox *box, const float matrix[static 9], float alpha); void (*render_quad_with_matrix)(struct wlr_renderer *renderer, const float color[static 4], const float matrix[static 9]); diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index b14c2b4fb..9b2dc0eb0 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -57,21 +57,21 @@ void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box); bool wlr_renderer_raster_upload(struct wlr_renderer *r, struct wlr_raster *raster); /** - * Renders the requested texture. + * Renders the requested raster. */ -bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture, +bool wlr_render_raster(struct wlr_renderer *r, struct wlr_raster *raster, const float projection[static 9], int x, int y, float alpha); /** - * Renders the requested texture using the provided matrix. + * Renders the requested raster using the provided matrix. */ -bool wlr_render_texture_with_matrix(struct wlr_renderer *r, - struct wlr_texture *texture, const float matrix[static 9], float alpha); +bool wlr_render_raster_with_matrix(struct wlr_renderer *r, + struct wlr_raster *raster, const float matrix[static 9], float alpha); /** - * Renders the requested texture using the provided matrix, after cropping it + * Renders the requested raster using the provided matrix, after cropping it * to the provided rectangle. */ -bool wlr_render_subtexture_with_matrix(struct wlr_renderer *r, - struct wlr_texture *texture, const struct wlr_fbox *box, +bool wlr_render_subraster_with_matrix(struct wlr_renderer *r, + struct wlr_raster *raster, const struct wlr_fbox *box, const float matrix[static 9], float alpha); /** * Renders a solid rectangle in the specified color. diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 4f8bff0df..3fce6d8af 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -34,7 +34,7 @@ struct wlr_output_cursor { struct wl_list link; // only when using a software cursor without a surface - struct wlr_texture *texture; + struct wlr_raster *raster; // only when using a cursor surface struct wlr_surface *surface; diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 85d0f94eb..326dc63cf 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -23,6 +23,7 @@ #include #include #include +#include struct wlr_output; struct wlr_output_layout; @@ -147,7 +148,7 @@ struct wlr_scene_buffer { // private state uint64_t active_outputs; - struct wlr_texture *texture; + struct wlr_raster *raster; struct wlr_fbox src_box; int dst_width, dst_height; enum wl_output_transform transform; diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 48d293d13..e24114a7d 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -246,15 +246,17 @@ static void gles2_scissor(struct wlr_renderer *wlr_renderer, pop_gles2_debug(renderer); } -static bool gles2_render_subtexture_with_matrix( - struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture, +static bool gles2_render_subraster_with_matrix( + struct wlr_renderer *wlr_renderer, struct wlr_raster *wlr_raster, const struct wlr_fbox *box, const float matrix[static 9], float alpha) { struct wlr_gles2_renderer *renderer = gles2_get_renderer_in_context(wlr_renderer); struct wlr_gles2_texture *texture = - gles2_get_texture(wlr_texture); - assert(texture->renderer == renderer); + gles2_raster_upload(renderer, wlr_raster); + if (!texture) { + return false; + } struct wlr_gles2_tex_shader *shader = NULL; @@ -305,10 +307,10 @@ static bool gles2_render_subtexture_with_matrix( glUniform1i(shader->tex, 0); glUniform1f(shader->alpha, alpha); - const GLfloat x1 = box->x / wlr_texture->width; - const GLfloat y1 = box->y / wlr_texture->height; - const GLfloat x2 = (box->x + box->width) / wlr_texture->width; - const GLfloat y2 = (box->y + box->height) / wlr_texture->height; + const GLfloat x1 = box->x / wlr_raster->width; + const GLfloat y1 = box->y / wlr_raster->height; + const GLfloat x2 = (box->x + box->width) / wlr_raster->width; + const GLfloat y2 = (box->y + box->height) / wlr_raster->height; const GLfloat texcoord[] = { x2, y1, // top right x1, y1, // top left @@ -549,7 +551,7 @@ static const struct wlr_renderer_impl renderer_impl = { .clear = gles2_clear, .scissor = gles2_scissor, .raster_upload = _gles2_raster_upload, - .render_subtexture_with_matrix = gles2_render_subtexture_with_matrix, + .render_subraster_with_matrix = gles2_render_subraster_with_matrix, .render_quad_with_matrix = gles2_render_quad_with_matrix, .get_shm_texture_formats = gles2_get_shm_texture_formats, .get_dmabuf_texture_formats = gles2_get_dmabuf_texture_formats, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 94ded6b17..43d015bee 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -23,7 +23,7 @@ bool wlr_texture_is_gles2(struct wlr_texture *wlr_texture) { return wlr_texture->impl == &texture_impl; } -struct wlr_gles2_texture *gles2_get_texture( +static struct wlr_gles2_texture *gles2_get_texture( struct wlr_texture *wlr_texture) { assert(wlr_texture_is_gles2(wlr_texture)); return (struct wlr_gles2_texture *)wlr_texture; diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index fbda32c01..5589ee66e 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -40,12 +40,6 @@ bool wlr_texture_is_pixman(struct wlr_texture *texture) { return texture->impl == &texture_impl; } -static struct wlr_pixman_texture *get_texture( - struct wlr_texture *wlr_texture) { - assert(wlr_texture_is_pixman(wlr_texture)); - return (struct wlr_pixman_texture *)wlr_texture; -} - static struct wlr_pixman_texture *pixman_texture_create( struct wlr_pixman_renderer *renderer, uint32_t drm_format, uint32_t width, uint32_t height) { @@ -310,13 +304,16 @@ static void matrix_to_pixman_transform(struct pixman_transform *transform, pixman_transform_from_pixman_f_transform(transform, &ftr); } -static bool pixman_render_subtexture_with_matrix( - struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture, +static bool pixman_render_subraster_with_matrix( + struct wlr_renderer *wlr_renderer, struct wlr_raster *wlr_raster, const struct wlr_fbox *fbox, const float matrix[static 9], float alpha) { struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); - struct wlr_pixman_texture *texture = get_texture(wlr_texture); struct wlr_pixman_buffer *buffer = renderer->current_buffer; + struct wlr_pixman_texture *texture = raster_upload(renderer, wlr_raster); + if (!texture){ + return false; + } if (texture->buffer != NULL) { void *data; @@ -530,7 +527,7 @@ static const struct wlr_renderer_impl renderer_impl = { .clear = pixman_clear, .scissor = pixman_scissor, .raster_upload = pixman_raster_upload, - .render_subtexture_with_matrix = pixman_render_subtexture_with_matrix, + .render_subraster_with_matrix = pixman_render_subraster_with_matrix, .render_quad_with_matrix = pixman_render_quad_with_matrix, .get_shm_texture_formats = pixman_get_shm_texture_formats, .get_render_formats = pixman_get_render_formats, diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index a4be726b1..5d9f01c53 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -740,14 +740,17 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) { } } -static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_renderer, - struct wlr_texture *wlr_texture, const struct wlr_fbox *box, +static bool vulkan_render_subraster_with_matrix(struct wlr_renderer *wlr_renderer, + struct wlr_raster *wlr_raster, const struct wlr_fbox *box, const float matrix[static 9], float alpha) { struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); VkCommandBuffer cb = renderer->cb; - struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); - assert(texture->renderer == renderer); + struct wlr_vk_texture *texture = vulkan_raster_upload(renderer, wlr_raster); + if (!texture) { + return false; + } + if (texture->dmabuf_imported && !texture->owned) { // Store this texture in the list of textures that need to be // acquired before rendering and released after rendering. @@ -776,10 +779,10 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render struct vert_pcr_data vert_pcr_data; mat3_to_mat4(final_matrix, vert_pcr_data.mat4); - vert_pcr_data.uv_off[0] = box->x / wlr_texture->width; - vert_pcr_data.uv_off[1] = box->y / wlr_texture->height; - vert_pcr_data.uv_size[0] = box->width / wlr_texture->width; - vert_pcr_data.uv_size[1] = box->height / wlr_texture->height; + vert_pcr_data.uv_off[0] = box->x / wlr_raster->width; + vert_pcr_data.uv_off[1] = box->y / wlr_raster->height; + vert_pcr_data.uv_size[0] = box->width / wlr_raster->width; + vert_pcr_data.uv_size[1] = box->height / wlr_raster->height; vkCmdPushConstants(cb, renderer->pipe_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data); @@ -990,7 +993,7 @@ static const struct wlr_renderer_impl renderer_impl = { .clear = vulkan_clear, .scissor = vulkan_scissor, .raster_upload = _vulkan_raster_upload, - .render_subtexture_with_matrix = vulkan_render_subtexture_with_matrix, + .render_subraster_with_matrix = vulkan_render_subraster_with_matrix, .render_quad_with_matrix = vulkan_render_quad_with_matrix, .get_shm_texture_formats = vulkan_get_shm_texture_formats, .get_dmabuf_texture_formats = vulkan_get_dmabuf_texture_formats, diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index a4c2b4366..ffd409f1e 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -18,7 +18,7 @@ bool wlr_texture_is_vk(struct wlr_texture *wlr_texture) { return wlr_texture->impl == &texture_impl; } -struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture) { +static struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture) { assert(wlr_texture_is_vk(wlr_texture)); return (struct wlr_vk_texture *)wlr_texture; } diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index a4965b538..3817fb98b 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -36,7 +36,7 @@ void wlr_renderer_init(struct wlr_renderer *renderer, assert(impl->clear); assert(impl->scissor); assert(impl->raster_upload); - assert(impl->render_subtexture_with_matrix); + assert(impl->render_subraster_with_matrix); assert(impl->render_quad_with_matrix); assert(impl->get_shm_texture_formats); assert(impl->get_render_buffer_caps); @@ -119,39 +119,39 @@ bool wlr_renderer_raster_upload(struct wlr_renderer *r, return r->impl->raster_upload(r, raster); } -bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture, +bool wlr_render_raster(struct wlr_renderer *r, struct wlr_raster *raster, const float projection[static 9], int x, int y, float alpha) { struct wlr_box box = { .x = x, .y = y, - .width = texture->width, - .height = texture->height, + .width = raster->width, + .height = raster->height, }; float matrix[9]; wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, projection); - return wlr_render_texture_with_matrix(r, texture, matrix, alpha); + return wlr_render_raster_with_matrix(r, raster, matrix, alpha); } -bool wlr_render_texture_with_matrix(struct wlr_renderer *r, - struct wlr_texture *texture, const float matrix[static 9], +bool wlr_render_raster_with_matrix(struct wlr_renderer *r, + struct wlr_raster *raster, const float matrix[static 9], float alpha) { struct wlr_fbox box = { .x = 0, .y = 0, - .width = texture->width, - .height = texture->height, + .width = raster->width, + .height = raster->height, }; - return wlr_render_subtexture_with_matrix(r, texture, &box, matrix, alpha); + return wlr_render_subraster_with_matrix(r, raster, &box, matrix, alpha); } -bool wlr_render_subtexture_with_matrix(struct wlr_renderer *r, - struct wlr_texture *texture, const struct wlr_fbox *box, +bool wlr_render_subraster_with_matrix(struct wlr_renderer *r, + struct wlr_raster *raster, const struct wlr_fbox *box, const float matrix[static 9], float alpha) { assert(r->rendering); - return r->impl->render_subtexture_with_matrix(r, texture, + return r->impl->render_subraster_with_matrix(r, raster, box, matrix, alpha); } diff --git a/types/output/cursor.c b/types/output/cursor.c index 995af5c8a..7aa858c4d 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -93,8 +93,7 @@ static void output_cursor_render(struct wlr_output_cursor *cursor, struct wlr_renderer *renderer = cursor->output->renderer; assert(renderer); - struct wlr_texture *texture = cursor->texture; - if (texture == NULL) { + if (!cursor->raster) { return; } @@ -118,7 +117,7 @@ static void output_cursor_render(struct wlr_output_cursor *cursor, pixman_box32_t *rects = pixman_region32_rectangles(&surface_damage, &nrects); for (int i = 0; i < nrects; ++i) { output_scissor(cursor->output, &rects[i]); - wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0f); + wlr_render_raster_with_matrix(renderer, cursor->raster, matrix, 1.0f); } wlr_renderer_scissor(renderer, NULL); @@ -231,28 +230,28 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor) float scale = output->scale; enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - struct wlr_texture *texture = cursor->texture; if (cursor->surface != NULL) { scale = cursor->surface->current.scale; transform = cursor->surface->current.transform; } - if (texture == NULL) { - return NULL; - } struct wlr_allocator *allocator = output->allocator; struct wlr_renderer *renderer = output->renderer; assert(allocator != NULL && renderer != NULL); - int width = texture->width; - int height = texture->height; + if (!cursor->raster) { + return NULL; + } + + int width = cursor->raster->width; + int height = cursor->raster->height; if (output->impl->get_cursor_size) { // Apply hardware limitations on buffer size output->impl->get_cursor_size(cursor->output, &width, &height); - if ((int)texture->width > width || (int)texture->height > height) { - wlr_log(WLR_DEBUG, "Cursor texture too large (%dx%d), " - "exceeds hardware limitations (%dx%d)", texture->width, - texture->height, width, height); + if ((int)cursor->raster->width > width || (int)cursor->raster->height > height) { + wlr_log(WLR_DEBUG, "Cursor raster too large (%dx%d), " + "exceeds hardware limitations (%dx%d)", cursor->raster->width, + cursor->raster->height, width, height); return NULL; } } @@ -284,8 +283,8 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor) } struct wlr_box cursor_box = { - .width = texture->width * output->scale / scale, - .height = texture->height * output->scale / scale, + .width = cursor->raster->width * output->scale / scale, + .height = cursor->raster->height * output->scale / scale, }; float output_matrix[9]; @@ -313,7 +312,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor) } wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 }); - wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0); + wlr_render_raster_with_matrix(renderer, cursor->raster, matrix, 1.0); wlr_renderer_end(renderer); @@ -333,21 +332,16 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { return false; } - // TODO: try using the surface buffer directly - struct wlr_texture *texture = cursor->texture; - // If the cursor was hidden or was a software cursor, the hardware // cursor position is outdated output->impl->move_cursor(cursor->output, (int)cursor->x, (int)cursor->y); struct wlr_buffer *buffer = NULL; - if (texture != NULL) { - buffer = render_cursor_buffer(cursor); - if (buffer == NULL) { - wlr_log(WLR_ERROR, "Failed to render cursor buffer"); - return false; - } + buffer = render_cursor_buffer(cursor); + if (buffer == NULL) { + wlr_log(WLR_ERROR, "Failed to render cursor buffer"); + return false; } struct wlr_box hotspot = { @@ -407,15 +401,16 @@ bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, output_cursor_update_visible(cursor); - wlr_texture_destroy(cursor->texture); - cursor->texture = NULL; + wlr_raster_unlock(cursor->raster); + cursor->raster = NULL; cursor->enabled = false; if (buffer != NULL) { - cursor->texture = wlr_texture_from_buffer(renderer, buffer); - if (cursor->texture == NULL) { + cursor->raster = wlr_raster_create(buffer); + if (!cursor->raster) { return false; } + cursor->enabled = true; } @@ -435,18 +430,14 @@ static void output_cursor_commit(struct wlr_output_cursor *cursor, output_cursor_damage_whole(cursor); } + wlr_raster_unlock(cursor->raster); + cursor->raster = NULL; + struct wlr_surface *surface = cursor->surface; assert(surface != NULL); - wlr_texture_destroy(cursor->texture); - cursor->texture = NULL; - if (surface->current.buffer) { - cursor->texture = wlr_texture_from_buffer(cursor->output->renderer, - surface->current.buffer); - if (cursor->texture == NULL) { - return; - } + cursor->raster = wlr_raster_create(surface->current.buffer); } // Some clients commit a cursor surface with a NULL buffer to hide it. @@ -593,7 +584,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) { output_set_hardware_cursor(cursor->output, NULL, 0, 0); cursor->output->hardware_cursor = NULL; } - wlr_texture_destroy(cursor->texture); + wlr_raster_unlock(cursor->raster); wl_list_remove(&cursor->link); free(cursor); } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 4306410b4..579b9b648 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -101,7 +101,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } } - wlr_texture_destroy(scene_buffer->texture); + wlr_raster_unlock(scene_buffer->raster); wlr_buffer_unlock(scene_buffer->buffer); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); @@ -345,8 +345,8 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff scene_node_damage_whole(&scene_buffer->node); } - wlr_texture_destroy(scene_buffer->texture); - scene_buffer->texture = NULL; + wlr_raster_unlock(scene_buffer->raster); + scene_buffer->raster = NULL; wlr_buffer_unlock(scene_buffer->buffer); if (buffer) { @@ -475,17 +475,6 @@ void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, wlr_signal_emit_safe(&scene_buffer->events.frame_done, now); } -static struct wlr_texture *scene_buffer_get_texture( - struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { - if (scene_buffer->texture != NULL) { - return scene_buffer->texture; - } - - scene_buffer->texture = - wlr_texture_from_buffer(renderer, scene_buffer->buffer); - return scene_buffer->texture; -} - static void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height) { *width = 0; @@ -821,8 +810,8 @@ static void render_rect(struct wlr_output *output, pixman_region32_fini(&damage); } -static void render_texture(struct wlr_output *output, - pixman_region32_t *output_damage, struct wlr_texture *texture, +static void render_raster(struct wlr_output *output, + pixman_region32_t *output_damage, struct wlr_raster *raster, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9]) { struct wlr_renderer *renderer = output->renderer; @@ -830,8 +819,8 @@ static void render_texture(struct wlr_output *output, struct wlr_fbox default_src_box = {0}; if (wlr_fbox_empty(src_box)) { - default_src_box.width = texture->width; - default_src_box.height = texture->height; + default_src_box.width = raster->width; + default_src_box.height = raster->height; src_box = &default_src_box; } @@ -845,7 +834,7 @@ static void render_texture(struct wlr_output *output, pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(output, &rects[i]); - wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, 1.0); + wlr_render_subraster_with_matrix(renderer, raster, src_box, matrix, 1.0); } pixman_region32_fini(&damage); @@ -870,7 +859,6 @@ static void render_node_iterator(struct wlr_scene_node *node, scene_node_get_size(node, &dst_box.width, &dst_box.height); scale_box(&dst_box, output->scale); - struct wlr_texture *texture; float matrix[9]; enum wl_output_transform transform; switch (node->type) { @@ -889,18 +877,16 @@ static void render_node_iterator(struct wlr_scene_node *node, return; } - struct wlr_renderer *renderer = output->renderer; - texture = scene_buffer_get_texture(scene_buffer, renderer); - if (texture == NULL) { - return; + if (!scene_buffer->raster) { + scene_buffer->raster = wlr_raster_create(scene_buffer->buffer); } transform = wlr_output_transform_invert(scene_buffer->transform); wlr_matrix_project_box(matrix, &dst_box, transform, 0.0, output->transform_matrix); - render_texture(output, output_damage, texture, &scene_buffer->src_box, - &dst_box, matrix); + render_raster(output, output_damage, scene_buffer->raster, + &scene_buffer->src_box, &dst_box, matrix); wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); break; diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index 0b48fe3f4..7c313696d 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -226,14 +226,18 @@ static bool frame_shm_copy(struct wlr_screencopy_frame_v1 *frame, static bool blit_dmabuf(struct wlr_renderer *renderer, struct wlr_dmabuf_v1_buffer *dst_dmabuf, struct wlr_buffer *src_buffer) { - struct wlr_buffer *dst_buffer = wlr_buffer_lock(&dst_dmabuf->base); - - struct wlr_texture *src_tex = - wlr_texture_from_buffer(renderer, src_buffer); - if (src_tex == NULL) { - goto error_src_tex; + struct wlr_raster *raster = wlr_raster_create(src_buffer); + if (!raster){ + return false; } + if (!wlr_renderer_raster_upload(renderer, raster)) { + wlr_raster_unlock(raster); + return false; + } + + struct wlr_buffer *dst_buffer = wlr_buffer_lock(&dst_dmabuf->base); + float mat[9]; wlr_matrix_identity(mat); wlr_matrix_scale(mat, dst_buffer->width, dst_buffer->height); @@ -243,17 +247,16 @@ static bool blit_dmabuf(struct wlr_renderer *renderer, } wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 }); - wlr_render_texture_with_matrix(renderer, src_tex, mat, 1.0f); + wlr_render_raster_with_matrix(renderer, raster, mat, 1.0f); wlr_renderer_end(renderer); - wlr_texture_destroy(src_tex); + wlr_raster_unlock(raster); wlr_buffer_unlock(dst_buffer); return true; error_renderer_begin: - wlr_texture_destroy(src_tex); -error_src_tex: + wlr_raster_unlock(raster); wlr_buffer_unlock(dst_buffer); return false; } From e594a590368b3ca6af808dddc06ef5b299b72694 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 2 Jul 2022 21:14:18 -0400 Subject: [PATCH 09/20] wlr_linux_dmabuf: Refactor to prevent double dmabuf import Instead, we'll initialize the buffer just enough so that renderers can work with it and if the dmabuf import was successful, we continue initializing the buffer. This will allow the dmabuf texture to addon itself onto the buffer for further use without another import. --- types/wlr_linux_dmabuf_v1.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index 1b1b7b3b8..7d2e013ba 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -201,17 +201,15 @@ static void buffer_handle_resource_destroy(struct wl_resource *buffer_resource) } static bool check_import_dmabuf(struct wlr_linux_dmabuf_v1 *linux_dmabuf, - struct wlr_dmabuf_attributes *attribs) { - struct wlr_texture *texture = - wlr_texture_from_dmabuf(linux_dmabuf->renderer, attribs); - if (texture == NULL) { + struct wlr_buffer *dmabuf) { + struct wlr_raster *raster = wlr_raster_create(dmabuf); + if (!raster) { return false; } - // We can import the image, good. No need to keep it since wlr_surface will - // import it again on commit. - wlr_texture_destroy(texture); - return true; + bool success = wlr_renderer_raster_upload(linux_dmabuf->renderer, raster); + wlr_raster_unlock(raster); + return success; } static void params_create_common(struct wl_resource *params_resource, @@ -331,17 +329,19 @@ static void params_create_common(struct wl_resource *params_resource, } } - /* Check if dmabuf is usable */ - if (!check_import_dmabuf(linux_dmabuf, &attribs)) { - goto err_failed; - } - struct wlr_dmabuf_v1_buffer *buffer = calloc(1, sizeof(*buffer)); if (!buffer) { wl_resource_post_no_memory(params_resource); goto err_failed; } wlr_buffer_init(&buffer->base, &buffer_impl, attribs.width, attribs.height); + buffer->attributes = attribs; + + /* Check if dmabuf is usable */ + if (!check_import_dmabuf(linux_dmabuf, &buffer->base)) { + free(buffer); + goto err_failed; + } struct wl_client *client = wl_resource_get_client(params_resource); buffer->resource = wl_resource_create(client, &wl_buffer_interface, @@ -354,8 +354,6 @@ static void params_create_common(struct wl_resource *params_resource, wl_resource_set_implementation(buffer->resource, &wl_buffer_impl, buffer, buffer_handle_resource_destroy); - buffer->attributes = attribs; - buffer->release.notify = buffer_handle_release; wl_signal_add(&buffer->base.events.release, &buffer->release); From dae7bd1413181580c1ac0c1bbc7d8e8a9f1982a2 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 20 Jun 2022 11:11:23 -0400 Subject: [PATCH 10/20] wlr_texture: Drop wlr_texture_from_dmabuf Compositors should first create a valid dmabuf first, then use normal apis to use that buffer where needed. --- include/wlr/render/wlr_texture.h | 7 ------- render/wlr_texture.c | 17 ----------------- 2 files changed, 24 deletions(-) diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index b5060d3c4..c5b50658b 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -12,7 +12,6 @@ #include #include #include -#include #include struct wlr_buffer; @@ -35,12 +34,6 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height, const void *data); -/** - * Create a new texture from a DMA-BUF. The returned texture is immutable. - */ -struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, - struct wlr_dmabuf_attributes *attribs); - /** * Update a texture with a struct wlr_buffer's contents. * diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 162656c16..6676d8f9d 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -56,23 +56,6 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, return texture; } -struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, - struct wlr_dmabuf_attributes *attribs) { - struct wlr_dmabuf_buffer *buffer = dmabuf_buffer_create(attribs); - if (buffer == NULL) { - return NULL; - } - - struct wlr_texture *texture = - wlr_texture_from_buffer(renderer, &buffer->base); - - // By this point, the renderer should have locked the buffer if it still - // needs to access it in the future. - dmabuf_buffer_drop(buffer); - - return texture; -} - struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, struct wlr_buffer *buffer) { if (!renderer->impl->texture_from_buffer) { From 33ae4085794c41b310bfe877ebb66248813feee9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 20 Jun 2022 23:59:22 -0400 Subject: [PATCH 11/20] wlr_texture: Drop wlr_texture_from_pixels Keeping the texture version doesn't make too much sense because compositors should send valid pixel data the first time around meaning they want to render straight away. wlr_raster_from_pixels should be used instead. Also drop a few asserts that are impossible because of the data type. --- include/wlr/render/wlr_texture.h | 8 -------- render/wlr_texture.c | 24 ------------------------ 2 files changed, 32 deletions(-) diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index c5b50658b..f438d2aaa 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -26,14 +26,6 @@ struct wlr_texture { struct wl_list link; }; -/** - * Create a new texture from raw pixel data. `stride` is in bytes. The returned - * texture is mutable. - */ -struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, - uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height, - const void *data); - /** * Update a texture with a struct wlr_buffer's contents. * diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 6676d8f9d..e1e621d55 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -32,30 +32,6 @@ void wlr_texture_destroy(struct wlr_texture *texture) { } } -struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, - uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height, - const void *data) { - assert(width > 0); - assert(height > 0); - assert(stride > 0); - assert(data); - - struct wlr_readonly_data_buffer *buffer = - readonly_data_buffer_create(fmt, stride, width, height, data); - if (buffer == NULL) { - return NULL; - } - - struct wlr_texture *texture = - wlr_texture_from_buffer(renderer, &buffer->base); - - // By this point, the renderer should have locked the buffer if it still - // needs to access it in the future. - readonly_data_buffer_drop(buffer); - - return texture; -} - struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, struct wlr_buffer *buffer) { if (!renderer->impl->texture_from_buffer) { From 1e2af8665bed0f4959e177723f9c1b97ee8f682b Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 20 Jun 2022 11:35:43 -0400 Subject: [PATCH 12/20] wlr_texture: Drop wlr_texure_from_buffer Compositors should be using wlr_raster for texture management. --- include/render/gles2.h | 2 - include/render/vulkan.h | 2 - include/wlr/render/interface.h | 2 - include/wlr/render/wlr_texture.h | 6 --- render/gles2/renderer.c | 1 - render/gles2/texture.c | 71 +++++++++++++---------------- render/pixman/renderer.c | 60 ++++++++++-------------- render/vulkan/renderer.c | 1 - render/vulkan/texture.c | 78 ++++++++++++++------------------ render/wlr_texture.c | 8 ---- 10 files changed, 88 insertions(+), 143 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index d311f434d..565a73d72 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -128,8 +128,6 @@ struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *rendere struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, struct wl_resource *data); -struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer, - struct wlr_buffer *buffer); void gles2_texture_destroy(struct wlr_gles2_texture *texture); void push_gles2_debug_(struct wlr_gles2_renderer *renderer, diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 2af72e50d..a7730225b 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -261,8 +261,6 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer, const struct wlr_dmabuf_attributes *attribs, VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems, bool for_render); -struct wlr_texture *vulkan_texture_from_buffer( - struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer); void vulkan_texture_destroy(struct wlr_vk_texture *texture); struct wlr_vk_descriptor_pool { diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 532a5ad3c..c072fa2f4 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -49,8 +49,6 @@ struct wlr_renderer_impl { void (*destroy)(struct wlr_renderer *renderer); int (*get_drm_fd)(struct wlr_renderer *renderer); uint32_t (*get_render_buffer_caps)(struct wlr_renderer *renderer); - struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer, - struct wlr_buffer *buffer); }; void wlr_renderer_init(struct wlr_renderer *renderer, diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index f438d2aaa..68131b46c 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -44,10 +44,4 @@ bool wlr_texture_update_from_buffer(struct wlr_texture *texture, */ void wlr_texture_destroy(struct wlr_texture *texture); -/** - * Create a new texture from a buffer. - */ -struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, - struct wlr_buffer *buffer); - #endif diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index e24114a7d..85cc03673 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -560,7 +560,6 @@ static const struct wlr_renderer_impl renderer_impl = { .read_pixels = gles2_read_pixels, .get_drm_fd = gles2_get_drm_fd, .get_render_buffer_caps = gles2_get_render_buffer_caps, - .texture_from_buffer = gles2_texture_from_buffer, }; void push_gles2_debug_(struct wlr_gles2_renderer *renderer, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 43d015bee..aac8e6465 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -196,12 +196,10 @@ static struct wlr_gles2_texture *gles2_texture_create( return texture; } -static struct wlr_texture *gles2_texture_from_pixels( - struct wlr_renderer *wlr_renderer, +static struct wlr_gles2_texture *gles2_texture_from_pixels( + struct wlr_gles2_renderer *renderer, uint32_t drm_format, uint32_t stride, uint32_t width, uint32_t height, const void *data) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - const struct wlr_gles2_pixel_format *fmt = get_gles2_format_from_drm(drm_format); if (fmt == NULL) { @@ -253,7 +251,7 @@ static struct wlr_texture *gles2_texture_from_pixels( wlr_egl_restore_context(&prev_ctx); - return &texture->wlr_texture; + return texture; } static struct wlr_texture *gles2_texture_from_dmabuf( @@ -325,7 +323,7 @@ static const struct wlr_addon_interface texture_addon_impl = { .destroy = texture_handle_buffer_destroy, }; -static struct wlr_texture *gles2_texture_from_dmabuf_buffer( +static struct wlr_gles2_texture *gles2_texture_from_dmabuf_buffer( struct wlr_gles2_renderer *renderer, struct wlr_buffer *buffer, struct wlr_dmabuf_attributes *dmabuf) { struct wlr_addon *addon = @@ -335,16 +333,16 @@ static struct wlr_texture *gles2_texture_from_dmabuf_buffer( wl_container_of(addon, texture, buffer_addon); if (!gles2_texture_invalidate(texture)) { wlr_log(WLR_ERROR, "Failed to invalidate texture"); - return false; + return NULL; } wlr_buffer_lock(texture->buffer); - return &texture->wlr_texture; + return texture; } struct wlr_texture *wlr_texture = gles2_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf); if (wlr_texture == NULL) { - return false; + return NULL; } struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); @@ -352,37 +350,16 @@ static struct wlr_texture *gles2_texture_from_dmabuf_buffer( wlr_addon_init(&texture->buffer_addon, &buffer->addons, renderer, &texture_addon_impl); - return &texture->wlr_texture; -} - -struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer, - struct wlr_buffer *buffer) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - - void *data; - uint32_t format; - size_t stride; - struct wlr_dmabuf_attributes dmabuf; - if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { - return gles2_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf); - } else if (wlr_buffer_begin_data_ptr_access(buffer, - WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { - struct wlr_texture *tex = gles2_texture_from_pixels(wlr_renderer, - format, stride, buffer->width, buffer->height, data); - wlr_buffer_end_data_ptr_access(buffer); - return tex; - } else { - return NULL; - } + return texture; } struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer, struct wlr_raster *wlr_raster) { - struct wlr_texture *texture; - wl_list_for_each(texture, &wlr_raster->sources, link) { - if (wlr_texture_is_gles2(texture)) { + struct wlr_texture *raster_texture; + wl_list_for_each(raster_texture, &wlr_raster->sources, link) { + if (wlr_texture_is_gles2(raster_texture)) { struct wlr_gles2_texture *gles2_tex = - (struct wlr_gles2_texture *)texture; + (struct wlr_gles2_texture *)raster_texture; if (gles2_tex->renderer != renderer) { continue; } @@ -390,19 +367,33 @@ struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *rendere } } + struct wlr_buffer *buffer = wlr_raster->buffer; if (!wlr_raster->buffer) { // we could possibly do a blit with another texture from another renderer, // but this is unsupported currently. return NULL; } - texture = gles2_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer); - if (!texture) { - return NULL; + struct wlr_gles2_texture *texture = NULL; + + void *data; + uint32_t format; + size_t stride; + struct wlr_dmabuf_attributes dmabuf; + if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { + texture = gles2_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf); + } else if (wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + texture = gles2_texture_from_pixels(renderer, + format, stride, buffer->width, buffer->height, data); + wlr_buffer_end_data_ptr_access(buffer); } - wlr_raster_attach(wlr_raster, texture); - return (struct wlr_gles2_texture *)texture; + if (texture) { + wlr_raster_attach(wlr_raster, &texture->wlr_texture); + } + + return texture; } void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture, diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 5589ee66e..8b1382c79 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -73,15 +73,32 @@ static struct wlr_pixman_texture *pixman_texture_create( return texture; } -static struct wlr_texture *pixman_texture_from_buffer( - struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer) { - struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer); +static struct wlr_pixman_texture *raster_upload( + struct wlr_pixman_renderer *renderer, struct wlr_raster *wlr_raster) { + struct wlr_texture *raster_texture; + wl_list_for_each(raster_texture, &wlr_raster->sources, link) { + if (wlr_texture_is_pixman(raster_texture)) { + struct wlr_pixman_texture *pixman_tex = + (struct wlr_pixman_texture *)raster_texture; + if (pixman_tex->renderer != renderer) { + continue; + } + return pixman_tex; + } + } + + struct wlr_buffer *buffer = wlr_raster->buffer; + if (!buffer) { + // we could possibly do a blit with another texture from another renderer, + // but this is unsupported currently. + return NULL; + } void *data = NULL; uint32_t drm_format; size_t stride; - if (!wlr_buffer_begin_data_ptr_access(buffer, WLR_BUFFER_DATA_PTR_ACCESS_READ, - &data, &drm_format, &stride)) { + if (!wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &drm_format, &stride)) { return NULL; } wlr_buffer_end_data_ptr_access(buffer); @@ -103,36 +120,8 @@ static struct wlr_texture *pixman_texture_from_buffer( texture->buffer = wlr_buffer_lock(buffer); - return &texture->wlr_texture; -} - -static struct wlr_pixman_texture *raster_upload( - struct wlr_pixman_renderer *renderer, struct wlr_raster *wlr_raster) { - struct wlr_texture *texture; - wl_list_for_each(texture, &wlr_raster->sources, link) { - if (wlr_texture_is_pixman(texture)) { - struct wlr_pixman_texture *pixman_tex = - (struct wlr_pixman_texture *)texture; - if (pixman_tex->renderer != renderer) { - continue; - } - return pixman_tex; - } - } - - if (!wlr_raster->buffer) { - // we could possibly do a blit with another texture from another renderer, - // but this is unsupported currently. - return NULL; - } - - texture = pixman_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer); - if (!texture) { - return NULL; - } - - wlr_raster_attach(wlr_raster, texture); - return (struct wlr_pixman_texture *)texture; + wlr_raster_attach(wlr_raster, &texture->wlr_texture); + return texture; } static void texture_destroy(struct wlr_texture *wlr_texture) { @@ -531,7 +520,6 @@ static const struct wlr_renderer_impl renderer_impl = { .render_quad_with_matrix = pixman_render_quad_with_matrix, .get_shm_texture_formats = pixman_get_shm_texture_formats, .get_render_formats = pixman_get_render_formats, - .texture_from_buffer = pixman_texture_from_buffer, .bind_buffer = pixman_bind_buffer, .destroy = pixman_destroy, .preferred_read_format = pixman_preferred_read_format, diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 5d9f01c53..95bc79d3a 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -1003,7 +1003,6 @@ static const struct wlr_renderer_impl renderer_impl = { .destroy = vulkan_destroy, .get_drm_fd = vulkan_get_drm_fd, .get_render_buffer_caps = vulkan_get_render_buffer_caps, - .texture_from_buffer = vulkan_texture_from_buffer, }; // Initializes the VkDescriptorSetLayout and VkPipelineLayout needed diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index ffd409f1e..f28bc3849 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -243,11 +243,9 @@ static struct wlr_vk_texture *vulkan_texture_create( return texture; } -static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_renderer, +static struct wlr_vk_texture *vulkan_texture_from_pixels(struct wlr_vk_renderer *renderer, uint32_t drm_fmt, uint32_t stride, uint32_t width, uint32_t height, const void *data) { - struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); - VkResult res; VkDevice dev = renderer->dev->dev; @@ -371,7 +369,7 @@ static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_r goto error; } - return &texture->wlr_texture; + return texture; error: vulkan_texture_destroy(texture); @@ -606,7 +604,7 @@ error_image: return VK_NULL_HANDLE; } -static struct wlr_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, +static struct wlr_vk_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, struct wlr_dmabuf_attributes *attribs) { struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); @@ -681,7 +679,7 @@ static struct wlr_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_r vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL); texture->dmabuf_imported = true; - return &texture->wlr_texture; + return texture; error: vulkan_texture_destroy(texture); @@ -695,61 +693,37 @@ static void texture_handle_buffer_destroy(struct wl_listener *listener, vulkan_texture_destroy(texture); } -static struct wlr_texture *vulkan_texture_from_dmabuf_buffer( +static struct wlr_vk_texture *vulkan_texture_from_dmabuf_buffer( struct wlr_vk_renderer *renderer, struct wlr_buffer *buffer, struct wlr_dmabuf_attributes *dmabuf) { struct wlr_vk_texture *texture; wl_list_for_each(texture, &renderer->textures, link) { if (texture->buffer == buffer) { wlr_buffer_lock(texture->buffer); - return &texture->wlr_texture; + return texture; } } - struct wlr_texture *wlr_texture = - vulkan_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf); - if (wlr_texture == NULL) { - return false; + texture = vulkan_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf); + if (!texture) { + return NULL; } - texture = vulkan_get_texture(wlr_texture); texture->buffer = wlr_buffer_lock(buffer); texture->buffer_destroy.notify = texture_handle_buffer_destroy; wl_signal_add(&buffer->events.destroy, &texture->buffer_destroy); - return &texture->wlr_texture; -} - -struct wlr_texture *vulkan_texture_from_buffer( - struct wlr_renderer *wlr_renderer, - struct wlr_buffer *buffer) { - struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); - - void *data; - uint32_t format; - size_t stride; - struct wlr_dmabuf_attributes dmabuf; - if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { - return vulkan_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf); - } else if (wlr_buffer_begin_data_ptr_access(buffer, - WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { - struct wlr_texture *tex = vulkan_texture_from_pixels(wlr_renderer, - format, stride, buffer->width, buffer->height, data); - wlr_buffer_end_data_ptr_access(buffer); - return tex; - } else { - return NULL; - } + return texture; } struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer, struct wlr_raster *wlr_raster) { - struct wlr_texture *texture; - wl_list_for_each(texture, &wlr_raster->sources, link) { - if (wlr_texture_is_vk(texture)) { + struct wlr_texture *raster_texture; + wl_list_for_each(raster_texture, &wlr_raster->sources, link) { + if (wlr_texture_is_vk(raster_texture)) { struct wlr_vk_texture *vk_tex = - (struct wlr_vk_texture *)texture; + (struct wlr_vk_texture *)raster_texture; if (vk_tex->renderer != renderer) { continue; } @@ -757,17 +731,31 @@ struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer, } } + struct wlr_buffer *buffer = wlr_raster->buffer; if (!wlr_raster->buffer) { // we could possibly do a blit with another texture from another renderer, // but this is unsupported currently. return NULL; } - texture = vulkan_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer); - if (!texture) { - return NULL; + struct wlr_vk_texture *texture = NULL; + + void *data; + uint32_t format; + size_t stride; + struct wlr_dmabuf_attributes dmabuf; + if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { + texture = vulkan_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf); + } else if (wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + texture = vulkan_texture_from_pixels(renderer, + format, stride, buffer->width, buffer->height, data); + wlr_buffer_end_data_ptr_access(buffer); } - wlr_raster_attach(wlr_raster, texture); - return (struct wlr_vk_texture *)texture; + if (texture) { + wlr_raster_attach(wlr_raster, &texture->wlr_texture); + } + + return texture; } diff --git a/render/wlr_texture.c b/render/wlr_texture.c index e1e621d55..ea2fef89b 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -32,14 +32,6 @@ void wlr_texture_destroy(struct wlr_texture *texture) { } } -struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, - struct wlr_buffer *buffer) { - if (!renderer->impl->texture_from_buffer) { - return NULL; - } - return renderer->impl->texture_from_buffer(renderer, buffer); -} - bool wlr_texture_update_from_buffer(struct wlr_texture *texture, struct wlr_buffer *buffer, pixman_region32_t *damage) { if (!texture->impl->update_from_buffer) { From beaede2df0970e5f4a5dfab8acc5ba406001c049 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 20 Jun 2022 12:34:10 -0400 Subject: [PATCH 13/20] wlr_texture: Update wlr_texture_update_from_buffer to use wlr_raster In the future, these implementations can use compatible texture sources to do fast blit instead. --- include/wlr/render/interface.h | 4 ++-- include/wlr/render/wlr_texture.h | 13 ++++++------- render/gles2/texture.c | 7 ++++--- render/vulkan/texture.c | 7 ++++--- render/wlr_texture.c | 15 +++++++-------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index c072fa2f4..843415da3 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -55,8 +55,8 @@ void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl); struct wlr_texture_impl { - bool (*update_from_buffer)(struct wlr_texture *texture, - struct wlr_buffer *buffer, pixman_region32_t *damage); + bool (*update_from_raster)(struct wlr_texture *texture, + struct wlr_raster *raster, pixman_region32_t *damage); void (*destroy)(struct wlr_texture *texture); }; diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 68131b46c..8ea1b9e3f 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -14,7 +14,6 @@ #include #include -struct wlr_buffer; struct wlr_renderer; struct wlr_texture_impl; @@ -27,17 +26,17 @@ struct wlr_texture { }; /** - * Update a texture with a struct wlr_buffer's contents. + * Update a texture with a struct wlr_raster's contents. * - * The update might be rejected (in case the texture is immutable, the buffer - * has an unsupported type/format, etc), so callers must be prepared to fall - * back to re-creating the texture from scratch via wlr_texture_from_buffer(). + * The update might be rejected (in case the texture is immutable, the raster + * doesn't have a compatible source, unsupported type/format, etc), so callers + * must be prepared to fall back. * * The damage can be used by the renderer as an optimization: only the supplied * region needs to be updated. */ -bool wlr_texture_update_from_buffer(struct wlr_texture *texture, - struct wlr_buffer *buffer, pixman_region32_t *damage); +bool wlr_texture_update_from_raster(struct wlr_texture *texture, + struct wlr_raster *raster, pixman_region32_t *damage); /** * Destroys the texture. diff --git a/render/gles2/texture.c b/render/gles2/texture.c index aac8e6465..e14194cfe 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -44,9 +44,10 @@ static bool check_stride(const struct wlr_pixel_format_info *fmt, return true; } -static bool gles2_texture_update_from_buffer(struct wlr_texture *wlr_texture, - struct wlr_buffer *buffer, pixman_region32_t *damage) { +static bool gles2_texture_update_from_raster(struct wlr_texture *wlr_texture, + struct wlr_raster *raster, pixman_region32_t *damage) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); + struct wlr_buffer *buffer = raster->buffer; if (texture->target != GL_TEXTURE_2D || texture->image != EGL_NO_IMAGE_KHR) { return false; @@ -178,7 +179,7 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .update_from_buffer = gles2_texture_update_from_buffer, + .update_from_raster = gles2_texture_update_from_raster, .destroy = gles2_texture_unref, }; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index f28bc3849..6d3af117b 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -136,9 +136,10 @@ static bool write_pixels(struct wlr_texture *wlr_texture, return true; } -static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture, - struct wlr_buffer *buffer, pixman_region32_t *damage) { +static bool vulkan_texture_update_from_raster(struct wlr_texture *wlr_texture, + struct wlr_raster *raster, pixman_region32_t *damage) { struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); + struct wlr_buffer *buffer = raster->buffer; void *data; uint32_t format; @@ -224,7 +225,7 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .update_from_buffer = vulkan_texture_update_from_buffer, + .update_from_raster = vulkan_texture_update_from_raster, .destroy = vulkan_texture_unref, }; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index ea2fef89b..072a5e260 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -32,19 +32,18 @@ void wlr_texture_destroy(struct wlr_texture *texture) { } } -bool wlr_texture_update_from_buffer(struct wlr_texture *texture, - struct wlr_buffer *buffer, pixman_region32_t *damage) { - if (!texture->impl->update_from_buffer) { +bool wlr_texture_update_from_raster(struct wlr_texture *texture, + struct wlr_raster *raster, pixman_region32_t *damage) { + if (!texture->impl->update_from_raster) { return false; } - if (texture->width != (uint32_t)buffer->width || - texture->height != (uint32_t)buffer->height) { + if (texture->width != raster->width || texture->height != raster->height) { return false; } const pixman_box32_t *extents = pixman_region32_extents(damage); - if (extents->x1 < 0 || extents->y1 < 0 || extents->x2 > buffer->width || - extents->y2 > buffer->height) { + if (extents->x1 < 0 || extents->y1 < 0 || extents->x2 > (int32_t)raster->width || + extents->y2 > (int32_t)raster->height) { return false; } - return texture->impl->update_from_buffer(texture, buffer, damage); + return texture->impl->update_from_raster(texture, raster, damage); } From 605c4aed38b1cfe6ec29b5c1500ee50db69866bd Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 19:40:27 -0400 Subject: [PATCH 14/20] cursor: Move wlr_output_cursor_set_buffer to wlr_raster --- include/wlr/types/wlr_output.h | 4 ++-- types/output/cursor.c | 35 +++++++++++++--------------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 3fce6d8af..e70fdb8b4 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -494,8 +494,8 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, int32_t hotspot_x, int32_t hotspot_y); void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor, struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y); -bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, - struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y); +bool wlr_output_cursor_set_raster(struct wlr_output_cursor *cursor, + struct wlr_raster *raster, int32_t hotspot_x, int32_t hotspot_y); bool wlr_output_cursor_move(struct wlr_output_cursor *cursor, double x, double y); void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor); diff --git a/types/output/cursor.c b/types/output/cursor.c index 7aa858c4d..0193704e2 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -363,24 +363,20 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) { - struct wlr_buffer *buffer = NULL; + struct wlr_raster *raster = NULL; if (pixels) { - struct wlr_readonly_data_buffer *ro_buffer = readonly_data_buffer_create( - DRM_FORMAT_ARGB8888, stride, width, height, pixels); - if (ro_buffer == NULL) { - return false; - } - buffer = &ro_buffer->base; + raster = wlr_raster_from_pixels(DRM_FORMAT_ARGB8888, + stride, width, height, pixels); } - bool ok = wlr_output_cursor_set_buffer(cursor, buffer, hotspot_x, hotspot_y); + bool ok = wlr_output_cursor_set_raster(cursor, raster, hotspot_x, hotspot_y); - wlr_buffer_drop(buffer); + wlr_raster_unlock(raster); return ok; } -bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, - struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y) { +bool wlr_output_cursor_set_raster(struct wlr_output_cursor *cursor, + struct wlr_raster *raster, int32_t hotspot_x, int32_t hotspot_y) { struct wlr_renderer *renderer = cursor->output->renderer; if (!renderer) { return false; @@ -388,9 +384,9 @@ bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, output_cursor_reset(cursor); - if (buffer != NULL) { - cursor->width = buffer->width; - cursor->height = buffer->height; + if (raster) { + cursor->width = raster->width; + cursor->height = raster->height; } else { cursor->width = 0; cursor->height = 0; @@ -404,14 +400,9 @@ bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, wlr_raster_unlock(cursor->raster); cursor->raster = NULL; - cursor->enabled = false; - if (buffer != NULL) { - cursor->raster = wlr_raster_create(buffer); - if (!cursor->raster) { - return false; - } - - cursor->enabled = true; + cursor->enabled = raster; + if (raster) { + cursor->raster = wlr_raster_lock(raster); } if (output_cursor_attempt_hardware(cursor)) { From a193d450ed94a0cf45ccae6da070028970fef2b2 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 24 Jun 2022 21:10:47 -0400 Subject: [PATCH 15/20] wlr_scene_buffer: Rework to use wlr_raster --- examples/scene-graph.c | 4 +- include/wlr/types/wlr_scene.h | 99 ++++++----- tinywl/tinywl.c | 6 +- types/scene/subsurface_tree.c | 4 +- types/scene/surface.c | 89 +++++----- types/scene/wlr_scene.c | 300 +++++++++++++++++----------------- 6 files changed, 252 insertions(+), 250 deletions(-) diff --git a/examples/scene-graph.c b/examples/scene-graph.c index ba5d2d756..2e6fc2a56 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -99,7 +99,7 @@ static void surface_handle_commit(struct wl_listener *listener, void *data) { static void surface_handle_destroy(struct wl_listener *listener, void *data) { struct surface *surface = wl_container_of(listener, surface, destroy); - wlr_scene_node_destroy(&surface->scene_surface->buffer->node); + wlr_scene_node_destroy(&surface->scene_surface->raster->node); wlr_scene_node_destroy(&surface->border->node); wl_list_remove(&surface->destroy.link); wl_list_remove(&surface->link); @@ -129,7 +129,7 @@ static void server_handle_new_surface(struct wl_listener *listener, surface->scene_surface = wlr_scene_surface_create(&server->scene->tree, wlr_surface); - wlr_scene_node_set_position(&surface->scene_surface->buffer->node, + wlr_scene_node_set_position(&surface->scene_surface->raster->node, pos + border_width, pos + border_width); } diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 326dc63cf..12a801481 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -31,21 +31,21 @@ struct wlr_xdg_surface; struct wlr_layer_surface_v1; struct wlr_scene_node; -struct wlr_scene_buffer; +struct wlr_scene_raster; typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node, int sx, int sy, void *data); -typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)( - struct wlr_scene_buffer *buffer, int sx, int sy); +typedef bool (*wlr_scene_raster_point_accepts_input_func_t)( + struct wlr_scene_raster *raster, int sx, int sy); -typedef void (*wlr_scene_buffer_iterator_func_t)( - struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); +typedef void (*wlr_scene_raster_iterator_func_t)( + struct wlr_scene_raster *raster, int sx, int sy, void *user_data); enum wlr_scene_node_type { WLR_SCENE_NODE_TREE, WLR_SCENE_NODE_RECT, - WLR_SCENE_NODE_BUFFER, + WLR_SCENE_NODE_RASTER, }; /** A node is an object in the scene. */ @@ -98,7 +98,7 @@ struct wlr_scene { /** A scene-graph node displaying a single surface. */ struct wlr_scene_surface { - struct wlr_scene_buffer *buffer; + struct wlr_scene_raster *raster; struct wlr_surface *surface; // private state @@ -120,12 +120,12 @@ struct wlr_scene_rect { float color[4]; }; -/** A scene-graph node displaying a buffer */ -struct wlr_scene_buffer { +/** A scene-graph node displaying a raster */ +struct wlr_scene_raster { struct wlr_scene_node node; // May be NULL - struct wlr_buffer *buffer; + struct wlr_raster *raster; struct { struct wl_signal output_enter; // struct wlr_scene_output @@ -135,11 +135,11 @@ struct wlr_scene_buffer { } events; // May be NULL - wlr_scene_buffer_point_accepts_input_func_t point_accepts_input; + wlr_scene_raster_point_accepts_input_func_t point_accepts_input; /** - * The output that the largest area of this buffer is displayed on. - * This may be NULL if the buffer is not currently displayed on any + * The output that the largest area of this raster is displayed on. + * This may be NULL if the raster is not currently displayed on any * outputs. This is the output that should be used for frame callbacks, * presentation feedback, etc. */ @@ -148,7 +148,6 @@ struct wlr_scene_buffer { // private state uint64_t active_outputs; - struct wlr_raster *raster; struct wlr_fbox src_box; int dst_width, dst_height; enum wl_output_transform transform; @@ -240,12 +239,12 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, */ bool wlr_scene_node_coords(struct wlr_scene_node *node, int *lx, int *ly); /** - * Call `iterator` on each buffer in the scene-graph, with the buffer's + * Call `iterator` on each raster in the scene-graph, with the raster's * position in layout coordinates. The function is called from root to leaves * (in rendering order). */ -void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node, - wlr_scene_buffer_iterator_func_t iterator, void *user_data); +void wlr_scene_node_for_each_raster(struct wlr_scene_node *node, + wlr_scene_raster_iterator_func_t iterator, void *user_data); /** * Find the topmost node in this scene-graph that contains the point at the * given layout-local coordinates. (For surface nodes, this means accepting @@ -285,14 +284,14 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent); struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent, struct wlr_surface *surface); -struct wlr_scene_buffer *wlr_scene_buffer_from_node(struct wlr_scene_node *node); +struct wlr_scene_raster *wlr_scene_raster_from_node(struct wlr_scene_node *node); /** - * If this buffer is backed by a surface, then the struct wlr_scene_surface is + * If this raster is backed by a surface, then the struct wlr_scene_surface is * returned. If not, NULL will be returned. */ -struct wlr_scene_surface *wlr_scene_surface_from_buffer( - struct wlr_scene_buffer *scene_buffer); +struct wlr_scene_surface *wlr_scene_surface_from_raster( + struct wlr_scene_raster *scene_raster); /** * Add a node displaying a solid-colored rectangle to the scene-graph. @@ -311,59 +310,59 @@ void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height) void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]); /** - * Add a node displaying a buffer to the scene-graph. + * Add a node displaying a raster to the scene-graph. * - * If the buffer is NULL, this node will not be displayed. + * If the raster is NULL, this node will not be displayed. */ -struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, - struct wlr_buffer *buffer); +struct wlr_scene_raster *wlr_scene_raster_create(struct wlr_scene_tree *parent, + struct wlr_raster *raster); /** - * Sets the buffer's backing buffer. + * Sets the raster's backing raster. * - * If the buffer is NULL, the buffer node will not be displayed. + * If the raster is NULL, the raster node will not be displayed. */ -void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, - struct wlr_buffer *buffer); +void wlr_scene_raster_set_raster(struct wlr_scene_raster *scene_raster, + struct wlr_raster *raster); /** - * Sets the buffer's backing buffer with a custom damage region. + * Sets the raster's backing raster with a custom damage region. * - * The damage region is in buffer-local coordinates. If the region is NULL, - * the whole buffer node will be damaged. + * The damage region is in raster-local coordinates. If the region is NULL, + * the whole raster node will be damaged. */ -void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer, - struct wlr_buffer *buffer, pixman_region32_t *region); +void wlr_scene_raster_set_raster_with_damage(struct wlr_scene_raster *scene_raster, + struct wlr_raster *raster, pixman_region32_t *region); /** - * Set the source rectangle describing the region of the buffer which will be - * sampled to render this node. This allows cropping the buffer. + * Set the source rectangle describing the region of the raster which will be + * sampled to render this node. This allows cropping the raster. * - * If NULL, the whole buffer is sampled. By default, the source box is NULL. + * If NULL, the whole raster is sampled. By default, the source box is NULL. */ -void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_set_source_box(struct wlr_scene_raster *scene_raster, const struct wlr_fbox *box); /** - * Set the destination size describing the region of the scene-graph the buffer - * will be painted onto. This allows scaling the buffer. + * Set the destination size describing the region of the scene-graph the raster + * will be painted onto. This allows scaling the raster. * - * If zero, the destination size will be the buffer size. By default, the + * If zero, the destination size will be the raster size. By default, the * destination size is zero. */ -void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_set_dest_size(struct wlr_scene_raster *scene_raster, int width, int height); /** - * Set a transform which will be applied to the buffer. + * Set a transform which will be applied to the raster. */ -void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_set_transform(struct wlr_scene_raster *scene_raster, enum wl_output_transform transform); /** - * Calls the buffer's frame_done signal. + * Calls the raster's frame_done signal. */ -void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_send_frame_done(struct wlr_scene_raster *scene_raster, struct timespec *now); /** @@ -394,12 +393,12 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output); void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, struct timespec *now); /** - * Call `iterator` on each buffer in the scene-graph visible on the output, - * with the buffer's position in layout coordinates. The function is called + * Call `iterator` on each raster in the scene-graph visible on the output, + * with the raster's position in layout coordinates. The function is called * from root to leaves (in rendering order). */ -void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, - wlr_scene_buffer_iterator_func_t iterator, void *user_data); +void wlr_scene_output_for_each_raster(struct wlr_scene_output *scene_output, + wlr_scene_raster_iterator_func_t iterator, void *user_data); /** * Get a scene-graph output from a struct wlr_output. * diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 4fc8477c7..d99bdb68b 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -343,12 +343,12 @@ static struct tinywl_view *desktop_view_at( * surface in the surface tree of a tinywl_view. */ struct wlr_scene_node *node = wlr_scene_node_at( &server->scene->tree.node, lx, ly, sx, sy); - if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) { + if (node == NULL || node->type != WLR_SCENE_NODE_RASTER) { return NULL; } - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_buffer(scene_buffer); + wlr_scene_surface_from_raster(scene_raster); if (!scene_surface) { return NULL; } diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index 35420abe4..c519d1208 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -81,9 +81,9 @@ static void subsurface_tree_reconfigure( } if (prev != NULL) { - wlr_scene_node_place_above(&subsurface_tree->scene_surface->buffer->node, prev); + wlr_scene_node_place_above(&subsurface_tree->scene_surface->raster->node, prev); } - prev = &subsurface_tree->scene_surface->buffer->node; + prev = &subsurface_tree->scene_surface->raster->node; wl_list_for_each(subsurface, &surface->current.subsurfaces_above, current.link) { diff --git a/types/scene/surface.c b/types/scene/surface.c index e06e77312..d3ab7441b 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -3,7 +3,7 @@ #include #include "types/wlr_scene.h" -static void handle_scene_buffer_output_enter( +static void handle_scene_raster_output_enter( struct wl_listener *listener, void *data) { struct wlr_scene_surface *surface = wl_container_of(listener, surface, output_enter); @@ -12,7 +12,7 @@ static void handle_scene_buffer_output_enter( wlr_surface_send_enter(surface->surface, output->output); } -static void handle_scene_buffer_output_leave( +static void handle_scene_raster_output_leave( struct wl_listener *listener, void *data) { struct wlr_scene_surface *surface = wl_container_of(listener, surface, output_leave); @@ -21,14 +21,14 @@ static void handle_scene_buffer_output_leave( wlr_surface_send_leave(surface->surface, output->output); } -static void handle_scene_buffer_output_present( +static void handle_scene_raster_output_present( struct wl_listener *listener, void *data) { struct wlr_scene_surface *surface = wl_container_of(listener, surface, output_present); struct wlr_scene_output *scene_output = data; - if (surface->buffer->primary_output == scene_output) { - struct wlr_scene *root = scene_node_get_root(&surface->buffer->node); + if (surface->raster->primary_output == scene_output) { + struct wlr_scene *root = scene_node_get_root(&surface->raster->node); struct wlr_presentation *presentation = root->presentation; if (presentation) { @@ -38,7 +38,7 @@ static void handle_scene_buffer_output_present( } } -static void handle_scene_buffer_frame_done( +static void handle_scene_raster_frame_done( struct wl_listener *listener, void *data) { struct wlr_scene_surface *surface = wl_container_of(listener, surface, frame_done); @@ -52,53 +52,60 @@ static void scene_surface_handle_surface_destroy( struct wlr_scene_surface *surface = wl_container_of(listener, surface, surface_destroy); - wlr_scene_node_destroy(&surface->buffer->node); + wlr_scene_node_destroy(&surface->raster->node); } -static void set_buffer_with_surface_state(struct wlr_scene_buffer *scene_buffer, +static void set_raster_with_surface_state(struct wlr_scene_raster *scene_raster, struct wlr_surface *surface) { struct wlr_surface_state *state = &surface->current; struct wlr_fbox src_box; wlr_surface_get_buffer_source_box(surface, &src_box); - wlr_scene_buffer_set_source_box(scene_buffer, &src_box); + wlr_scene_raster_set_source_box(scene_raster, &src_box); - wlr_scene_buffer_set_dest_size(scene_buffer, state->width, state->height); - wlr_scene_buffer_set_transform(scene_buffer, state->transform); + wlr_scene_raster_set_dest_size(scene_raster, state->width, state->height); + wlr_scene_raster_set_transform(scene_raster, state->transform); + struct wlr_raster *raster = NULL; if (surface->current.buffer) { - wlr_scene_buffer_set_buffer_with_damage(scene_buffer, - surface->current.buffer, &surface->buffer_damage); - } else { - wlr_scene_buffer_set_buffer(scene_buffer, NULL); + raster = wlr_raster_create(surface->current.buffer); } + + if (raster) { + wlr_scene_raster_set_raster_with_damage(scene_raster, + raster, &surface->buffer_damage); + } else { + wlr_scene_raster_set_raster(scene_raster, NULL); + } + + wlr_raster_unlock(raster); } static void handle_scene_surface_surface_commit( struct wl_listener *listener, void *data) { struct wlr_scene_surface *surface = wl_container_of(listener, surface, surface_commit); - struct wlr_scene_buffer *scene_buffer = surface->buffer; + struct wlr_scene_raster *scene_raster = surface->raster; - set_buffer_with_surface_state(scene_buffer, surface->surface); + set_raster_with_surface_state(scene_raster, surface->surface); // Even if the surface hasn't submitted damage, schedule a new frame if // the client has requested a wl_surface.frame callback. Check if the node // is visible. If not, the client will never receive a frame_done event // anyway so it doesn't make sense to schedule here. int lx, ly; - bool enabled = wlr_scene_node_coords(&scene_buffer->node, &lx, &ly); + bool enabled = wlr_scene_node_coords(&scene_raster->node, &lx, &ly); if (!wl_list_empty(&surface->surface->current.frame_callback_list) && - surface->buffer->primary_output != NULL && enabled) { - wlr_output_schedule_frame(surface->buffer->primary_output->output); + surface->raster->primary_output != NULL && enabled) { + wlr_output_schedule_frame(surface->raster->primary_output->output); } } -static bool scene_buffer_point_accepts_input(struct wlr_scene_buffer *scene_buffer, +static bool scene_raster_point_accepts_input(struct wlr_scene_raster *scene_raster, int sx, int sy) { struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_buffer(scene_buffer); + wlr_scene_surface_from_raster(scene_raster); return wlr_surface_point_accepts_input(scene_surface->surface, sx, sy); } @@ -123,10 +130,10 @@ static const struct wlr_addon_interface surface_addon_impl = { .destroy = surface_addon_destroy, }; -struct wlr_scene_surface *wlr_scene_surface_from_buffer( - struct wlr_scene_buffer *scene_buffer) { - struct wlr_addon *addon = wlr_addon_find(&scene_buffer->node.addons, - scene_buffer, &surface_addon_impl); +struct wlr_scene_surface *wlr_scene_surface_from_raster( + struct wlr_scene_raster *scene_raster) { + struct wlr_addon *addon = wlr_addon_find(&scene_raster->node.addons, + scene_raster, &surface_addon_impl); if (!addon) { return NULL; } @@ -142,27 +149,27 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent return NULL; } - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(parent, NULL); - if (!scene_buffer) { + struct wlr_scene_raster *scene_raster = wlr_scene_raster_create(parent, NULL); + if (!scene_raster) { free(surface); return NULL; } - surface->buffer = scene_buffer; + surface->raster = scene_raster; surface->surface = wlr_surface; - scene_buffer->point_accepts_input = scene_buffer_point_accepts_input; + scene_raster->point_accepts_input = scene_raster_point_accepts_input; - surface->output_enter.notify = handle_scene_buffer_output_enter; - wl_signal_add(&scene_buffer->events.output_enter, &surface->output_enter); + surface->output_enter.notify = handle_scene_raster_output_enter; + wl_signal_add(&scene_raster->events.output_enter, &surface->output_enter); - surface->output_leave.notify = handle_scene_buffer_output_leave; - wl_signal_add(&scene_buffer->events.output_leave, &surface->output_leave); + surface->output_leave.notify = handle_scene_raster_output_leave; + wl_signal_add(&scene_raster->events.output_leave, &surface->output_leave); - surface->output_present.notify = handle_scene_buffer_output_present; - wl_signal_add(&scene_buffer->events.output_present, &surface->output_present); + surface->output_present.notify = handle_scene_raster_output_present; + wl_signal_add(&scene_raster->events.output_present, &surface->output_present); - surface->frame_done.notify = handle_scene_buffer_frame_done; - wl_signal_add(&scene_buffer->events.frame_done, &surface->frame_done); + surface->frame_done.notify = handle_scene_raster_frame_done; + wl_signal_add(&scene_raster->events.frame_done, &surface->frame_done); surface->surface_destroy.notify = scene_surface_handle_surface_destroy; wl_signal_add(&wlr_surface->events.destroy, &surface->surface_destroy); @@ -170,10 +177,10 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent surface->surface_commit.notify = handle_scene_surface_surface_commit; wl_signal_add(&wlr_surface->events.commit, &surface->surface_commit); - wlr_addon_init(&surface->addon, &scene_buffer->node.addons, - scene_buffer, &surface_addon_impl); + wlr_addon_init(&surface->addon, &scene_raster->node.addons, + scene_raster, &surface_addon_impl); - set_buffer_with_surface_state(scene_buffer, wlr_surface); + set_raster_with_surface_state(scene_raster, wlr_surface); return surface; } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 579b9b648..c8cf3179f 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -28,10 +28,10 @@ static struct wlr_scene_rect *scene_rect_from_node( return (struct wlr_scene_rect *)node; } -struct wlr_scene_buffer *wlr_scene_buffer_from_node( +struct wlr_scene_raster *wlr_scene_raster_from_node( struct wlr_scene_node *node) { - assert(node->type == WLR_SCENE_NODE_BUFFER); - return (struct wlr_scene_buffer *)node; + assert(node->type == WLR_SCENE_NODE_RASTER); + return (struct wlr_scene_raster *)node; } struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { @@ -87,22 +87,21 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_signal_emit_safe(&node->events.destroy, NULL); struct wlr_scene *scene = scene_node_get_root(node); - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + if (node->type == WLR_SCENE_NODE_RASTER) { + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); - uint64_t active = scene_buffer->active_outputs; + uint64_t active = scene_raster->active_outputs; if (active) { struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { if (active & (1ull << scene_output->index)) { - wlr_signal_emit_safe(&scene_buffer->events.output_leave, + wlr_signal_emit_safe(&scene_raster->events.output_leave, scene_output); } } } - wlr_raster_unlock(scene_buffer->raster); - wlr_buffer_unlock(scene_buffer->buffer); + wlr_raster_unlock(scene_raster->raster); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); @@ -182,16 +181,16 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) { static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly); // This function must be called whenever the coordinates/dimensions of a scene -// buffer or scene output change. It is not necessary to call when a scene -// buffer's node is enabled/disabled or obscured by other nodes. -static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, +// raster or scene output change. It is not necessary to call when a scene +// raster's node is enabled/disabled or obscured by other nodes. +static void scene_raster_update_outputs(struct wlr_scene_raster *scene_raster, int lx, int ly, struct wlr_scene *scene, struct wlr_scene_output *ignore) { - struct wlr_box buffer_box = { .x = lx, .y = ly }; - scene_node_get_size(&scene_buffer->node, &buffer_box.width, &buffer_box.height); + struct wlr_box raster_box = { .x = lx, .y = ly }; + scene_node_get_size(&scene_raster->node, &raster_box.width, &raster_box.height); int largest_overlap = 0; - scene_buffer->primary_output = NULL; + scene_raster->primary_output = NULL; uint64_t active_outputs = 0; @@ -215,21 +214,21 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, &output_box.width, &output_box.height); struct wlr_box intersection; - bool intersects = wlr_box_intersection(&intersection, &buffer_box, &output_box); + bool intersects = wlr_box_intersection(&intersection, &raster_box, &output_box); if (intersects) { int overlap = intersection.width * intersection.height; if (overlap > largest_overlap) { largest_overlap = overlap; - scene_buffer->primary_output = scene_output; + scene_raster->primary_output = scene_output; } active_outputs |= 1ull << scene_output->index; } } - uint64_t old_active = scene_buffer->active_outputs; - scene_buffer->active_outputs = active_outputs; + uint64_t old_active = scene_raster->active_outputs; + scene_raster->active_outputs = active_outputs; wl_list_for_each(scene_output, &scene->outputs, link) { uint64_t mask = 1ull << scene_output->index; @@ -237,9 +236,9 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, bool intersects_before = old_active & mask; if (intersects && !intersects_before) { - wlr_signal_emit_safe(&scene_buffer->events.output_enter, scene_output); + wlr_signal_emit_safe(&scene_raster->events.output_enter, scene_output); } else if (!intersects && intersects_before) { - wlr_signal_emit_safe(&scene_buffer->events.output_leave, scene_output); + wlr_signal_emit_safe(&scene_raster->events.output_leave, scene_output); } } } @@ -247,10 +246,10 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, static void _scene_node_update_outputs(struct wlr_scene_node *node, int lx, int ly, struct wlr_scene *scene, struct wlr_scene_output *ignore) { - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); - scene_buffer_update_outputs(scene_buffer, lx, ly, scene, ignore); + if (node->type == WLR_SCENE_NODE_RASTER) { + struct wlr_scene_raster *scene_raster = + wlr_scene_raster_from_node(node); + scene_raster_update_outputs(scene_raster, lx, ly, scene, ignore); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); struct wlr_scene_node *child; @@ -308,57 +307,54 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta scene_node_damage_whole(&rect->node); } -struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, - struct wlr_buffer *buffer) { - struct wlr_scene_buffer *scene_buffer = calloc(1, sizeof(*scene_buffer)); - if (scene_buffer == NULL) { +struct wlr_scene_raster *wlr_scene_raster_create(struct wlr_scene_tree *parent, + struct wlr_raster *raster) { + struct wlr_scene_raster *scene_raster = calloc(1, sizeof(*scene_raster)); + if (scene_raster == NULL) { return NULL; } assert(parent); - scene_node_init(&scene_buffer->node, WLR_SCENE_NODE_BUFFER, parent); + scene_node_init(&scene_raster->node, WLR_SCENE_NODE_RASTER, parent); - if (buffer) { - scene_buffer->buffer = wlr_buffer_lock(buffer); + if (raster) { + scene_raster->raster = wlr_raster_lock(raster); } - wl_signal_init(&scene_buffer->events.output_enter); - wl_signal_init(&scene_buffer->events.output_leave); - wl_signal_init(&scene_buffer->events.output_present); - wl_signal_init(&scene_buffer->events.frame_done); + wl_signal_init(&scene_raster->events.output_enter); + wl_signal_init(&scene_raster->events.output_leave); + wl_signal_init(&scene_raster->events.output_present); + wl_signal_init(&scene_raster->events.frame_done); - scene_node_damage_whole(&scene_buffer->node); + scene_node_damage_whole(&scene_raster->node); - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update_outputs(&scene_raster->node, NULL); - return scene_buffer; + return scene_raster; } -void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer, - struct wlr_buffer *buffer, pixman_region32_t *damage) { - // specifying a region for a NULL buffer doesn't make sense. We need to know - // about the buffer to scale the buffer local coordinates down to scene +void wlr_scene_raster_set_raster_with_damage(struct wlr_scene_raster *scene_raster, + struct wlr_raster *raster, pixman_region32_t *damage) { + // specifying a region for a NULL raster doesn't make sense. We need to know + // about the raster to scale the raster local coordinates down to scene // coordinates. - assert(buffer || !damage); + assert(raster || !damage); - if (buffer != scene_buffer->buffer) { + if (raster != scene_raster->raster) { if (!damage) { - scene_node_damage_whole(&scene_buffer->node); + scene_node_damage_whole(&scene_raster->node); } - wlr_raster_unlock(scene_buffer->raster); - scene_buffer->raster = NULL; - wlr_buffer_unlock(scene_buffer->buffer); + wlr_raster_unlock(scene_raster->raster); + scene_raster->raster = NULL; - if (buffer) { - scene_buffer->buffer = wlr_buffer_lock(buffer); - } else { - scene_buffer->buffer = NULL; + if (raster) { + scene_raster->raster = wlr_raster_lock(raster); } - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update_outputs(&scene_raster->node, NULL); if (!damage) { - scene_node_damage_whole(&scene_buffer->node); + scene_node_damage_whole(&scene_raster->node); } } @@ -367,41 +363,41 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff } int lx, ly; - if (!wlr_scene_node_coords(&scene_buffer->node, &lx, &ly)) { + if (!wlr_scene_node_coords(&scene_raster->node, &lx, &ly)) { return; } - struct wlr_fbox box = scene_buffer->src_box; + struct wlr_fbox box = scene_raster->src_box; if (wlr_fbox_empty(&box)) { box.x = 0; box.y = 0; - if (scene_buffer->transform & WL_OUTPUT_TRANSFORM_90) { - box.width = buffer->height; - box.height = buffer->width; + if (scene_raster->transform & WL_OUTPUT_TRANSFORM_90) { + box.width = raster->height; + box.height = raster->width; } else { - box.width = buffer->width; - box.height = buffer->height; + box.width = raster->width; + box.height = raster->height; } } double scale_x, scale_y; - if (scene_buffer->dst_width || scene_buffer->dst_height) { - scale_x = scene_buffer->dst_width / box.width; - scale_y = scene_buffer->dst_height / box.height; + if (scene_raster->dst_width || scene_raster->dst_height) { + scale_x = scene_raster->dst_width / box.width; + scale_y = scene_raster->dst_height / box.height; } else { - scale_x = buffer->width / box.width; - scale_y = buffer->height / box.height; + scale_x = raster->width / box.width; + scale_y = raster->height / box.height; } pixman_region32_t trans_damage; pixman_region32_init(&trans_damage); wlr_region_transform(&trans_damage, damage, - scene_buffer->transform, buffer->width, buffer->height); + scene_raster->transform, raster->width, raster->height); pixman_region32_intersect_rect(&trans_damage, &trans_damage, box.x, box.y, box.width, box.height); - struct wlr_scene *scene = scene_node_get_root(&scene_buffer->node); + struct wlr_scene *scene = scene_node_get_root(&scene_raster->node); struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { float output_scale = scene_output->output->scale; @@ -421,14 +417,14 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff pixman_region32_fini(&trans_damage); } -void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, - struct wlr_buffer *buffer) { - wlr_scene_buffer_set_buffer_with_damage(scene_buffer, buffer, NULL); +void wlr_scene_raster_set_raster(struct wlr_scene_raster *scene_raster, + struct wlr_raster *raster) { + wlr_scene_raster_set_raster_with_damage(scene_raster, raster, NULL); } -void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_set_source_box(struct wlr_scene_raster *scene_raster, const struct wlr_fbox *box) { - struct wlr_fbox *cur = &scene_buffer->src_box; + struct wlr_fbox *cur = &scene_raster->src_box; if ((wlr_fbox_empty(box) && wlr_fbox_empty(cur)) || (box != NULL && memcmp(cur, box, sizeof(*box)) == 0)) { return; @@ -440,39 +436,39 @@ void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, memset(cur, 0, sizeof(*cur)); } - scene_node_damage_whole(&scene_buffer->node); + scene_node_damage_whole(&scene_raster->node); } -void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_set_dest_size(struct wlr_scene_raster *scene_raster, int width, int height) { - if (scene_buffer->dst_width == width && scene_buffer->dst_height == height) { + if (scene_raster->dst_width == width && scene_raster->dst_height == height) { return; } - scene_node_damage_whole(&scene_buffer->node); - scene_buffer->dst_width = width; - scene_buffer->dst_height = height; - scene_node_damage_whole(&scene_buffer->node); + scene_node_damage_whole(&scene_raster->node); + scene_raster->dst_width = width; + scene_raster->dst_height = height; + scene_node_damage_whole(&scene_raster->node); - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update_outputs(&scene_raster->node, NULL); } -void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_set_transform(struct wlr_scene_raster *scene_raster, enum wl_output_transform transform) { - if (scene_buffer->transform == transform) { + if (scene_raster->transform == transform) { return; } - scene_node_damage_whole(&scene_buffer->node); - scene_buffer->transform = transform; - scene_node_damage_whole(&scene_buffer->node); + scene_node_damage_whole(&scene_raster->node); + scene_raster->transform = transform; + scene_node_damage_whole(&scene_raster->node); - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update_outputs(&scene_raster->node, NULL); } -void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, +void wlr_scene_raster_send_frame_done(struct wlr_scene_raster *scene_raster, struct timespec *now) { - wlr_signal_emit_safe(&scene_buffer->events.frame_done, now); + wlr_signal_emit_safe(&scene_raster->events.frame_done, now); } static void scene_node_get_size(struct wlr_scene_node *node, @@ -488,18 +484,18 @@ static void scene_node_get_size(struct wlr_scene_node *node, *width = scene_rect->width; *height = scene_rect->height; break; - case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (scene_buffer->dst_width > 0 && scene_buffer->dst_height > 0) { - *width = scene_buffer->dst_width; - *height = scene_buffer->dst_height; - } else if (scene_buffer->buffer) { - if (scene_buffer->transform & WL_OUTPUT_TRANSFORM_90) { - *height = scene_buffer->buffer->width; - *width = scene_buffer->buffer->height; + case WLR_SCENE_NODE_RASTER:; + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); + if (scene_raster->dst_width > 0 && scene_raster->dst_height > 0) { + *width = scene_raster->dst_width; + *height = scene_raster->dst_height; + } else if (scene_raster->raster) { + if (scene_raster->transform & WL_OUTPUT_TRANSFORM_90) { + *height = scene_raster->raster->width; + *width = scene_raster->raster->height; } else { - *width = scene_buffer->buffer->width; - *height = scene_buffer->buffer->height; + *width = scene_raster->raster->width; + *height = scene_raster->raster->height; } } break; @@ -687,8 +683,8 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node, return enabled; } -static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node, - int lx, int ly, wlr_scene_buffer_iterator_func_t user_iterator, +static void scene_node_for_each_scene_raster(struct wlr_scene_node *node, + int lx, int ly, wlr_scene_raster_iterator_func_t user_iterator, void *user_data) { if (!node->enabled) { return; @@ -697,21 +693,21 @@ static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node, lx += node->x; ly += node->y; - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - user_iterator(scene_buffer, lx, ly, user_data); + if (node->type == WLR_SCENE_NODE_RASTER) { + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); + user_iterator(scene_raster, lx, ly, user_data); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); struct wlr_scene_node *child; wl_list_for_each(child, &scene_tree->children, link) { - scene_node_for_each_scene_buffer(child, lx, ly, user_iterator, user_data); + scene_node_for_each_scene_raster(child, lx, ly, user_iterator, user_data); } } } -void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node, - wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { - scene_node_for_each_scene_buffer(node, 0, 0, user_iterator, user_data); +void wlr_scene_node_for_each_raster(struct wlr_scene_node *node, + wlr_scene_raster_iterator_func_t user_iterator, void *user_data) { + scene_node_for_each_scene_raster(node, 0, 0, user_iterator, user_data); } struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, @@ -742,11 +738,11 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, scene_node_get_size(node, &width, &height); intersects = lx >= 0 && lx < width && ly >= 0 && ly < height; break; - case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + case WLR_SCENE_NODE_RASTER:; + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); - if (scene_buffer->point_accepts_input) { - intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly); + if (scene_raster->point_accepts_input) { + intersects = scene_raster->point_accepts_input(scene_raster, lx, ly); } else { int width, height; scene_node_get_size(node, &width, &height); @@ -871,24 +867,20 @@ static void render_node_iterator(struct wlr_scene_node *node, render_rect(output, output_damage, scene_rect->color, &dst_box, output->transform_matrix); break; - case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (!scene_buffer->buffer) { + case WLR_SCENE_NODE_RASTER:; + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); + if (!scene_raster->raster) { return; } - if (!scene_buffer->raster) { - scene_buffer->raster = wlr_raster_create(scene_buffer->buffer); - } - - transform = wlr_output_transform_invert(scene_buffer->transform); + transform = wlr_output_transform_invert(scene_raster->transform); wlr_matrix_project_box(matrix, &dst_box, transform, 0.0, output->transform_matrix); - render_raster(output, output_damage, scene_buffer->raster, - &scene_buffer->src_box, &dst_box, matrix); + render_raster(output, output_damage, scene_raster->raster, + &scene_raster->src_box, &dst_box, matrix); - wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); + wlr_signal_emit_safe(&scene_raster->events.output_present, scene_output); break; } } @@ -1143,31 +1135,35 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { } struct wlr_scene_node *node = check_scanout_data.node; - struct wlr_buffer *buffer; + struct wlr_raster *raster; switch (node->type) { - case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (scene_buffer->buffer == NULL || - !wlr_fbox_empty(&scene_buffer->src_box) || - scene_buffer->transform != output->transform) { + case WLR_SCENE_NODE_RASTER:; + struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node); + if (scene_raster->raster == NULL || + !wlr_fbox_empty(&scene_raster->src_box) || + scene_raster->transform != output->transform) { return false; } - buffer = scene_buffer->buffer; + raster = scene_raster->raster; break; default: return false; } - wlr_output_attach_buffer(output, buffer); + if (!raster->buffer) { + return false; + } + + wlr_output_attach_buffer(output, raster->buffer); if (!wlr_output_test(output)) { wlr_output_rollback(output); return false; } - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); - wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); + if (node->type == WLR_SCENE_NODE_RASTER) { + struct wlr_scene_raster *scene_raster = + wlr_scene_raster_from_node(node); + wlr_signal_emit_safe(&scene_raster->events.output_present, scene_output); } return wlr_output_commit(output); @@ -1333,12 +1329,12 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node, return; } - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); + if (node->type == WLR_SCENE_NODE_RASTER) { + struct wlr_scene_raster *scene_raster = + wlr_scene_raster_from_node(node); - if (scene_buffer->primary_output == scene_output) { - wlr_scene_buffer_send_frame_done(scene_buffer, now); + if (scene_raster->primary_output == scene_output) { + wlr_scene_raster_send_frame_done(scene_raster, now); } } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); @@ -1355,9 +1351,9 @@ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, scene_output, now); } -static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, +static void scene_output_for_each_scene_raster(const struct wlr_box *output_box, struct wlr_scene_node *node, int lx, int ly, - wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { + wlr_scene_raster_iterator_func_t user_iterator, void *user_data) { if (!node->enabled) { return; } @@ -1365,31 +1361,31 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, lx += node->x; ly += node->y; - if (node->type == WLR_SCENE_NODE_BUFFER) { + if (node->type == WLR_SCENE_NODE_RASTER) { struct wlr_box node_box = { .x = lx, .y = ly }; scene_node_get_size(node, &node_box.width, &node_box.height); struct wlr_box intersection; if (wlr_box_intersection(&intersection, output_box, &node_box)) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); - user_iterator(scene_buffer, lx, ly, user_data); + struct wlr_scene_raster *scene_raster = + wlr_scene_raster_from_node(node); + user_iterator(scene_raster, lx, ly, user_data); } } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); struct wlr_scene_node *child; wl_list_for_each(child, &scene_tree->children, link) { - scene_output_for_each_scene_buffer(output_box, child, lx, ly, + scene_output_for_each_scene_raster(output_box, child, lx, ly, user_iterator, user_data); } } } -void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, - wlr_scene_buffer_iterator_func_t iterator, void *user_data) { +void wlr_scene_output_for_each_raster(struct wlr_scene_output *scene_output, + wlr_scene_raster_iterator_func_t iterator, void *user_data) { struct wlr_box box = { .x = scene_output->x, .y = scene_output->y }; wlr_output_effective_resolution(scene_output->output, &box.width, &box.height); - scene_output_for_each_scene_buffer(&box, &scene_output->scene->tree.node, 0, 0, + scene_output_for_each_scene_raster(&box, &scene_output->scene->tree.node, 0, 0, iterator, user_data); } From c71800cf8d676de06bf34341ab46826c8f78e16b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 28 May 2022 12:26:26 +0200 Subject: [PATCH 16/20] buffer: move wlr_shm_client_buffer functions to internal header These will get used by wlr_compositor in the next commit. --- include/types/wlr_buffer.h | 3 +++ types/wlr_buffer.c | 7 ++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/types/wlr_buffer.h b/include/types/wlr_buffer.h index e7097ae25..a134e892d 100644 --- a/include/types/wlr_buffer.h +++ b/include/types/wlr_buffer.h @@ -22,6 +22,9 @@ struct wlr_shm_client_buffer { struct wl_listener release; }; +bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer); +struct wlr_shm_client_buffer *shm_client_buffer_from_buffer(struct wlr_buffer *buffer); + /** * A read-only buffer that holds a data pointer. * diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 800a3f992..312fd0688 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -111,9 +111,6 @@ bool wlr_resource_is_buffer(struct wl_resource *resource) { static struct wlr_shm_client_buffer *shm_client_buffer_get_or_create( struct wl_resource *resource); -static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer); -static struct wlr_shm_client_buffer *shm_client_buffer_from_buffer( - struct wlr_buffer *buffer); /* struct wlr_buffer_resource_interface */ static struct wl_array buffer_resource_interfaces = {0}; @@ -217,11 +214,11 @@ bool buffer_is_opaque(struct wlr_buffer *buffer) { static const struct wlr_buffer_impl shm_client_buffer_impl; -static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer) { +bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer) { return buffer->impl == &shm_client_buffer_impl; } -static struct wlr_shm_client_buffer *shm_client_buffer_from_buffer( +struct wlr_shm_client_buffer *shm_client_buffer_from_buffer( struct wlr_buffer *buffer) { assert(buffer_is_shm_client_buffer(buffer)); return (struct wlr_shm_client_buffer *)buffer; From 43a3cbe6aebdb8b4da1fa3cae915a6b1695b15bd Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 28 Jun 2022 13:11:23 -0400 Subject: [PATCH 17/20] Re implement partial texture uploads for surfaces and immediate buffer unlocking --- include/wlr/types/wlr_compositor.h | 10 ++++ types/output/cursor.c | 4 +- types/scene/surface.c | 7 +-- types/wlr_compositor.c | 96 +++++++++++++++++++++++++++++- 4 files changed, 108 insertions(+), 9 deletions(-) diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index a8577087d..a664f7484 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -93,6 +93,13 @@ struct wlr_surface { * The buffer position, in surface-local units. */ int sx, sy; + /** + * The surface's raster, if any. A surface has an attached raster when it + * commits with a non-null buffer in its pending state. A surface will not + * have a raster if it has never committed one or has committed a null + * buffer. + */ + struct wlr_raster *raster; /** * The last commit's buffer damage, in buffer-local coordinates. This * contains both the damage accumulated by the client via @@ -157,6 +164,9 @@ struct wlr_surface { } previous; bool opaque; + + struct wlr_raster *old_raster; + struct wl_listener raster_destroy; }; struct wlr_renderer; diff --git a/types/output/cursor.c b/types/output/cursor.c index 0193704e2..a2d53cd91 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -427,8 +427,8 @@ static void output_cursor_commit(struct wlr_output_cursor *cursor, struct wlr_surface *surface = cursor->surface; assert(surface != NULL); - if (surface->current.buffer) { - cursor->raster = wlr_raster_create(surface->current.buffer); + if (surface->raster) { + cursor->raster = wlr_raster_lock(surface->raster); } // Some clients commit a cursor surface with a NULL buffer to hide it. diff --git a/types/scene/surface.c b/types/scene/surface.c index d3ab7441b..a0cb4de77 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -66,10 +66,7 @@ static void set_raster_with_surface_state(struct wlr_scene_raster *scene_raster, wlr_scene_raster_set_dest_size(scene_raster, state->width, state->height); wlr_scene_raster_set_transform(scene_raster, state->transform); - struct wlr_raster *raster = NULL; - if (surface->current.buffer) { - raster = wlr_raster_create(surface->current.buffer); - } + struct wlr_raster *raster = surface->raster; if (raster) { wlr_scene_raster_set_raster_with_damage(scene_raster, @@ -77,8 +74,6 @@ static void set_raster_with_surface_state(struct wlr_scene_raster *scene_raster, } else { wlr_scene_raster_set_raster(scene_raster, NULL); } - - wlr_raster_unlock(raster); } static void handle_scene_surface_surface_commit( diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index fc00abb2f..46b0025c6 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -415,8 +416,34 @@ static void surface_commit_state(struct wlr_surface *surface, surface_state_move(&surface->current, next); if (invalid_buffer) { + if (!surface->current.buffer) { + wlr_raster_unlock(surface->raster); + surface->raster = NULL; + } + + if (!surface->raster || surface->raster->buffer != surface->current.buffer) { + surface->old_raster = surface->raster; + + if (surface->current.buffer) { + surface->raster = wlr_raster_create(surface->current.buffer); + } + + if (surface->old_raster) { + // By the time we unlock the buffer next the buffer might + // get destroyed. We need to start listening here. + wl_signal_add(&surface->old_raster->events.destroy, + &surface->raster_destroy); + + wlr_raster_unlock(surface->old_raster); + } + } + surface_apply_damage(surface); + + wlr_buffer_unlock(surface->current.buffer); + surface->current.buffer = NULL; } + surface_update_opaque_region(surface); surface_update_input_region(surface); @@ -450,6 +477,29 @@ static void surface_commit_state(struct wlr_surface *surface, } wlr_signal_emit_safe(&surface->events.commit, surface); + + if (surface->old_raster) { + wl_list_remove(&surface->raster_destroy.link); + surface->old_raster = NULL; + } + + if (invalid_buffer && surface->raster) { + // make sure there is at least one source for the raster before removing + // the buffer + if (wl_list_empty(&surface->raster->sources)) { + wlr_renderer_raster_upload(surface->renderer, surface->raster); + } + + // unlock the buffer for shm buffers only. Clients may implement + // optimizations if given the shm buffer back immediately. + // + // For other buffers, we want to continue to lock it so that we + // may direct scanout. + if (!wl_list_empty(&surface->raster->sources) && surface->raster->buffer && + buffer_is_shm_client_buffer(surface->raster->buffer)) { + wlr_raster_remove_buffer(surface->raster); + } + } } static void collect_subsurface_damage_iter(struct wlr_surface *surface, @@ -614,6 +664,8 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { surface_output_destroy(surface_output); } + wlr_raster_unlock(surface->raster); + wlr_signal_emit_safe(&surface->events.destroy, surface); wlr_addon_set_finish(&surface->addons); @@ -640,6 +692,46 @@ static void surface_handle_renderer_destroy(struct wl_listener *listener, wl_resource_destroy(surface->resource); } +static void surface_handle_raster_destroy(struct wl_listener *listener, void *data) { + struct wlr_surface *surface = + wl_container_of(listener, surface, raster_destroy); + + // try to reclaim a texture from this raster so we can try to do a partial + // upload next time. + struct wlr_texture *reuse = NULL; + + struct wlr_texture *texture, *tmp_texture; + wl_list_for_each_safe(texture, tmp_texture, + &surface->old_raster->sources, link) { + // we can be smarter about this, but for now let's just take the first + // texture + wlr_raster_detach(surface->old_raster, texture); + reuse = texture; + break; + } + + surface->old_raster = NULL; + + if (!reuse) { + return; + } + + // if there are already sources for the new raster, don't bother uploading + // if something else already did for us. + if (!wl_list_empty(&surface->raster->sources)) { + wlr_texture_destroy(reuse); + return; + } + + if (!wlr_texture_update_from_raster(reuse, + surface->raster, &surface->buffer_damage)) { + wlr_texture_destroy(reuse); + return; + } + + wlr_raster_attach(surface->raster, reuse); +} + static struct wlr_surface *surface_create(struct wl_client *client, uint32_t version, uint32_t id, struct wlr_renderer *renderer) { struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface)); @@ -680,11 +772,13 @@ static struct wlr_surface *surface_create(struct wl_client *client, wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy); surface->renderer_destroy.notify = surface_handle_renderer_destroy; + surface->raster_destroy.notify = surface_handle_raster_destroy; + return surface; } bool wlr_surface_has_buffer(struct wlr_surface *surface) { - return surface->current.buffer != NULL; + return surface->raster != NULL; } bool wlr_surface_set_role(struct wlr_surface *surface, From fc6fd95e4d35c63f92531ecb05059ef42e2fe7d1 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 14:21:53 -0400 Subject: [PATCH 18/20] wlr_texture: Expose owning renderer --- include/render/gles2.h | 1 - include/render/pixman.h | 1 - include/render/vulkan.h | 1 - include/wlr/render/interface.h | 2 +- include/wlr/render/wlr_texture.h | 2 ++ render/gles2/texture.c | 38 ++++++++++++++++++++------------ render/pixman/renderer.c | 6 ++--- render/vulkan/texture.c | 25 ++++++++++----------- render/wlr_texture.c | 5 ++++- 9 files changed, 46 insertions(+), 35 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 565a73d72..f3542b9d4 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -92,7 +92,6 @@ struct wlr_gles2_buffer { struct wlr_gles2_texture { struct wlr_texture wlr_texture; - struct wlr_gles2_renderer *renderer; struct wl_list link; // wlr_gles2_renderer.textures // Basically: diff --git a/include/render/pixman.h b/include/render/pixman.h index 24847d1a7..6e099e4a9 100644 --- a/include/render/pixman.h +++ b/include/render/pixman.h @@ -37,7 +37,6 @@ struct wlr_pixman_buffer { struct wlr_pixman_texture { struct wlr_texture wlr_texture; - struct wlr_pixman_renderer *renderer; struct wl_list link; // wlr_pixman_renderer.textures pixman_image_t *image; diff --git a/include/render/vulkan.h b/include/render/vulkan.h index a7730225b..a88c90824 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -234,7 +234,6 @@ struct wlr_vk_renderer *vulkan_get_renderer(struct wlr_renderer *r); // State (e.g. image texture) associated with a surface. struct wlr_vk_texture { struct wlr_texture wlr_texture; - struct wlr_vk_renderer *renderer; uint32_t mem_count; VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES]; VkImage image; diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 843415da3..2ad302438 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -60,7 +60,7 @@ struct wlr_texture_impl { void (*destroy)(struct wlr_texture *texture); }; -void wlr_texture_init(struct wlr_texture *texture, +void wlr_texture_init(struct wlr_texture *texture, struct wlr_renderer *rendener, const struct wlr_texture_impl *impl, uint32_t width, uint32_t height); #endif diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 8ea1b9e3f..45bf77047 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -21,6 +21,8 @@ struct wlr_texture { const struct wlr_texture_impl *impl; uint32_t width, height; + struct wlr_renderer *renderer; + struct wlr_raster *raster; struct wl_list link; }; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index e14194cfe..4aa75dcdc 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -79,11 +79,14 @@ static bool gles2_texture_update_from_raster(struct wlr_texture *wlr_texture, return false; } + struct wlr_gles2_renderer *renderer = + gles2_get_renderer(texture->wlr_texture.renderer); + struct wlr_egl_context prev_ctx; wlr_egl_save_context(&prev_ctx); - wlr_egl_make_current(texture->renderer->egl); + wlr_egl_make_current(renderer->egl); - push_gles2_debug(texture->renderer); + push_gles2_debug(renderer); glBindTexture(GL_TEXTURE_2D, texture->tex); @@ -109,7 +112,7 @@ static bool gles2_texture_update_from_raster(struct wlr_texture *wlr_texture, glBindTexture(GL_TEXTURE_2D, 0); - pop_gles2_debug(texture->renderer); + pop_gles2_debug(renderer); wlr_egl_restore_context(&prev_ctx); @@ -127,18 +130,21 @@ static bool gles2_texture_invalidate(struct wlr_gles2_texture *texture) { return true; } + struct wlr_gles2_renderer *renderer = + gles2_get_renderer(texture->wlr_texture.renderer); + struct wlr_egl_context prev_ctx; wlr_egl_save_context(&prev_ctx); - wlr_egl_make_current(texture->renderer->egl); + wlr_egl_make_current(renderer->egl); - push_gles2_debug(texture->renderer); + push_gles2_debug(renderer); glBindTexture(texture->target, texture->tex); - texture->renderer->procs.glEGLImageTargetTexture2DOES(texture->target, + renderer->procs.glEGLImageTargetTexture2DOES(texture->target, texture->image); glBindTexture(texture->target, 0); - pop_gles2_debug(texture->renderer); + pop_gles2_debug(renderer); wlr_egl_restore_context(&prev_ctx); @@ -151,16 +157,20 @@ void gles2_texture_destroy(struct wlr_gles2_texture *texture) { wlr_addon_finish(&texture->buffer_addon); } + struct wlr_gles2_renderer *renderer = + gles2_get_renderer(texture->wlr_texture.renderer); + + struct wlr_egl_context prev_ctx; wlr_egl_save_context(&prev_ctx); - wlr_egl_make_current(texture->renderer->egl); + wlr_egl_make_current(renderer->egl); - push_gles2_debug(texture->renderer); + push_gles2_debug(renderer); glDeleteTextures(1, &texture->tex); - wlr_egl_destroy_image(texture->renderer->egl, texture->image); + wlr_egl_destroy_image(renderer->egl, texture->image); - pop_gles2_debug(texture->renderer); + pop_gles2_debug(renderer); wlr_egl_restore_context(&prev_ctx); @@ -191,8 +201,8 @@ static struct wlr_gles2_texture *gles2_texture_create( wlr_log_errno(WLR_ERROR, "Allocation failed"); return NULL; } - wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height); - texture->renderer = renderer; + wlr_texture_init(&texture->wlr_texture, &renderer->wlr_renderer, + &texture_impl, width, height); wl_list_insert(&renderer->textures, &texture->link); return texture; } @@ -361,7 +371,7 @@ struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *rendere if (wlr_texture_is_gles2(raster_texture)) { struct wlr_gles2_texture *gles2_tex = (struct wlr_gles2_texture *)raster_texture; - if (gles2_tex->renderer != renderer) { + if (gles2_tex->wlr_texture.renderer != &renderer->wlr_renderer) { continue; } return gles2_tex; diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 8b1382c79..87e36f978 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -50,8 +50,8 @@ static struct wlr_pixman_texture *pixman_texture_create( return NULL; } - wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height); - texture->renderer = renderer; + wlr_texture_init(&texture->wlr_texture, &renderer->wlr_renderer, + &texture_impl, width, height); texture->format_info = drm_get_pixel_format_info(drm_format); if (!texture->format_info) { @@ -80,7 +80,7 @@ static struct wlr_pixman_texture *raster_upload( if (wlr_texture_is_pixman(raster_texture)) { struct wlr_pixman_texture *pixman_tex = (struct wlr_pixman_texture *)raster_texture; - if (pixman_tex->renderer != renderer) { + if (pixman_tex->wlr_texture.renderer != &renderer->wlr_renderer) { continue; } return pixman_tex; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 6d3af117b..077e9c391 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -42,8 +42,9 @@ static bool write_pixels(struct wlr_texture *wlr_texture, VkAccessFlags src_access) { VkResult res; struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); - struct wlr_vk_renderer *renderer = texture->renderer; - VkDevice dev = texture->renderer->dev->dev; + struct wlr_vk_renderer *renderer = + vulkan_get_renderer(wlr_texture->renderer); + VkDevice dev = renderer->dev->dev; // make sure assumptions are met assert(src_x + width <= texture->wlr_texture.width); @@ -179,18 +180,16 @@ out: } void vulkan_texture_destroy(struct wlr_vk_texture *texture) { - if (!texture->renderer) { - free(texture); - return; - } + struct wlr_vk_renderer *renderer = + vulkan_get_renderer(texture->wlr_texture.renderer); // when we recorded a command to fill this image _this_ frame, // it has to be executed before the texture can be destroyed. // Add it to the renderer->destroy_textures list, destroying // _after_ the stage command buffer has exectued - if (texture->last_used == texture->renderer->frame) { + if (texture->last_used == renderer->frame) { assert(texture->destroy_link.next == NULL); // not already inserted - wl_list_insert(&texture->renderer->destroy_textures, + wl_list_insert(&renderer->destroy_textures, &texture->destroy_link); return; } @@ -198,9 +197,9 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) { wl_list_remove(&texture->link); wl_list_remove(&texture->buffer_destroy.link); - VkDevice dev = texture->renderer->dev->dev; + VkDevice dev = renderer->dev->dev; if (texture->ds && texture->ds_pool) { - vulkan_free_ds(texture->renderer, texture->ds_pool, texture->ds); + vulkan_free_ds(renderer, texture->ds_pool, texture->ds); } vkDestroyImageView(dev, texture->image_view, NULL); @@ -237,8 +236,8 @@ static struct wlr_vk_texture *vulkan_texture_create( wlr_log_errno(WLR_ERROR, "Allocation failed"); return NULL; } - wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height); - texture->renderer = renderer; + wlr_texture_init(&texture->wlr_texture, &renderer->wlr_renderer, + &texture_impl, width, height); wl_list_insert(&renderer->textures, &texture->link); wl_list_init(&texture->buffer_destroy.link); return texture; @@ -725,7 +724,7 @@ struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer, if (wlr_texture_is_vk(raster_texture)) { struct wlr_vk_texture *vk_tex = (struct wlr_vk_texture *)raster_texture; - if (vk_tex->renderer != renderer) { + if (vk_tex->wlr_texture.renderer != &renderer->wlr_renderer) { continue; } return vk_tex; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 072a5e260..43050152e 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -7,9 +7,12 @@ #include #include "types/wlr_buffer.h" -void wlr_texture_init(struct wlr_texture *texture, +void wlr_texture_init(struct wlr_texture *texture, struct wlr_renderer *renderer, const struct wlr_texture_impl *impl, uint32_t width, uint32_t height) { + assert(renderer); + memset(texture, 0, sizeof(*texture)); + texture->renderer = renderer; texture->impl = impl; texture->width = width; texture->height = height; From 5a7c30966c916f0c58ad77d3ba6933bc1eb59608 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 19:36:04 -0400 Subject: [PATCH 19/20] compositor: Remove notion of primary renderer Uploading textures are done by what outputs intersect the surface, not an arbitrary renderer. If no outputs intersect the surface, the source buffer is locked for longer until the surface is shown, at which point a renderer will be uploaded the buffer. --- examples/fullscreen-shell.c | 2 +- examples/scene-graph.c | 3 +- include/wlr/types/wlr_compositor.h | 9 +-- tinywl/tinywl.c | 2 +- types/wlr_compositor.c | 97 +++++++++++++++--------------- 5 files changed, 52 insertions(+), 61 deletions(-) diff --git a/examples/fullscreen-shell.c b/examples/fullscreen-shell.c index e514649ff..74b889bfa 100644 --- a/examples/fullscreen-shell.c +++ b/examples/fullscreen-shell.c @@ -213,7 +213,7 @@ int main(int argc, char *argv[]) { server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); - wlr_compositor_create(server.wl_display, server.renderer); + wlr_compositor_create(server.wl_display); server.output_layout = wlr_output_layout_create(); diff --git a/examples/scene-graph.c b/examples/scene-graph.c index 2e6fc2a56..9344439ea 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -166,8 +166,7 @@ int main(int argc, char *argv[]) { server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); - struct wlr_compositor *compositor = - wlr_compositor_create(server.display, server.renderer); + struct wlr_compositor *compositor = wlr_compositor_create(server.display); wlr_xdg_shell_create(server.display, 2); diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index a664f7484..3a130e9e7 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -88,7 +88,6 @@ struct wlr_surface_output { struct wlr_surface { struct wl_resource *resource; - struct wlr_renderer *renderer; /** * The buffer position, in surface-local units. */ @@ -154,8 +153,6 @@ struct wlr_surface { // private state - struct wl_listener renderer_destroy; - struct { int32_t scale; enum wl_output_transform transform; @@ -169,11 +166,8 @@ struct wlr_surface { struct wl_listener raster_destroy; }; -struct wlr_renderer; - struct wlr_compositor { struct wl_global *global; - struct wlr_renderer *renderer; struct wl_listener display_destroy; @@ -295,7 +289,6 @@ uint32_t wlr_surface_lock_pending(struct wlr_surface *surface); */ void wlr_surface_unlock_cached(struct wlr_surface *surface, uint32_t seq); -struct wlr_compositor *wlr_compositor_create(struct wl_display *display, - struct wlr_renderer *renderer); +struct wlr_compositor *wlr_compositor_create(struct wl_display *display); #endif diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index d99bdb68b..b4d82592c 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -853,7 +853,7 @@ int main(int argc, char *argv[]) { * to dig your fingers in and play with their behavior if you want. Note that * the clients cannot set the selection directly without compositor approval, * see the handling of the request_set_selection event below.*/ - wlr_compositor_create(server.wl_display, server.renderer); + wlr_compositor_create(server.wl_display); wlr_subcompositor_create(server.wl_display); wlr_data_device_manager_create(server.wl_display); diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 46b0025c6..ebd2e3c30 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -484,14 +484,22 @@ static void surface_commit_state(struct wlr_surface *surface, } if (invalid_buffer && surface->raster) { - // make sure there is at least one source for the raster before removing - // the buffer - if (wl_list_empty(&surface->raster->sources)) { - wlr_renderer_raster_upload(surface->renderer, surface->raster); + // upload the texture to all renderers that this surface intersects. + struct wlr_surface_output *surface_output; + wl_list_for_each(surface_output, &surface->current_outputs, link) { + if (!surface_output->output->renderer) { + continue; + } + + wlr_renderer_raster_upload(surface_output->output->renderer, + surface->raster); } // unlock the buffer for shm buffers only. Clients may implement - // optimizations if given the shm buffer back immediately. + // optimizations if given the shm buffer back immediately. But only do + // this if the raster has a source, if not, that means that the surface + // is not visible on any outputs and let's continue locking the buffer + // until it is visible. // // For other buffers, we want to continue to lock it so that we // may direct scanout. @@ -675,7 +683,6 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { surface_state_destroy_cached(cached); } - wl_list_remove(&surface->renderer_destroy.link); surface_state_finish(&surface->pending); surface_state_finish(&surface->current); pixman_region32_fini(&surface->buffer_damage); @@ -685,55 +692,54 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { free(surface); } -static void surface_handle_renderer_destroy(struct wl_listener *listener, - void *data) { - struct wlr_surface *surface = - wl_container_of(listener, surface, renderer_destroy); - wl_resource_destroy(surface->resource); -} - static void surface_handle_raster_destroy(struct wl_listener *listener, void *data) { struct wlr_surface *surface = wl_container_of(listener, surface, raster_destroy); - // try to reclaim a texture from this raster so we can try to do a partial - // upload next time. - struct wlr_texture *reuse = NULL; - - struct wlr_texture *texture, *tmp_texture; - wl_list_for_each_safe(texture, tmp_texture, - &surface->old_raster->sources, link) { - // we can be smarter about this, but for now let's just take the first - // texture - wlr_raster_detach(surface->old_raster, texture); - reuse = texture; - break; - } - - surface->old_raster = NULL; - - if (!reuse) { - return; - } - // if there are already sources for the new raster, don't bother uploading // if something else already did for us. if (!wl_list_empty(&surface->raster->sources)) { - wlr_texture_destroy(reuse); + surface->old_raster = NULL; return; } - if (!wlr_texture_update_from_raster(reuse, - surface->raster, &surface->buffer_damage)) { - wlr_texture_destroy(reuse); - return; + // try to reclaim the textures from this raster so we can try to do a partial + // upload. + struct wlr_texture *texture, *tmp_texture; + wl_list_for_each_safe(texture, tmp_texture, + &surface->old_raster->sources, link) { + wlr_raster_detach(surface->old_raster, texture); + + bool visible = false; + + // only try to reuse textures of renderers that will see this surface. + struct wlr_surface_output *surface_output; + wl_list_for_each(surface_output, &surface->current_outputs, link) { + if (surface_output->output->renderer == texture->renderer) { + visible = true; + break; + } + } + + if (!visible) { + wlr_texture_destroy(texture); + continue; + } + + if (!wlr_texture_update_from_raster(texture, + surface->raster, &surface->buffer_damage)) { + wlr_texture_destroy(texture); + continue; + } + + wlr_raster_attach(surface->raster, texture); } - wlr_raster_attach(surface->raster, reuse); + surface->old_raster = NULL; } static struct wlr_surface *surface_create(struct wl_client *client, - uint32_t version, uint32_t id, struct wlr_renderer *renderer) { + uint32_t version, uint32_t id) { struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface)); if (!surface) { wl_client_post_no_memory(client); @@ -751,8 +757,6 @@ static struct wlr_surface *surface_create(struct wl_client *client, wlr_log(WLR_DEBUG, "New wlr_surface %p (res %p)", surface, surface->resource); - surface->renderer = renderer; - surface_state_init(&surface->current); surface_state_init(&surface->pending); surface->pending.seq = 1; @@ -769,9 +773,6 @@ static struct wlr_surface *surface_create(struct wl_client *client, pixman_region32_init(&surface->input_region); wlr_addon_set_init(&surface->addons); - wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy); - surface->renderer_destroy.notify = surface_handle_renderer_destroy; - surface->raster_destroy.notify = surface_handle_raster_destroy; return surface; @@ -1151,7 +1152,7 @@ static void compositor_create_surface(struct wl_client *client, struct wlr_compositor *compositor = compositor_from_resource(resource); struct wlr_surface *surface = surface_create(client, - wl_resource_get_version(resource), id, compositor->renderer); + wl_resource_get_version(resource), id); if (surface == NULL) { wl_client_post_no_memory(client); return; @@ -1193,8 +1194,7 @@ static void compositor_handle_display_destroy( free(compositor); } -struct wlr_compositor *wlr_compositor_create(struct wl_display *display, - struct wlr_renderer *renderer) { +struct wlr_compositor *wlr_compositor_create(struct wl_display *display) { struct wlr_compositor *compositor = calloc(1, sizeof(*compositor)); if (!compositor) { return NULL; @@ -1206,7 +1206,6 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display, free(compositor); return NULL; } - compositor->renderer = renderer; wl_signal_init(&compositor->events.new_surface); wl_signal_init(&compositor->events.destroy); From 2a64f19b3bffa8863975a6f5cd5cc0f4a89b79d7 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 10 Jul 2022 00:04:08 -0400 Subject: [PATCH 20/20] wlr_renderer: Add single pixel optimization Instead of uploading a texture and rendering with the texture, add an optimization to use the more optimal render_quad code path. --- render/wlr_renderer.c | 49 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 3817fb98b..166a645fd 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -147,10 +148,58 @@ bool wlr_render_raster_with_matrix(struct wlr_renderer *r, return wlr_render_subraster_with_matrix(r, raster, &box, matrix, alpha); } +static bool try_single_pixel(struct wlr_buffer *buffer, + float color[static 4], const struct wlr_fbox *box, float alpha) { + if (box->width != 1.f || box->height != 1.f || + box->x < 0.f || box->y < 0.f || + box->x >= buffer->width || box->y >= buffer->height) { + return false; + } + + uint32_t x = floor(box->x); + uint32_t y = floor(box->y); + + if (box->x != (float)x || box->y != (float)y) { + return false; + } + + void *data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + return false; + } + + if (format != DRM_FORMAT_ARGB8888) { + wlr_buffer_end_data_ptr_access(buffer); + return false; + } + + size_t pixel_stride = stride / buffer->width; + uint8_t *data_color = &((uint8_t *)data)[pixel_stride * x + stride * y]; + color[0] = data_color[3] * alpha / 255.f; + color[1] = data_color[2] * alpha / 255.f; + color[2] = data_color[1] * alpha / 255.f; + color[3] = data_color[0] * alpha / 255.f; + + wlr_buffer_end_data_ptr_access(buffer); + + return true; +} + bool wlr_render_subraster_with_matrix(struct wlr_renderer *r, struct wlr_raster *raster, const struct wlr_fbox *box, const float matrix[static 9], float alpha) { assert(r->rendering); + + float color[4]; + if (raster->buffer && + try_single_pixel(raster->buffer, (float *)&color, box, alpha)) { + wlr_render_quad_with_matrix(r, color, matrix); + return true; + } + return r->impl->render_subraster_with_matrix(r, raster, box, matrix, alpha); }