diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 1e352c6e6..bc66e7d54 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -37,6 +37,8 @@ struct wlr_texture_read_pixels_options { uint32_t dst_x, dst_y; /** Source box of the texture to read from. If empty, the full texture is assumed. */ const struct wlr_box src_box; + /** Region of interest within source box. If NULL, the full region is assumed to be of interest. */ + struct pixman_region32 *roi; }; bool wlr_texture_read_pixels(struct wlr_texture *texture, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 9a967ebdb..a339bd0e7 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -214,7 +214,19 @@ static bool gles2_texture_read_pixels(struct wlr_texture *wlr_texture, // Under these particular conditions, we can read the pixels with only // one glReadPixels call - glReadPixels(src.x, src.y, src.width, src.height, fmt->gl_format, fmt->gl_type, p); + int y_offset = 0; + int src_height = src.height; + int data_offset = 0; + if (options->roi) { + struct pixman_box32 *ext = + pixman_region32_extents(options->roi); + y_offset = ext->y1; + src_height = ext->y2 - ext->y1; + data_offset = y_offset * options->stride; + } + + glReadPixels(src.x, src.y + y_offset, src.width, src_height, + fmt->gl_format, fmt->gl_type, p + data_offset); } else { // Unfortunately GLES2 doesn't support GL_PACK_ROW_LENGTH, so we have to read // the lines out row by row diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 4631a33ab..25229562c 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -107,9 +107,12 @@ static bool texture_read_pixels(struct wlr_texture *wlr_texture, pixman_image_t *dst = pixman_image_create_bits_no_clear(fmt, src.width, src.height, p, options->stride); + if (options->roi) { + pixman_image_set_clip_region32(dst, options->roi); + } + pixman_image_composite32(PIXMAN_OP_SRC, texture->image, NULL, dst, src.x, src.y, 0, 0, 0, 0, src.width, src.height); - pixman_image_unref(dst); return true;