Go to the source code of this file.
Functions | |
void | st_read_stencil_pixels (GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, const struct gl_pixelstore_attrib *packing, GLvoid *pixels) |
glReadPixels interface to pipe | |
struct st_renderbuffer * | st_get_color_read_renderbuffer (GLcontext *ctx) |
Return renderbuffer to use for reading color pixels for glRead/CopyPixel commands. | |
static GLboolean | st_fast_readpixels (GLcontext *ctx, struct st_renderbuffer *strb, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *dest) |
Try to do glReadPixels in a fast manner for common cases. | |
static void | st_readpixels (GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *dest) |
Do glReadPixels by getting rows from the framebuffer surface with get_tile(). | |
void | st_init_readpixels_functions (struct dd_function_table *functions) |
static GLboolean st_fast_readpixels | ( | GLcontext * | ctx, | |
struct st_renderbuffer * | strb, | |||
GLint | x, | |||
GLint | y, | |||
GLsizei | width, | |||
GLsizei | height, | |||
GLenum | format, | |||
GLenum | type, | |||
const struct gl_pixelstore_attrib * | pack, | |||
GLvoid * | dest | |||
) | [static] |
Try to do glReadPixels in a fast manner for common cases.
Definition at line 170 of file st_cb_readpixels.c.
References st_renderbuffer::format, pipe_screen::get_tex_surface, pipe_surface::height, PIPE_BUFFER_USAGE_CPU_READ, PIPE_FORMAT_A8R8G8B8_UNORM, pipe_surface_reference(), pipe_context::screen, st_fb_orientation(), pipe_surface::stride, pipe_screen::surface_map, pipe_screen::surface_unmap, st_renderbuffer::texture, and Y_0_TOP.
00175 { 00176 enum combination { 00177 A8R8G8B8_UNORM_TO_RGBA_UBYTE, 00178 A8R8G8B8_UNORM_TO_RGB_UBYTE, 00179 A8R8G8B8_UNORM_TO_BGRA_UINT 00180 } combo; 00181 00182 if (ctx->_ImageTransferState) 00183 return GL_FALSE; 00184 00185 if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM && 00186 format == GL_RGBA && type == GL_UNSIGNED_BYTE) { 00187 combo = A8R8G8B8_UNORM_TO_RGBA_UBYTE; 00188 } 00189 else if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM && 00190 format == GL_RGB && type == GL_UNSIGNED_BYTE) { 00191 combo = A8R8G8B8_UNORM_TO_RGB_UBYTE; 00192 } 00193 else if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM && 00194 format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) { 00195 combo = A8R8G8B8_UNORM_TO_BGRA_UINT; 00196 } 00197 else { 00198 return GL_FALSE; 00199 } 00200 00201 /*printf("st_fast_readpixels combo %d\n", (GLint) combo);*/ 00202 00203 { 00204 struct pipe_context *pipe = ctx->st->pipe; 00205 struct pipe_screen *screen = pipe->screen; 00206 struct pipe_surface *surf; 00207 const GLubyte *map; 00208 GLubyte *dst; 00209 GLint row, col, dy, dstStride; 00210 00211 surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, 00212 PIPE_BUFFER_USAGE_CPU_READ); 00213 if (!surf) { 00214 return GL_FALSE; 00215 } 00216 00217 map = screen->surface_map(screen, surf, PIPE_BUFFER_USAGE_CPU_READ); 00218 if (!map) { 00219 pipe_surface_reference(&surf, NULL); 00220 return GL_FALSE; 00221 } 00222 00223 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 00224 y = surf->height - y - 1; 00225 dy = -1; 00226 } 00227 else { 00228 dy = 1; 00229 } 00230 00231 dst = _mesa_image_address2d(pack, dest, width, height, 00232 format, type, 0, 0); 00233 dstStride = _mesa_image_row_stride(pack, width, format, type); 00234 00235 switch (combo) { 00236 case A8R8G8B8_UNORM_TO_RGBA_UBYTE: 00237 for (row = 0; row < height; row++) { 00238 const GLubyte *src = map + y * surf->stride + x * 4; 00239 for (col = 0; col < width; col++) { 00240 GLuint pixel = ((GLuint *) src)[col]; 00241 dst[col*4+0] = (pixel >> 16) & 0xff; 00242 dst[col*4+1] = (pixel >> 8) & 0xff; 00243 dst[col*4+2] = (pixel >> 0) & 0xff; 00244 dst[col*4+3] = (pixel >> 24) & 0xff; 00245 } 00246 dst += dstStride; 00247 y += dy; 00248 } 00249 break; 00250 case A8R8G8B8_UNORM_TO_RGB_UBYTE: 00251 for (row = 0; row < height; row++) { 00252 const GLubyte *src = map + y * surf->stride + x * 4; 00253 for (col = 0; col < width; col++) { 00254 GLuint pixel = ((GLuint *) src)[col]; 00255 dst[col*3+0] = (pixel >> 16) & 0xff; 00256 dst[col*3+1] = (pixel >> 8) & 0xff; 00257 dst[col*3+2] = (pixel >> 0) & 0xff; 00258 } 00259 dst += dstStride; 00260 y += dy; 00261 } 00262 break; 00263 case A8R8G8B8_UNORM_TO_BGRA_UINT: 00264 for (row = 0; row < height; row++) { 00265 const GLubyte *src = map + y * surf->stride + x * 4; 00266 memcpy(dst, src, 4 * width); 00267 dst += dstStride; 00268 y += dy; 00269 } 00270 break; 00271 default: 00272 ; /* nothing */ 00273 } 00274 00275 screen->surface_unmap(screen, surf); 00276 pipe_surface_reference(&surf, NULL); 00277 } 00278 00279 return GL_TRUE; 00280 }
struct st_renderbuffer* st_get_color_read_renderbuffer | ( | GLcontext * | ctx | ) | [read] |
Return renderbuffer to use for reading color pixels for glRead/CopyPixel commands.
Special care is needed for the front buffer.
Definition at line 143 of file st_cb_readpixels.c.
References FRONT_STATUS_COPY_OF_BACK, and st_renderbuffer().
00144 { 00145 struct gl_framebuffer *fb = ctx->ReadBuffer; 00146 struct st_renderbuffer *strb = 00147 st_renderbuffer(fb->_ColorReadBuffer); 00148 struct st_renderbuffer *front = 00149 st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 00150 00151 if (strb == front 00152 && ctx->st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) { 00153 /* reading from front color buffer, which is a logical copy of the 00154 * back color buffer. 00155 */ 00156 struct st_renderbuffer *back = 00157 st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 00158 strb = back; 00159 } 00160 00161 return strb; 00162 }
void st_init_readpixels_functions | ( | struct dd_function_table * | functions | ) |
Definition at line 461 of file st_cb_readpixels.c.
References st_readpixels().
00462 { 00463 functions->ReadPixels = st_readpixels; 00464 }
void st_read_stencil_pixels | ( | GLcontext * | ctx, | |
GLint | x, | |||
GLint | y, | |||
GLsizei | width, | |||
GLsizei | height, | |||
GLenum | type, | |||
const struct gl_pixelstore_attrib * | packing, | |||
GLvoid * | pixels | |||
) |
glReadPixels interface to pipe
Definition at line 58 of file st_cb_readpixels.c.
References assert, ASSERT, pipe_surface::format, pipe_screen::get_tex_surface, MAX_WIDTH, PIPE_BUFFER_USAGE_CPU_READ, PIPE_FORMAT_S8_UNORM, PIPE_FORMAT_S8Z24_UNORM, PIPE_FORMAT_Z24S8_UNORM, pipe_surface_reference(), st_fb_orientation(), st_renderbuffer(), pipe_surface::stride, pipe_screen::surface_map, pipe_screen::surface_unmap, st_renderbuffer::texture, and Y_0_TOP.
00062 { 00063 struct gl_framebuffer *fb = ctx->ReadBuffer; 00064 struct pipe_screen *screen = ctx->st->pipe->screen; 00065 struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer); 00066 struct pipe_surface *ps; 00067 ubyte *stmap; 00068 GLint j; 00069 00070 /* Create a CPU-READ surface/view into the renderbuffer's texture */ 00071 ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, 00072 PIPE_BUFFER_USAGE_CPU_READ); 00073 00074 /* map the stencil buffer */ 00075 stmap = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ); 00076 00077 /* width should never be > MAX_WIDTH since we did clipping earlier */ 00078 ASSERT(width <= MAX_WIDTH); 00079 00080 /* process image row by row */ 00081 for (j = 0; j < height; j++, y++) { 00082 GLvoid *dest; 00083 GLstencil values[MAX_WIDTH]; 00084 GLint srcY; 00085 00086 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 00087 srcY = ctx->DrawBuffer->Height - y - 1; 00088 } 00089 else { 00090 srcY = y; 00091 } 00092 00093 /* get stencil values */ 00094 switch (ps->format) { 00095 case PIPE_FORMAT_S8_UNORM: 00096 { 00097 const ubyte *src = stmap + srcY * ps->stride + x; 00098 memcpy(values, src, width); 00099 } 00100 break; 00101 case PIPE_FORMAT_S8Z24_UNORM: 00102 { 00103 const uint *src = (uint *) (stmap + srcY * ps->stride + x*4); 00104 GLint k; 00105 for (k = 0; k < width; k++) { 00106 values[k] = src[k] >> 24; 00107 } 00108 } 00109 break; 00110 case PIPE_FORMAT_Z24S8_UNORM: 00111 { 00112 const uint *src = (uint *) (stmap + srcY * ps->stride + x*4); 00113 GLint k; 00114 for (k = 0; k < width; k++) { 00115 values[k] = src[k] & 0xff; 00116 } 00117 } 00118 break; 00119 default: 00120 assert(0); 00121 } 00122 00123 /* store */ 00124 dest = _mesa_image_address2d(packing, pixels, width, height, 00125 GL_STENCIL_INDEX, type, j, 0); 00126 00127 _mesa_pack_stencil_span(ctx, width, type, dest, values, packing); 00128 } 00129 00130 00131 /* unmap the stencil buffer */ 00132 screen->surface_unmap(screen, ps); 00133 pipe_surface_reference(&ps, NULL); 00134 }
static void st_readpixels | ( | GLcontext * | ctx, | |
GLint | x, | |||
GLint | y, | |||
GLsizei | width, | |||
GLsizei | height, | |||
GLenum | format, | |||
GLenum | type, | |||
const struct gl_pixelstore_attrib * | pack, | |||
GLvoid * | dest | |||
) | [static] |
Do glReadPixels by getting rows from the framebuffer surface with get_tile().
Convert to requested format/type with Mesa image routines. Image transfer ops are done in software too.
Definition at line 289 of file st_cb_readpixels.c.
References assert, st_renderbuffer::Base, pipe_surface::format, pipe_screen::get_tex_surface, MAX_WIDTH, PIPE_BUFFER_USAGE_CPU_READ, PIPE_FLUSH_RENDER_CACHE, PIPE_FORMAT_S8Z24_UNORM, PIPE_FORMAT_X8Z24_UNORM, PIPE_FORMAT_Z16_UNORM, PIPE_FORMAT_Z32_UNORM, pipe_get_tile_raw(), pipe_get_tile_rgba(), pipe_surface_reference(), pipe_context::screen, st_fast_readpixels(), st_fb_orientation(), st_flush(), st_get_color_read_renderbuffer(), st_read_stencil_pixels(), st_renderbuffer(), st_renderbuffer::texture, and Y_0_TOP.
00293 { 00294 struct pipe_context *pipe = ctx->st->pipe; 00295 struct pipe_screen *screen = pipe->screen; 00296 GLfloat temp[MAX_WIDTH][4]; 00297 const GLbitfield transferOps = ctx->_ImageTransferState; 00298 GLsizei i, j; 00299 GLint yStep, dfStride; 00300 GLfloat *df; 00301 struct st_renderbuffer *strb; 00302 struct gl_pixelstore_attrib clippedPacking = *pack; 00303 struct pipe_surface *surf; 00304 00305 assert(ctx->ReadBuffer->Width > 0); 00306 00307 /* XXX convolution not done yet */ 00308 assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0); 00309 00310 /* Do all needed clipping here, so that we can forget about it later */ 00311 if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { 00312 /* The ReadPixels surface is totally outside the window bounds */ 00313 return; 00314 } 00315 00316 dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest); 00317 if (!dest) 00318 return; 00319 00320 /* make sure rendering has completed */ 00321 st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); 00322 00323 if (format == GL_STENCIL_INDEX) { 00324 st_read_stencil_pixels(ctx, x, y, width, height, type, pack, dest); 00325 return; 00326 } 00327 else if (format == GL_DEPTH_COMPONENT) { 00328 strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); 00329 } 00330 else { 00331 /* Read color buffer */ 00332 strb = st_get_color_read_renderbuffer(ctx); 00333 } 00334 00335 if (!strb) 00336 return; 00337 00338 /* try a fast-path readpixels before anything else */ 00339 if (st_fast_readpixels(ctx, strb, x, y, width, height, 00340 format, type, pack, dest)) { 00341 /* success! */ 00342 _mesa_unmap_readpix_pbo(ctx, &clippedPacking); 00343 return; 00344 } 00345 00346 if (format == GL_RGBA && type == GL_FLOAT) { 00347 /* write tile(row) directly into user's buffer */ 00348 df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width, 00349 height, format, type, 0, 0); 00350 dfStride = width * 4; 00351 } 00352 else { 00353 /* write tile(row) into temp row buffer */ 00354 df = (GLfloat *) temp; 00355 dfStride = 0; 00356 } 00357 00358 /* determine bottom-to-top vs. top-to-bottom order */ 00359 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 00360 y = strb->Base.Height - 1 - y; 00361 yStep = -1; 00362 } 00363 else { 00364 yStep = 1; 00365 } 00366 00367 /* Create a CPU-READ surface/view into the renderbuffer's texture */ 00368 surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, 00369 PIPE_BUFFER_USAGE_CPU_READ); 00370 00371 /* 00372 * Copy pixels from pipe_surface to user memory 00373 */ 00374 { 00375 /* dest of first pixel in client memory */ 00376 GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width, 00377 height, format, type, 0, 0); 00378 /* dest row stride */ 00379 const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, 00380 format, type); 00381 00382 if (surf->format == PIPE_FORMAT_S8Z24_UNORM || 00383 surf->format == PIPE_FORMAT_X8Z24_UNORM) { 00384 if (format == GL_DEPTH_COMPONENT) { 00385 for (i = 0; i < height; i++) { 00386 GLuint ztemp[MAX_WIDTH]; 00387 GLfloat zfloat[MAX_WIDTH]; 00388 const double scale = 1.0 / ((1 << 24) - 1); 00389 pipe_get_tile_raw(surf, x, y, width, 1, ztemp, 0); 00390 y += yStep; 00391 for (j = 0; j < width; j++) { 00392 zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff)); 00393 } 00394 _mesa_pack_depth_span(ctx, width, dst, type, 00395 zfloat, &clippedPacking); 00396 dst += dstStride; 00397 } 00398 } 00399 else { 00400 /* untested, but simple: */ 00401 assert(format == GL_DEPTH_STENCIL_EXT); 00402 for (i = 0; i < height; i++) { 00403 pipe_get_tile_raw(surf, x, y, width, 1, dst, 0); 00404 y += yStep; 00405 dst += dstStride; 00406 } 00407 } 00408 } 00409 else if (surf->format == PIPE_FORMAT_Z16_UNORM) { 00410 for (i = 0; i < height; i++) { 00411 GLushort ztemp[MAX_WIDTH]; 00412 GLfloat zfloat[MAX_WIDTH]; 00413 const double scale = 1.0 / 0xffff; 00414 pipe_get_tile_raw(surf, x, y, width, 1, ztemp, 0); 00415 y += yStep; 00416 for (j = 0; j < width; j++) { 00417 zfloat[j] = (float) (scale * ztemp[j]); 00418 } 00419 _mesa_pack_depth_span(ctx, width, dst, type, 00420 zfloat, &clippedPacking); 00421 dst += dstStride; 00422 } 00423 } 00424 else if (surf->format == PIPE_FORMAT_Z32_UNORM) { 00425 for (i = 0; i < height; i++) { 00426 GLuint ztemp[MAX_WIDTH]; 00427 GLfloat zfloat[MAX_WIDTH]; 00428 const double scale = 1.0 / 0xffffffff; 00429 pipe_get_tile_raw(surf, x, y, width, 1, ztemp, 0); 00430 y += yStep; 00431 for (j = 0; j < width; j++) { 00432 zfloat[j] = (float) (scale * ztemp[j]); 00433 } 00434 _mesa_pack_depth_span(ctx, width, dst, type, 00435 zfloat, &clippedPacking); 00436 dst += dstStride; 00437 } 00438 } 00439 else { 00440 /* RGBA format */ 00441 /* Do a row at a time to flip image data vertically */ 00442 for (i = 0; i < height; i++) { 00443 pipe_get_tile_rgba(surf, x, y, width, 1, df); 00444 y += yStep; 00445 df += dfStride; 00446 if (!dfStride) { 00447 _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst, 00448 &clippedPacking, transferOps); 00449 dst += dstStride; 00450 } 00451 } 00452 } 00453 } 00454 00455 pipe_surface_reference(&surf, NULL); 00456 00457 _mesa_unmap_readpix_pbo(ctx, &clippedPacking); 00458 }