diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 432f0427b..a44cc587f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -1491,7 +1492,7 @@ static void handle_page_flip(int fd, unsigned seq, * interface. */ if (!drm->parent && plane->current_fb && - wlr_client_buffer_get(plane->current_fb->wlr_buf)) { + wlr_dmabuf_v1_buffer_is_buffer(plane->current_fb->wlr_buf)) { present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY; } 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 bc4bb7a86..74b889bfa 100644 --- a/examples/fullscreen-shell.c +++ b/examples/fullscreen-shell.c @@ -56,8 +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); - if (texture == NULL) { + struct wlr_raster *raster = wlr_raster_create(surface->current.buffer); + if (raster == NULL) { return; } @@ -74,9 +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_raster_unlock(raster); } static void output_handle_frame(struct wl_listener *listener, void *data) { @@ -211,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/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/scene-graph.c b/examples/scene-graph.c index ba5d2d756..9344439ea 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); } @@ -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/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 714bacf56..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: @@ -123,13 +122,11 @@ 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); 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/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 1cba5a192..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; @@ -255,13 +254,12 @@ 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, 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/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/include/wlr/render/interface.h b/include/wlr/render/interface.h index 7e923353e..2ad302438 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; @@ -27,8 +28,10 @@ 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 (*render_subtexture_with_matrix)(struct wlr_renderer *renderer, - struct wlr_texture *texture, const struct wlr_fbox *box, + bool (*raster_upload)(struct wlr_renderer *renderer, + struct wlr_raster *raster); + 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]); @@ -46,22 +49,18 @@ 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, 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_raster)(struct wlr_texture *texture, + struct wlr_raster *raster, pixman_region32_t *damage); 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/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/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index 50ba6b215..9b2dc0eb0 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -48,22 +48,30 @@ 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); + /** - * Renders the requested texture. + * 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_render_texture(struct wlr_renderer *r, struct wlr_texture *texture, +bool wlr_renderer_raster_upload(struct wlr_renderer *r, + struct wlr_raster *raster); +/** + * Renders the requested raster. + */ +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/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 0f39b8a89..45bf77047 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -9,51 +9,40 @@ #ifndef WLR_RENDER_WLR_TEXTURE_H #define WLR_RENDER_WLR_TEXTURE_H +#include #include #include -#include +#include -struct wlr_buffer; struct wlr_renderer; struct wlr_texture_impl; 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; }; /** - * 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); - -/** - * 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 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_raster's contents. + * + * 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_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_raster(struct wlr_texture *texture, + struct wlr_raster *raster, pixman_region32_t *damage); /** * Destroys the 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/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 17b93e5c4..46a9198bc 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -132,53 +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; - - // If the client buffer has been created from a wl_shm buffer - uint32_t shm_source_format; -}; - -/** - * 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..3a130e9e7 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -88,18 +88,17 @@ 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. */ 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 @@ -154,8 +153,6 @@ struct wlr_surface { // private state - struct wl_listener renderer_destroy; - struct { int32_t scale; enum wl_output_transform transform; @@ -164,13 +161,13 @@ struct wlr_surface { } previous; bool opaque; -}; -struct wlr_renderer; + struct wlr_raster *old_raster; + struct wl_listener raster_destroy; +}; struct wlr_compositor { struct wl_global *global; - struct wlr_renderer *renderer; struct wl_listener display_destroy; @@ -199,13 +196,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. @@ -299,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/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/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 4f8bff0df..e70fdb8b4 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; @@ -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/include/wlr/types/wlr_raster.h b/include/wlr/types/wlr_raster.h new file mode 100644 index 000000000..f10a09b3b --- /dev/null +++ b/include/wlr/types/wlr_raster.h @@ -0,0 +1,84 @@ +/* + * 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); + +/** + * 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/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index a87379210..784e77b59 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; @@ -30,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 +99,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 +121,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 +136,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 +149,6 @@ struct wlr_scene_buffer { // private state uint64_t active_outputs; - struct wlr_texture *texture; struct wlr_fbox src_box; int dst_width, dst_height; enum wl_output_transform transform; @@ -240,12 +240,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 +285,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 +311,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 +394,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/render/gles2/renderer.c b/render/gles2/renderer.c index c00a7f51c..a032867bf 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 @@ -529,6 +531,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, @@ -536,7 +545,8 @@ static const struct wlr_renderer_impl renderer_impl = { .end = gles2_end, .clear = gles2_clear, .scissor = gles2_scissor, - .render_subtexture_with_matrix = gles2_render_subtexture_with_matrix, + .raster_upload = _gles2_raster_upload, + .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, @@ -545,7 +555,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 d794e436b..4aa75dcdc 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; @@ -44,14 +44,25 @@ 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_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) { - 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,24 +74,37 @@ 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; } + 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); - 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); @@ -88,10 +112,12 @@ static bool gles2_texture_write_pixels(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); + wlr_buffer_end_data_ptr_access(buffer); + return true; } @@ -104,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); @@ -128,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); @@ -156,7 +189,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_raster = gles2_texture_update_from_raster, .destroy = gles2_texture_unref, }; @@ -168,18 +201,16 @@ 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; } -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) { @@ -231,7 +262,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( @@ -303,7 +334,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 = @@ -313,16 +344,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); @@ -330,28 +361,50 @@ 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; + return 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); +struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_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_gles2(raster_texture)) { + struct wlr_gles2_texture *gles2_tex = + (struct wlr_gles2_texture *)raster_texture; + if (gles2_tex->wlr_texture.renderer != &renderer->wlr_renderer) { + continue; + } + return gles2_tex; + } + } + + 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; + } + + 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)) { - return gles2_texture_from_dmabuf_buffer(renderer, 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)) { - struct wlr_texture *tex = gles2_texture_from_pixels(wlr_renderer, + texture = gles2_texture_from_pixels(renderer, format, stride, buffer->width, buffer->height, data); wlr_buffer_end_data_ptr_access(buffer); - return tex; - } else { - return NULL; } + + 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 2853b7047..87e36f978 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -40,14 +40,92 @@ 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) { + 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, &renderer->wlr_renderer, + &texture_impl, width, height); + + 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_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->wlr_texture.renderer != &renderer->wlr_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)) { + 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); + + wlr_raster_attach(wlr_raster, &texture->wlr_texture); + return 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); @@ -215,13 +293,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; @@ -334,72 +415,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,16 +503,23 @@ 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, - .render_subtexture_with_matrix = pixman_render_subtexture_with_matrix, + .raster_upload = pixman_raster_upload, + .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, - .texture_from_buffer = pixman_texture_from_buffer, .bind_buffer = pixman_bind_buffer, .destroy = pixman_destroy, .preferred_read_format = pixman_preferred_read_format, @@ -528,11 +550,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); diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index c373269df..95bc79d3a 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); @@ -976,13 +979,21 @@ 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, - .render_subtexture_with_matrix = vulkan_render_subtexture_with_matrix, + .raster_upload = _vulkan_raster_upload, + .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, @@ -992,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 35b9562e7..077e9c391 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; } @@ -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); @@ -136,27 +137,59 @@ 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_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; + 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) { - 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; } @@ -164,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); @@ -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_raster = vulkan_texture_update_from_raster, .destroy = vulkan_texture_unref, }; @@ -203,18 +236,16 @@ 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; } -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; @@ -338,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); @@ -573,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); @@ -648,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); @@ -662,50 +693,69 @@ 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; + return 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); +struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_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_vk(raster_texture)) { + struct wlr_vk_texture *vk_tex = + (struct wlr_vk_texture *)raster_texture; + if (vk_tex->wlr_texture.renderer != &renderer->wlr_renderer) { + continue; + } + return vk_tex; + } + } + + 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; + } + + 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)) { - return vulkan_texture_from_dmabuf_buffer(renderer, 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)) { - struct wlr_texture *tex = vulkan_texture_from_pixels(wlr_renderer, + texture = vulkan_texture_from_pixels(renderer, format, stride, buffer->width, buffer->height, data); wlr_buffer_end_data_ptr_access(buffer); - return tex; - } else { - return NULL; } + + if (texture) { + wlr_raster_attach(wlr_raster, &texture->wlr_texture); + } + + return texture; } diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 478db7453..166a645fd 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,8 @@ void wlr_renderer_init(struct wlr_renderer *renderer, assert(impl->begin); assert(impl->clear); assert(impl->scissor); - assert(impl->render_subtexture_with_matrix); + assert(impl->raster_upload); + assert(impl->render_subraster_with_matrix); assert(impl->render_quad_with_matrix); assert(impl->get_shm_texture_formats); assert(impl->get_render_buffer_caps); @@ -113,39 +115,92 @@ void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box) { r->impl->scissor(r, box); } -bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture, +bool wlr_renderer_raster_upload(struct wlr_renderer *r, + struct wlr_raster *raster) { + return r->impl->raster_upload(r, raster); +} + +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, +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); - return r->impl->render_subtexture_with_matrix(r, texture, + + 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); } diff --git a/render/wlr_texture.c b/render/wlr_texture.c index fa864d02b..43050152e 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -4,80 +4,49 @@ #include #include #include +#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; } 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); } } -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_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) { - return NULL; - } - 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_raster(struct wlr_texture *texture, + struct wlr_raster *raster, pixman_region32_t *damage) { + if (!texture->impl->update_from_raster) { return false; } - return texture->impl->write_pixels(texture, stride, width, height, - src_x, src_y, dst_x, dst_y, data); + 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 > (int32_t)raster->width || + extents->y2 > (int32_t)raster->height) { + return false; + } + return texture->impl->update_from_raster(texture, raster, damage); } diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 4fc8477c7..b4d82592c 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; } @@ -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/meson.build b/types/meson.build index 19360eb7d..d0fcdef45 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/output/cursor.c b/types/output/cursor.c index 85973ce93..a2d53cd91 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -93,11 +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 (cursor->surface != NULL) { - texture = wlr_surface_get_texture(cursor->surface); - } - if (texture == NULL) { + if (!cursor->raster) { return; } @@ -121,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); @@ -234,29 +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) { - texture = wlr_surface_get_texture(cursor->surface); 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; } } @@ -288,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]; @@ -317,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); @@ -337,24 +332,16 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { return false; } - 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 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 = { @@ -376,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; @@ -401,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; @@ -414,16 +397,12 @@ 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) { - return false; - } - cursor->enabled = true; + cursor->enabled = raster; + if (raster) { + cursor->raster = wlr_raster_lock(raster); } if (output_cursor_attempt_hardware(cursor)) { @@ -442,9 +421,16 @@ 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); + if (surface->raster) { + cursor->raster = wlr_raster_lock(surface->raster); + } + // 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; @@ -589,7 +575,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/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 d3a0b035f..a0cb4de77 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,25 +52,27 @@ 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); - if (surface->buffer) { - wlr_scene_buffer_set_buffer_with_damage(scene_buffer, - &surface->buffer->base, &surface->buffer_damage); + struct wlr_raster *raster = surface->raster; + + if (raster) { + wlr_scene_raster_set_raster_with_damage(scene_raster, + raster, &surface->buffer_damage); } else { - wlr_scene_buffer_set_buffer(scene_buffer, NULL); + wlr_scene_raster_set_raster(scene_raster, NULL); } } @@ -78,27 +80,27 @@ 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 +125,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 +144,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 +172,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 3c4581163..3e7eb672e 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_texture_destroy(scene_buffer->texture); - 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); @@ -196,16 +195,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; @@ -229,21 +228,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; @@ -251,9 +250,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); } } } @@ -261,10 +260,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; @@ -322,57 +321,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_texture_destroy(scene_buffer->texture); - scene_buffer->texture = 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); } } @@ -381,41 +377,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; @@ -435,14 +431,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; @@ -454,56 +450,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); -} - -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; - } - - scene_buffer->texture = - wlr_texture_from_buffer(renderer, scene_buffer->buffer); - return scene_buffer->texture; + wlr_signal_emit_safe(&scene_raster->events.frame_done, now); } static void scene_node_get_size(struct wlr_scene_node *node, @@ -519,18 +498,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; @@ -718,8 +697,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; @@ -728,21 +707,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, @@ -773,11 +752,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); @@ -841,8 +820,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; @@ -850,8 +829,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; } @@ -865,7 +844,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); @@ -890,7 +869,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) { @@ -903,26 +881,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; } - struct wlr_renderer *renderer = output->renderer; - texture = scene_buffer_get_texture(scene_buffer, renderer); - if (texture == NULL) { - return; - } - - 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_texture(output, output_damage, texture, &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; } } @@ -1181,31 +1153,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); @@ -1371,12 +1347,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); @@ -1393,9 +1369,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; } @@ -1403,31 +1379,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); } diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 49e205f3c..312fd0688 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -109,59 +109,8 @@ 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); -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}; @@ -263,99 +212,13 @@ 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; - - 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); - - 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; - } - - 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; -} - 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; diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index c1cdc3b05..ebd2e3c30 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -333,45 +334,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; } @@ -445,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); @@ -480,6 +477,37 @@ 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) { + // 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. 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. + 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, @@ -644,6 +672,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); @@ -653,28 +683,63 @@ 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); 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); } -static void surface_handle_renderer_destroy(struct wl_listener *listener, - void *data) { +static void surface_handle_raster_destroy(struct wl_listener *listener, void *data) { struct wlr_surface *surface = - wl_container_of(listener, surface, renderer_destroy); - wl_resource_destroy(surface->resource); + wl_container_of(listener, surface, raster_destroy); + + // 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)) { + surface->old_raster = NULL; + 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); + } + + 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); @@ -692,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; @@ -710,21 +773,13 @@ 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; } -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->raster != NULL; } bool wlr_surface_set_role(struct wlr_surface *surface, @@ -1097,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; @@ -1139,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; @@ -1152,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); diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index a124d5212..7d2e013ba 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); @@ -197,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, @@ -327,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, @@ -350,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); diff --git a/types/wlr_raster.c b/types/wlr_raster.c new file mode 100644 index 000000000..3bc408ef2 --- /dev/null +++ b/types/wlr_raster.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include "types/wlr_buffer.h" +#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); +} + +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; +} 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; }