diff options
author | Nicolai Hähnle <[email protected]> | 2016-06-08 13:01:05 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2016-06-21 10:54:12 +0200 |
commit | b74c23138c34b908a05e5af98b231634df1b1b74 (patch) | |
tree | 5c3b2d75f79acffe41aeaefed67f733e35383619 | |
parent | f9ddd52317caf14a21ec7c040fd4bb944f9842e4 (diff) |
st/mesa: move ReadPixels blit into a separate function
Reviewed-by: Marek Olšák <[email protected]>
-rw-r--r-- | src/mesa/state_tracker/st_cb_readpixels.c | 130 |
1 files changed, 78 insertions, 52 deletions
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 42ff73b0691..ef575baca9d 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -219,6 +219,79 @@ fail: } /** + * Create a staging texture and blit the requested region to it. + */ +static struct pipe_resource * +blit_to_staging(struct st_context *st, struct st_renderbuffer *strb, + bool invert_y, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, + enum pipe_format src_format, enum pipe_format dst_format) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_resource dst_templ; + struct pipe_resource *dst; + struct pipe_blit_info blit; + + /* We are creating a texture of the size of the region being read back. + * Need to check for NPOT texture support. */ + if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) && + (!util_is_power_of_two(width) || + !util_is_power_of_two(height))) + return NULL; + + /* create the destination texture */ + memset(&dst_templ, 0, sizeof(dst_templ)); + dst_templ.target = PIPE_TEXTURE_2D; + dst_templ.format = dst_format; + dst_templ.bind = PIPE_BIND_TRANSFER_READ; + if (util_format_is_depth_or_stencil(dst_format)) + dst_templ.bind |= PIPE_BIND_DEPTH_STENCIL; + else + dst_templ.bind |= PIPE_BIND_RENDER_TARGET; + dst_templ.usage = PIPE_USAGE_STAGING; + + st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1, + &dst_templ.width0, &dst_templ.height0, + &dst_templ.depth0, &dst_templ.array_size); + + dst = screen->resource_create(screen, &dst_templ); + if (!dst) + return NULL; + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = strb->texture; + blit.src.level = strb->surface->u.tex.level; + blit.src.format = src_format; + blit.dst.resource = dst; + blit.dst.level = 0; + blit.dst.format = dst->format; + blit.src.box.x = x; + blit.dst.box.x = 0; + blit.src.box.y = y; + blit.dst.box.y = 0; + blit.src.box.z = strb->surface->u.tex.first_layer; + blit.dst.box.z = 0; + blit.src.box.width = blit.dst.box.width = width; + blit.src.box.height = blit.dst.box.height = height; + blit.src.box.depth = blit.dst.box.depth = 1; + blit.mask = st_get_blit_mask(strb->Base._BaseFormat, format); + blit.filter = PIPE_TEX_FILTER_NEAREST; + blit.scissor_enable = FALSE; + + if (invert_y) { + blit.src.box.y = strb->Base.Height - blit.src.box.y; + blit.src.box.height = -blit.src.box.height; + } + + /* blit */ + st->pipe->blit(st->pipe, &blit); + + return dst; +} + +/** * This uses a blit to copy the read buffer to a texture format which matches * the format and type combo and then a fast read-back is done using memcpy. * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is @@ -245,9 +318,7 @@ st_ReadPixels(struct gl_context *ctx, GLint x, GLint y, struct pipe_screen *screen = pipe->screen; struct pipe_resource *src; struct pipe_resource *dst = NULL; - struct pipe_resource dst_templ; enum pipe_format dst_format, src_format; - struct pipe_blit_info blit; unsigned bind = PIPE_BIND_TRANSFER_READ; struct pipe_transfer *tex_xfer; ubyte *map = NULL; @@ -316,14 +387,6 @@ st_ReadPixels(struct gl_context *ctx, GLint x, GLint y, return; } - /* We are creating a texture of the size of the region being read back. - * Need to check for NPOT texture support. */ - if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) && - (!util_is_power_of_two(width) || - !util_is_power_of_two(height))) { - goto fallback; - } - /* See if the texture format already matches the format and type, * in which case the memcpy-based fast path will likely be used and * we don't have to blit. */ @@ -336,49 +399,12 @@ st_ReadPixels(struct gl_context *ctx, GLint x, GLint y, goto fallback; } - /* create the destination texture */ - memset(&dst_templ, 0, sizeof(dst_templ)); - dst_templ.target = PIPE_TEXTURE_2D; - dst_templ.format = dst_format; - dst_templ.bind = bind; - dst_templ.usage = PIPE_USAGE_STAGING; - - st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1, - &dst_templ.width0, &dst_templ.height0, - &dst_templ.depth0, &dst_templ.array_size); - - dst = screen->resource_create(screen, &dst_templ); - if (!dst) { + dst = blit_to_staging(st, strb, + st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP, + x, y, width, height, format, + src_format, dst_format); + if (!dst) goto fallback; - } - - memset(&blit, 0, sizeof(blit)); - blit.src.resource = src; - blit.src.level = strb->surface->u.tex.level; - blit.src.format = src_format; - blit.dst.resource = dst; - blit.dst.level = 0; - blit.dst.format = dst->format; - blit.src.box.x = x; - blit.dst.box.x = 0; - blit.src.box.y = y; - blit.dst.box.y = 0; - blit.src.box.z = strb->surface->u.tex.first_layer; - blit.dst.box.z = 0; - blit.src.box.width = blit.dst.box.width = width; - blit.src.box.height = blit.dst.box.height = height; - blit.src.box.depth = blit.dst.box.depth = 1; - blit.mask = st_get_blit_mask(rb->_BaseFormat, format); - blit.filter = PIPE_TEX_FILTER_NEAREST; - blit.scissor_enable = FALSE; - - if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { - blit.src.box.y = rb->Height - blit.src.box.y; - blit.src.box.height = -blit.src.box.height; - } - - /* blit */ - st->pipe->blit(st->pipe, &blit); /* map resources */ pixels = _mesa_map_pbo_dest(ctx, pack, pixels); |