diff --git a/include/types/wlr_buffer.h b/include/types/wlr_buffer.h index bdb6e5b7..e7097ae2 100644 --- a/include/types/wlr_buffer.h +++ b/include/types/wlr_buffer.h @@ -69,4 +69,13 @@ struct wlr_dmabuf_buffer *dmabuf_buffer_create( */ bool dmabuf_buffer_drop(struct wlr_dmabuf_buffer *buffer); +/** + * Check whether a buffer is fully opaque. + * + * When true is returned, the buffer is guaranteed to be fully opaque, but the + * reverse is not true: false may be returned in cases where the buffer is fully + * opaque. + */ +bool buffer_is_opaque(struct wlr_buffer *buffer); + #endif diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 4207bd30..7e923353 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -54,7 +54,6 @@ void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl); struct wlr_texture_impl { - bool (*is_opaque)(struct wlr_texture *texture); 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, diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 93fc221c..0f39b8a8 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -36,11 +36,6 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, struct wlr_dmabuf_attributes *attribs); -/** - * Returns true if this texture is using a fully opaque format. - */ -bool wlr_texture_is_opaque(struct wlr_texture *texture); - /** * 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. diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index bff6bc83..034b075b 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -162,6 +162,8 @@ struct wlr_surface { int width, height; int buffer_width, buffer_height; } previous; + + bool opaque; }; struct wlr_renderer; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 57420744..d794e436 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -29,11 +29,6 @@ struct wlr_gles2_texture *gles2_get_texture( return (struct wlr_gles2_texture *)wlr_texture; } -static bool gles2_texture_is_opaque(struct wlr_texture *wlr_texture) { - struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - return !texture->has_alpha; -} - static bool check_stride(const struct wlr_pixel_format_info *fmt, uint32_t stride, uint32_t width) { if (stride % (fmt->bpp / 8) != 0) { @@ -161,7 +156,6 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .is_opaque = gles2_texture_is_opaque, .write_pixels = gles2_texture_write_pixels, .destroy = gles2_texture_unref, }; diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 13db0880..2853b704 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -46,11 +46,6 @@ static struct wlr_pixman_texture *get_texture( return (struct wlr_pixman_texture *)wlr_texture; } -static bool texture_is_opaque(struct wlr_texture *wlr_texture) { - struct wlr_pixman_texture *texture = get_texture(wlr_texture); - return !texture->format_info->has_alpha; -} - static void texture_destroy(struct wlr_texture *wlr_texture) { struct wlr_pixman_texture *texture = get_texture(wlr_texture); wl_list_remove(&texture->link); @@ -61,7 +56,6 @@ static void texture_destroy(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .is_opaque = texture_is_opaque, .destroy = texture_destroy, }; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 26af9867..35b9562e 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -33,14 +33,6 @@ static VkImageAspectFlagBits mem_plane_aspect(unsigned i) { } } -static bool vulkan_texture_is_opaque(struct wlr_texture *wlr_texture) { - struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); - const struct wlr_pixel_format_info *format_info = drm_get_pixel_format_info( - texture->format->drm_format); - assert(format_info); - return !format_info->has_alpha; -} - // Will transition the texture to shaderReadOnlyOptimal layout for reading // from fragment shader later on static bool write_pixels(struct wlr_texture *wlr_texture, @@ -199,7 +191,6 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .is_opaque = vulkan_texture_is_opaque, .write_pixels = vulkan_texture_write_pixels, .destroy = vulkan_texture_unref, }; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 36cbf136..fa864d02 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -71,13 +71,6 @@ struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, return renderer->impl->texture_from_buffer(renderer, buffer); } -bool wlr_texture_is_opaque(struct wlr_texture *texture) { - if (!texture->impl->is_opaque) { - return false; - } - return texture->impl->is_opaque(texture); -} - 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, diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 96e508b2..49e205f3 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -237,6 +237,32 @@ struct wlr_buffer *wlr_buffer_from_resource(struct wl_resource *resource) { return buffer; } +bool buffer_is_opaque(struct wlr_buffer *buffer) { + void *data; + uint32_t format; + size_t stride; + struct wlr_dmabuf_attributes dmabuf; + struct wlr_shm_attributes shm; + if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { + format = dmabuf.format; + } else if (wlr_buffer_get_shm(buffer, &shm)) { + format = shm.format; + } else if (wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + wlr_buffer_end_data_ptr_access(buffer); + } else { + return false; + } + + const struct wlr_pixel_format_info *format_info = + drm_get_pixel_format_info(format); + if (format_info == NULL) { + return false; + } + + 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); diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 8b84a643..c1cdc3b0 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -10,6 +10,7 @@ #include #include #include +#include "types/wlr_buffer.h" #include "types/wlr_region.h" #include "util/signal.h" #include "util/time.h" @@ -336,9 +337,12 @@ static void surface_apply_damage(struct wlr_surface *surface) { 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)) { @@ -372,7 +376,7 @@ static void surface_update_opaque_region(struct wlr_surface *surface) { return; } - if (wlr_texture_is_opaque(texture)) { + if (surface->opaque) { pixman_region32_init_rect(&surface->opaque_region, 0, 0, surface->current.width, surface->current.height); return;