00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00036 #include "main/imports.h"
00037 #include "main/bufferobj.h"
00038 #include "main/context.h"
00039 #include "main/image.h"
00040
00041 #include "pipe/p_context.h"
00042 #include "pipe/p_defines.h"
00043 #include "pipe/p_inlines.h"
00044 #include "util/u_tile.h"
00045 #include "st_context.h"
00046 #include "st_cb_bitmap.h"
00047 #include "st_cb_readpixels.h"
00048 #include "st_cb_fbo.h"
00049 #include "st_format.h"
00050 #include "st_public.h"
00051
00052
00057 void
00058 st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
00059 GLsizei width, GLsizei height, GLenum type,
00060 const struct gl_pixelstore_attrib *packing,
00061 GLvoid *pixels)
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
00071 ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
00072 PIPE_BUFFER_USAGE_CPU_READ);
00073
00074
00075 stmap = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ);
00076
00077
00078 ASSERT(width <= MAX_WIDTH);
00079
00080
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
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
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
00132 screen->surface_unmap(screen, ps);
00133 pipe_surface_reference(&ps, NULL);
00134 }
00135
00136
00142 struct st_renderbuffer *
00143 st_get_color_read_renderbuffer(GLcontext *ctx)
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
00154
00155
00156 struct st_renderbuffer *back =
00157 st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
00158 strb = back;
00159 }
00160
00161 return strb;
00162 }
00163
00164
00169 static GLboolean
00170 st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb,
00171 GLint x, GLint y, GLsizei width, GLsizei height,
00172 GLenum format, GLenum type,
00173 const struct gl_pixelstore_attrib *pack,
00174 GLvoid *dest)
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
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 ;
00273 }
00274
00275 screen->surface_unmap(screen, surf);
00276 pipe_surface_reference(&surf, NULL);
00277 }
00278
00279 return GL_TRUE;
00280 }
00281
00282
00288 static void
00289 st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
00290 GLenum format, GLenum type,
00291 const struct gl_pixelstore_attrib *pack,
00292 GLvoid *dest)
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
00308 assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
00309
00310
00311 if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
00312
00313 return;
00314 }
00315
00316 dest = _mesa_map_readpix_pbo(ctx, &clippedPacking, dest);
00317 if (!dest)
00318 return;
00319
00320
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
00332 strb = st_get_color_read_renderbuffer(ctx);
00333 }
00334
00335 if (!strb)
00336 return;
00337
00338
00339 if (st_fast_readpixels(ctx, strb, x, y, width, height,
00340 format, type, pack, dest)) {
00341
00342 _mesa_unmap_readpix_pbo(ctx, &clippedPacking);
00343 return;
00344 }
00345
00346 if (format == GL_RGBA && type == GL_FLOAT) {
00347
00348 df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
00349 height, format, type, 0, 0);
00350 dfStride = width * 4;
00351 }
00352 else {
00353
00354 df = (GLfloat *) temp;
00355 dfStride = 0;
00356 }
00357
00358
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
00368 surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
00369 PIPE_BUFFER_USAGE_CPU_READ);
00370
00371
00372
00373
00374 {
00375
00376 GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width,
00377 height, format, type, 0, 0);
00378
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
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
00441
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 }
00459
00460
00461 void st_init_readpixels_functions(struct dd_function_table *functions)
00462 {
00463 functions->ReadPixels = st_readpixels;
00464 }