diff --git a/render/gles2/texture.c b/render/gles2/texture.c index b2421d078..1cfd7bab3 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -195,6 +195,8 @@ static bool gles2_texture_read_pixels(struct wlr_texture *wlr_texture, } push_gles2_debug(texture->renderer); + struct wlr_egl_context prev_ctx; + wlr_egl_save_context(&prev_ctx); if (!wlr_egl_make_current(texture->renderer->egl)) { return false; @@ -228,15 +230,58 @@ static bool gles2_texture_read_pixels(struct wlr_texture *wlr_texture, } } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + wlr_egl_restore_context(&prev_ctx); pop_gles2_debug(texture->renderer); return glGetError() == GL_NO_ERROR; } +static uint32_t gles2_texture_preferred_read_format(struct wlr_texture *wlr_texture) { + struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); + + push_gles2_debug(texture->renderer); + struct wlr_egl_context prev_ctx; + wlr_egl_save_context(&prev_ctx); + + uint32_t fmt = DRM_FORMAT_INVALID; + + if (!wlr_egl_make_current(texture->renderer->egl)) { + goto out; + } + + if (!gles2_texture_bind(texture)) { + goto out; + } + + GLint gl_format = -1, gl_type = -1, alpha_size = -1; + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_format); + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_type); + glGetIntegerv(GL_ALPHA_BITS, &alpha_size); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + pop_gles2_debug(texture->renderer); + + const struct wlr_gles2_pixel_format *pix_fmt = + get_gles2_format_from_gl(gl_format, gl_type, alpha_size > 0); + if (pix_fmt != NULL) { + fmt = pix_fmt->drm_format; + goto out; + } + + if (texture->renderer->exts.EXT_read_format_bgra) { + fmt = DRM_FORMAT_XRGB8888; + goto out; + } + +out: + wlr_egl_restore_context(&prev_ctx); + return fmt; +} + static const struct wlr_texture_impl texture_impl = { .update_from_buffer = gles2_texture_update_from_buffer, .read_pixels = gles2_texture_read_pixels, + .preferred_read_format = gles2_texture_preferred_read_format, .destroy = handle_gles2_texture_destroy, }; diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 2c92e6629..13049e8fa 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -115,8 +115,16 @@ static bool texture_read_pixels(struct wlr_texture *wlr_texture, return true; } +static uint32_t pixman_texture_preferred_read_format(struct wlr_texture *wlr_texture) { + struct wlr_pixman_texture *texture = get_texture(wlr_texture); + + pixman_format_code_t pixman_format = pixman_image_get_format(texture->image); + return get_drm_format_from_pixman(pixman_format); +} + static const struct wlr_texture_impl texture_impl = { .read_pixels = texture_read_pixels, + .preferred_read_format = pixman_texture_preferred_read_format, .destroy = texture_destroy, }; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 16c48356b..20aa12f1e 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -262,9 +262,15 @@ static bool vulkan_texture_read_pixels(struct wlr_texture *wlr_texture, options->format, options->stride, src.width, src.height, src.x, src.y, 0, 0, p); } +static uint32_t vulkan_texture_preferred_read_format(struct wlr_texture *wlr_texture) { + struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); + return texture->format->drm; +} + static const struct wlr_texture_impl texture_impl = { .update_from_buffer = vulkan_texture_update_from_buffer, .read_pixels = vulkan_texture_read_pixels, + .preferred_read_format = vulkan_texture_preferred_read_format, .destroy = vulkan_texture_unref, };