diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index caf3939..1482f66 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -45,6 +45,7 @@ #include "st_context.h" #include "st_cb_bitmap.h" #include "st_cb_readpixels.h" +#include "st_cb_bufferobjects.h" #include "st_cb_fbo.h" #include "st_format.h" #include "st_public.h" @@ -181,6 +182,8 @@ st_accelerated_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, GLint row, col, dy, dstStride; struct gl_pixelstore_attrib clippedPacking = *pack; struct pipe_transfer *trans; + struct st_buffer_object *st_obj = st_buffer_object(pack->BufferObj); + boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); enum combination { A8R8G8B8_UNORM_TO_RGBA_UBYTE, @@ -189,20 +192,14 @@ st_accelerated_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, A8R8G8B8_UNORM_TO_FLOAT } combo; - if (!screen->get_tex_transfer || - !screen->tex_transfer_destroy || - !screen->transfer_map || - !screen->transfer_unmap) { - return GL_FALSE; - } - if (ctx->_ImageTransferState) return GL_FALSE; if (strb->format != PIPE_FORMAT_A8R8G8B8_UNORM) return GL_FALSE; - if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) { + if (format == GL_RGBA && + ((type == GL_UNSIGNED_BYTE) || (type == GL_UNSIGNED_INT_8_8_8_8))) { combo = A8R8G8B8_UNORM_TO_RGBA_UBYTE; } else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) { @@ -218,7 +215,79 @@ st_accelerated_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, return GL_FALSE; } - if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + /* Try issue a copy to PBO if possible */ + if (st_obj && ( + (combo == A8R8G8B8_UNORM_TO_RGBA_UBYTE) || + (combo == A8R8G8B8_UNORM_TO_BGRA_UINT))) { + struct pipe_surface *surface = NULL; + struct pipe_surface *surf = NULL; + struct pipe_texture template; + struct pipe_texture *tex; + GLuint stride = (width * 4); + + surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ); + if (!surf) { + return GL_FALSE; + } + + template.target = PIPE_TEXTURE_2D; + template.compressed = 0; + template.format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET); + assert(template.format != PIPE_FORMAT_NONE); + pf_get_block(template.format, &template.block); + template.width[0] = width; + template.height[0] = height; + template.depth[0] = 1; + template.last_level = 0; + template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + + tex = pipe->screen->texture_blanket( pipe->screen, + &template, + &stride, + st_obj->buffer ); + if (!tex) { + pipe_surface_reference(&surf, NULL); + return GL_FALSE; + } + + surface = pipe->screen->get_tex_surface( pipe->screen, + tex, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE ); + + if (!surface) { + pipe_texture_reference(&tex, NULL); + pipe_surface_reference(&surf, NULL); + return GL_FALSE; + } + + pipe->surface_copy(pipe, + do_flip, + /* dest */ + surface, + 0, 0, + /* src */ + surf, + x, y, + /* size */ + width, height); + + pipe_surface_reference(&surface, NULL); + pipe_texture_reference(&tex, NULL); + pipe_surface_reference(&surf, NULL); + + return GL_TRUE; + } + + if (!screen->get_tex_transfer || + !screen->tex_transfer_destroy || + !screen->transfer_map || + !screen->transfer_unmap) { + return GL_FALSE; + } + + if (do_flip) { y = strb->texture->height[0] - y - height; } @@ -236,7 +305,7 @@ st_accelerated_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, return GL_FALSE; } - if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { + if (do_flip) { y = height - 1; dy = -1; } @@ -245,6 +314,10 @@ st_accelerated_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, dy = 1; } + dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest); + if (!dest) + return GL_FALSE; + dst = _mesa_image_address2d(pack, dest, width, height, format, type, 0, 0); dstStride = _mesa_image_row_stride(pack, width, format, type); @@ -310,6 +383,8 @@ st_accelerated_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, ; /* nothing */ } + _mesa_unmap_readpix_pbo(ctx, &clippedPacking); + screen->transfer_unmap(screen, trans); screen->tex_transfer_destroy(trans); @@ -468,15 +543,17 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, return; } - dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest); - if (!dest) - return; - /* make sure rendering has completed */ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); if (format == GL_STENCIL_INDEX) { + dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest); + if (!dest) + return; + st_read_stencil_pixels(ctx, x, y, width, height, type, pack, dest); + + _mesa_unmap_readpix_pbo(ctx, &clippedPacking); return; } else if (format == GL_DEPTH_COMPONENT) { @@ -490,12 +567,14 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, if (!strb) return; + /* try an accelerated readpixels before anything else */ if (st_accelerated_readpixels(ctx, strb, x, y, width, height, - format, type, pack, dest)) { - /* success! */ - _mesa_unmap_readpix_pbo(ctx, &clippedPacking); + format, type, pack, dest)) + return; + + dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest); + if (!dest) return; - } /* try a fast-path readpixels before anything else */ if (st_fast_readpixels(ctx, strb, x, y, width, height,