[3598] | 1 | /* $Id: readpix.c,v 1.3 2000-05-23 20:40:52 jeroen Exp $ */
|
---|
[2938] | 2 |
|
---|
| 3 | /*
|
---|
| 4 | * Mesa 3-D graphics library
|
---|
[3598] | 5 | * Version: 3.3
|
---|
[2938] | 6 | *
|
---|
| 7 | * Copyright (C) 1999 Brian Paul All Rights Reserved.
|
---|
| 8 | *
|
---|
| 9 | * Permission is hereby granted, free of charge, to any person obtaining a
|
---|
| 10 | * copy of this software and associated documentation files (the "Software"),
|
---|
| 11 | * to deal in the Software without restriction, including without limitation
|
---|
| 12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
---|
| 13 | * and/or sell copies of the Software, and to permit persons to whom the
|
---|
| 14 | * Software is furnished to do so, subject to the following conditions:
|
---|
| 15 | *
|
---|
| 16 | * The above copyright notice and this permission notice shall be included
|
---|
| 17 | * in all copies or substantial portions of the Software.
|
---|
| 18 | *
|
---|
| 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
| 20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
| 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
---|
| 22 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
---|
| 23 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
---|
| 24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
---|
| 25 | */
|
---|
| 26 |
|
---|
| 27 |
|
---|
| 28 | #ifdef PC_HEADER
|
---|
| 29 | #include "all.h"
|
---|
| 30 | #else
|
---|
[3598] | 31 | #include "glheader.h"
|
---|
[2938] | 32 | #include "alphabuf.h"
|
---|
[2962] | 33 | #include "types.h"
|
---|
[2938] | 34 | #include "context.h"
|
---|
| 35 | #include "depth.h"
|
---|
| 36 | #include "feedback.h"
|
---|
| 37 | #include "image.h"
|
---|
| 38 | #include "macros.h"
|
---|
| 39 | #include "pixel.h"
|
---|
| 40 | #include "readpix.h"
|
---|
| 41 | #include "span.h"
|
---|
| 42 | #include "stencil.h"
|
---|
[3598] | 43 | #include "mem.h"
|
---|
[2938] | 44 | #endif
|
---|
| 45 |
|
---|
| 46 |
|
---|
| 47 |
|
---|
| 48 |
|
---|
| 49 | /*
|
---|
| 50 | * Read a block of color index pixels.
|
---|
| 51 | */
|
---|
| 52 | static void read_index_pixels( GLcontext *ctx,
|
---|
| 53 | GLint x, GLint y,
|
---|
[2962] | 54 | GLsizei width, GLsizei height,
|
---|
[3598] | 55 | GLenum type, GLvoid *pixels,
|
---|
[2938] | 56 | const struct gl_pixelstore_attrib *packing )
|
---|
| 57 | {
|
---|
| 58 | GLint i, j, readWidth;
|
---|
| 59 |
|
---|
| 60 | /* error checking */
|
---|
| 61 | if (ctx->Visual->RGBAflag) {
|
---|
| 62 | gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
|
---|
| 63 | return;
|
---|
| 64 | }
|
---|
| 65 |
|
---|
[3598] | 66 | ASSERT(ctx->Driver.SetReadBuffer);
|
---|
| 67 | (*ctx->Driver.SetReadBuffer)(ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer);
|
---|
[2938] | 68 |
|
---|
| 69 | readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
|
---|
| 70 |
|
---|
| 71 | /* process image row by row */
|
---|
| 72 | for (j=0;j<height;j++,y++) {
|
---|
| 73 | GLuint index[MAX_WIDTH];
|
---|
| 74 | GLvoid *dest;
|
---|
| 75 |
|
---|
| 76 | (*ctx->Driver.ReadCI32Span)( ctx, readWidth, x, y, index );
|
---|
| 77 |
|
---|
| 78 | if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) {
|
---|
| 79 | gl_shift_and_offset_ci( ctx, readWidth, index);
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | if (ctx->Pixel.MapColorFlag) {
|
---|
| 83 | gl_map_ci(ctx, readWidth, index);
|
---|
| 84 | }
|
---|
| 85 |
|
---|
[3598] | 86 | dest = _mesa_image_address(packing, pixels,
|
---|
[2938] | 87 | width, height, GL_COLOR_INDEX, type, 0, j, 0);
|
---|
| 88 |
|
---|
| 89 | switch (type) {
|
---|
[3598] | 90 | case GL_UNSIGNED_BYTE:
|
---|
| 91 | {
|
---|
[2938] | 92 | GLubyte *dst = (GLubyte *) dest;
|
---|
[3598] | 93 | for (i=0;i<readWidth;i++) {
|
---|
| 94 | *dst++ = (GLubyte) index[i];
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 | break;
|
---|
| 98 | case GL_BYTE:
|
---|
| 99 | {
|
---|
[2938] | 100 | GLbyte *dst = (GLbyte *) dest;
|
---|
[3598] | 101 | for (i=0;i<readWidth;i++) {
|
---|
| 102 | dst[i] = (GLbyte) index[i];
|
---|
| 103 | }
|
---|
| 104 | }
|
---|
| 105 | break;
|
---|
| 106 | case GL_UNSIGNED_SHORT:
|
---|
| 107 | {
|
---|
[2938] | 108 | GLushort *dst = (GLushort *) dest;
|
---|
[3598] | 109 | for (i=0;i<readWidth;i++) {
|
---|
| 110 | dst[i] = (GLushort) index[i];
|
---|
| 111 | }
|
---|
| 112 | if (packing->SwapBytes) {
|
---|
| 113 | _mesa_swap2( (GLushort *) dst, readWidth );
|
---|
| 114 | }
|
---|
| 115 | }
|
---|
| 116 | break;
|
---|
| 117 | case GL_SHORT:
|
---|
| 118 | {
|
---|
[2938] | 119 | GLshort *dst = (GLshort *) dest;
|
---|
[3598] | 120 | for (i=0;i<readWidth;i++) {
|
---|
| 121 | dst[i] = (GLshort) index[i];
|
---|
| 122 | }
|
---|
| 123 | if (packing->SwapBytes) {
|
---|
| 124 | _mesa_swap2( (GLushort *) dst, readWidth );
|
---|
| 125 | }
|
---|
| 126 | }
|
---|
| 127 | break;
|
---|
| 128 | case GL_UNSIGNED_INT:
|
---|
| 129 | {
|
---|
[2938] | 130 | GLuint *dst = (GLuint *) dest;
|
---|
[3598] | 131 | for (i=0;i<readWidth;i++) {
|
---|
| 132 | dst[i] = (GLuint) index[i];
|
---|
| 133 | }
|
---|
| 134 | if (packing->SwapBytes) {
|
---|
| 135 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
| 136 | }
|
---|
| 137 | }
|
---|
| 138 | break;
|
---|
| 139 | case GL_INT:
|
---|
| 140 | {
|
---|
[2938] | 141 | GLint *dst = (GLint *) dest;
|
---|
[3598] | 142 | for (i=0;i<readWidth;i++) {
|
---|
| 143 | dst[i] = (GLint) index[i];
|
---|
| 144 | }
|
---|
| 145 | if (packing->SwapBytes) {
|
---|
| 146 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
| 147 | }
|
---|
| 148 | }
|
---|
| 149 | break;
|
---|
| 150 | case GL_FLOAT:
|
---|
| 151 | {
|
---|
[2938] | 152 | GLfloat *dst = (GLfloat *) dest;
|
---|
[3598] | 153 | for (i=0;i<readWidth;i++) {
|
---|
| 154 | dst[i] = (GLfloat) index[i];
|
---|
| 155 | }
|
---|
| 156 | if (packing->SwapBytes) {
|
---|
| 157 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
| 158 | }
|
---|
| 159 | }
|
---|
| 160 | break;
|
---|
[2938] | 161 | default:
|
---|
| 162 | gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
|
---|
| 163 | j = height + 1; /* exit loop */
|
---|
| 164 | }
|
---|
| 165 | }
|
---|
| 166 |
|
---|
[3598] | 167 | (*ctx->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer);
|
---|
[2938] | 168 | }
|
---|
| 169 |
|
---|
| 170 |
|
---|
| 171 |
|
---|
| 172 | static void read_depth_pixels( GLcontext *ctx,
|
---|
| 173 | GLint x, GLint y,
|
---|
[3598] | 174 | GLsizei width, GLsizei height,
|
---|
| 175 | GLenum type, GLvoid *pixels,
|
---|
[2938] | 176 | const struct gl_pixelstore_attrib *packing )
|
---|
| 177 | {
|
---|
| 178 | GLint i, j, readWidth;
|
---|
| 179 | GLboolean bias_or_scale;
|
---|
| 180 |
|
---|
| 181 | /* Error checking */
|
---|
| 182 | if (ctx->Visual->DepthBits <= 0) {
|
---|
| 183 | /* No depth buffer */
|
---|
| 184 | gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
|
---|
| 185 | return;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
|
---|
| 189 |
|
---|
| 190 | if (type != GL_BYTE &&
|
---|
| 191 | type != GL_UNSIGNED_BYTE &&
|
---|
| 192 | type != GL_SHORT &&
|
---|
| 193 | type != GL_UNSIGNED_SHORT &&
|
---|
| 194 | type != GL_INT &&
|
---|
| 195 | type != GL_UNSIGNED_INT &&
|
---|
| 196 | type != GL_FLOAT) {
|
---|
| 197 | gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels(depth type)");
|
---|
| 198 | return;
|
---|
| 199 | }
|
---|
| 200 |
|
---|
| 201 | bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
|
---|
| 202 |
|
---|
| 203 | if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
|
---|
| 204 | && !bias_or_scale && !packing->SwapBytes) {
|
---|
| 205 | /* Special case: directly read 16-bit unsigned depth values. */
|
---|
| 206 | for (j=0;j<height;j++,y++) {
|
---|
[3598] | 207 | GLdepth depth[MAX_WIDTH];
|
---|
| 208 | GLushort *dst = (GLushort*) _mesa_image_address( packing, pixels,
|
---|
[2938] | 209 | width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
|
---|
[3598] | 210 | GLint i;
|
---|
| 211 | (*ctx->Driver.ReadDepthSpan)( ctx, width, x, y, depth);
|
---|
| 212 | for (i = 0; i < width; i++)
|
---|
| 213 | dst[i] = depth[i];
|
---|
[2938] | 214 | }
|
---|
| 215 | }
|
---|
[3598] | 216 | else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32
|
---|
[2938] | 217 | && !bias_or_scale && !packing->SwapBytes) {
|
---|
| 218 | /* Special case: directly read 32-bit unsigned depth values. */
|
---|
| 219 | for (j=0;j<height;j++,y++) {
|
---|
[3598] | 220 | GLdepth *dst = (GLdepth *) _mesa_image_address( packing, pixels,
|
---|
[2938] | 221 | width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
|
---|
[3598] | 222 | (*ctx->Driver.ReadDepthSpan)( ctx, width, x, y, dst);
|
---|
[2938] | 223 | }
|
---|
| 224 | }
|
---|
| 225 | else {
|
---|
| 226 | /* General case (slow) */
|
---|
| 227 | for (j=0;j<height;j++,y++) {
|
---|
| 228 | GLfloat depth[MAX_WIDTH];
|
---|
| 229 | GLvoid *dest;
|
---|
| 230 |
|
---|
[3598] | 231 | _mesa_read_depth_span_float(ctx, readWidth, x, y, depth);
|
---|
[2938] | 232 |
|
---|
| 233 | if (bias_or_scale) {
|
---|
| 234 | for (i=0;i<readWidth;i++) {
|
---|
| 235 | GLfloat d;
|
---|
| 236 | d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
|
---|
| 237 | depth[i] = CLAMP( d, 0.0F, 1.0F );
|
---|
| 238 | }
|
---|
| 239 | }
|
---|
| 240 |
|
---|
[3598] | 241 | dest = _mesa_image_address(packing, pixels,
|
---|
[2938] | 242 | width, height, GL_DEPTH_COMPONENT, type, 0, j, 0);
|
---|
| 243 |
|
---|
| 244 | switch (type) {
|
---|
| 245 | case GL_UNSIGNED_BYTE:
|
---|
| 246 | {
|
---|
| 247 | GLubyte *dst = (GLubyte *) dest;
|
---|
| 248 | for (i=0;i<readWidth;i++) {
|
---|
| 249 | dst[i] = FLOAT_TO_UBYTE( depth[i] );
|
---|
| 250 | }
|
---|
| 251 | }
|
---|
| 252 | break;
|
---|
| 253 | case GL_BYTE:
|
---|
| 254 | {
|
---|
| 255 | GLbyte *dst = (GLbyte *) dest;
|
---|
| 256 | for (i=0;i<readWidth;i++) {
|
---|
| 257 | dst[i] = FLOAT_TO_BYTE( depth[i] );
|
---|
| 258 | }
|
---|
| 259 | }
|
---|
| 260 | break;
|
---|
| 261 | case GL_UNSIGNED_SHORT:
|
---|
| 262 | {
|
---|
| 263 | GLushort *dst = (GLushort *) dest;
|
---|
| 264 | for (i=0;i<readWidth;i++) {
|
---|
| 265 | dst[i] = FLOAT_TO_USHORT( depth[i] );
|
---|
| 266 | }
|
---|
| 267 | if (packing->SwapBytes) {
|
---|
[3598] | 268 | _mesa_swap2( (GLushort *) dst, readWidth );
|
---|
[2938] | 269 | }
|
---|
| 270 | }
|
---|
| 271 | break;
|
---|
| 272 | case GL_SHORT:
|
---|
| 273 | {
|
---|
| 274 | GLshort *dst = (GLshort *) dest;
|
---|
| 275 | for (i=0;i<readWidth;i++) {
|
---|
| 276 | dst[i] = FLOAT_TO_SHORT( depth[i] );
|
---|
| 277 | }
|
---|
| 278 | if (packing->SwapBytes) {
|
---|
[3598] | 279 | _mesa_swap2( (GLushort *) dst, readWidth );
|
---|
[2938] | 280 | }
|
---|
| 281 | }
|
---|
| 282 | break;
|
---|
| 283 | case GL_UNSIGNED_INT:
|
---|
| 284 | {
|
---|
| 285 | GLuint *dst = (GLuint *) dest;
|
---|
| 286 | for (i=0;i<readWidth;i++) {
|
---|
| 287 | dst[i] = FLOAT_TO_UINT( depth[i] );
|
---|
| 288 | }
|
---|
| 289 | if (packing->SwapBytes) {
|
---|
[3598] | 290 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
[2938] | 291 | }
|
---|
| 292 | }
|
---|
| 293 | break;
|
---|
| 294 | case GL_INT:
|
---|
| 295 | {
|
---|
| 296 | GLint *dst = (GLint *) dest;
|
---|
| 297 | for (i=0;i<readWidth;i++) {
|
---|
| 298 | dst[i] = FLOAT_TO_INT( depth[i] );
|
---|
| 299 | }
|
---|
| 300 | if (packing->SwapBytes) {
|
---|
[3598] | 301 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
[2938] | 302 | }
|
---|
| 303 | }
|
---|
| 304 | break;
|
---|
| 305 | case GL_FLOAT:
|
---|
| 306 | {
|
---|
| 307 | GLfloat *dst = (GLfloat *) dest;
|
---|
| 308 | for (i=0;i<readWidth;i++) {
|
---|
| 309 | dst[i] = depth[i];
|
---|
| 310 | }
|
---|
| 311 | if (packing->SwapBytes) {
|
---|
[3598] | 312 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
[2938] | 313 | }
|
---|
| 314 | }
|
---|
| 315 | break;
|
---|
| 316 | default:
|
---|
| 317 | gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
|
---|
| 318 | }
|
---|
| 319 | }
|
---|
| 320 | }
|
---|
| 321 | }
|
---|
| 322 |
|
---|
| 323 |
|
---|
| 324 |
|
---|
| 325 |
|
---|
| 326 | static void read_stencil_pixels( GLcontext *ctx,
|
---|
| 327 | GLint x, GLint y,
|
---|
[3598] | 328 | GLsizei width, GLsizei height,
|
---|
| 329 | GLenum type, GLvoid *pixels,
|
---|
[2938] | 330 | const struct gl_pixelstore_attrib *packing )
|
---|
| 331 | {
|
---|
| 332 | GLboolean shift_or_offset;
|
---|
| 333 | GLint i, j, readWidth;
|
---|
| 334 |
|
---|
| 335 | if (type != GL_BYTE &&
|
---|
| 336 | type != GL_UNSIGNED_BYTE &&
|
---|
| 337 | type != GL_SHORT &&
|
---|
| 338 | type != GL_UNSIGNED_SHORT &&
|
---|
| 339 | type != GL_INT &&
|
---|
| 340 | type != GL_UNSIGNED_INT &&
|
---|
| 341 | type != GL_FLOAT &&
|
---|
| 342 | type != GL_BITMAP) {
|
---|
| 343 | gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels(stencil type)");
|
---|
| 344 | return;
|
---|
| 345 | }
|
---|
| 346 |
|
---|
| 347 | readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
|
---|
| 348 |
|
---|
| 349 | if (ctx->Visual->StencilBits<=0) {
|
---|
| 350 | /* No stencil buffer */
|
---|
| 351 | gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
|
---|
| 352 | return;
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0;
|
---|
| 356 |
|
---|
| 357 | /* process image row by row */
|
---|
| 358 | for (j=0;j<height;j++,y++) {
|
---|
| 359 | GLvoid *dest;
|
---|
| 360 | GLstencil stencil[MAX_WIDTH];
|
---|
| 361 |
|
---|
| 362 | gl_read_stencil_span( ctx, readWidth, x, y, stencil );
|
---|
| 363 |
|
---|
| 364 | if (shift_or_offset) {
|
---|
| 365 | gl_shift_and_offset_stencil( ctx, readWidth, stencil );
|
---|
| 366 | }
|
---|
| 367 |
|
---|
| 368 | if (ctx->Pixel.MapStencilFlag) {
|
---|
| 369 | gl_map_stencil( ctx, readWidth, stencil );
|
---|
| 370 | }
|
---|
| 371 |
|
---|
[3598] | 372 | dest = _mesa_image_address( packing, pixels,
|
---|
[2938] | 373 | width, height, GL_STENCIL_INDEX, type, 0, j, 0 );
|
---|
| 374 |
|
---|
| 375 | switch (type) {
|
---|
[3598] | 376 | case GL_UNSIGNED_BYTE:
|
---|
[2938] | 377 | if (sizeof(GLstencil) == 8) {
|
---|
| 378 | MEMCPY( dest, stencil, readWidth );
|
---|
| 379 | }
|
---|
| 380 | else {
|
---|
| 381 | GLubyte *dst = (GLubyte *) dest;
|
---|
[3598] | 382 | for (i=0;i<readWidth;i++) {
|
---|
| 383 | dst[i] = (GLubyte) stencil[i];
|
---|
| 384 | }
|
---|
[2938] | 385 | }
|
---|
[3598] | 386 | break;
|
---|
| 387 | case GL_BYTE:
|
---|
[2938] | 388 | if (sizeof(GLstencil) == 8) {
|
---|
| 389 | MEMCPY( dest, stencil, readWidth );
|
---|
| 390 | }
|
---|
| 391 | else {
|
---|
| 392 | GLbyte *dst = (GLbyte *) dest;
|
---|
[3598] | 393 | for (i=0;i<readWidth;i++) {
|
---|
| 394 | dst[i] = (GLbyte) stencil[i];
|
---|
| 395 | }
|
---|
[2938] | 396 | }
|
---|
[3598] | 397 | break;
|
---|
| 398 | case GL_UNSIGNED_SHORT:
|
---|
| 399 | {
|
---|
[2938] | 400 | GLushort *dst = (GLushort *) dest;
|
---|
[3598] | 401 | for (i=0;i<readWidth;i++) {
|
---|
| 402 | dst[i] = (GLushort) stencil[i];
|
---|
| 403 | }
|
---|
| 404 | if (packing->SwapBytes) {
|
---|
| 405 | _mesa_swap2( (GLushort *) dst, readWidth );
|
---|
| 406 | }
|
---|
| 407 | }
|
---|
| 408 | break;
|
---|
| 409 | case GL_SHORT:
|
---|
| 410 | {
|
---|
[2938] | 411 | GLshort *dst = (GLshort *) dest;
|
---|
[3598] | 412 | for (i=0;i<readWidth;i++) {
|
---|
| 413 | dst[i] = (GLshort) stencil[i];
|
---|
| 414 | }
|
---|
| 415 | if (packing->SwapBytes) {
|
---|
| 416 | _mesa_swap2( (GLushort *) dst, readWidth );
|
---|
| 417 | }
|
---|
| 418 | }
|
---|
| 419 | break;
|
---|
| 420 | case GL_UNSIGNED_INT:
|
---|
| 421 | {
|
---|
[2938] | 422 | GLuint *dst = (GLuint *) dest;
|
---|
[3598] | 423 | for (i=0;i<readWidth;i++) {
|
---|
| 424 | dst[i] = (GLuint) stencil[i];
|
---|
| 425 | }
|
---|
| 426 | if (packing->SwapBytes) {
|
---|
| 427 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
| 428 | }
|
---|
| 429 | }
|
---|
| 430 | break;
|
---|
| 431 | case GL_INT:
|
---|
| 432 | {
|
---|
[2938] | 433 | GLint *dst = (GLint *) dest;
|
---|
[3598] | 434 | for (i=0;i<readWidth;i++) {
|
---|
| 435 | *dst++ = (GLint) stencil[i];
|
---|
| 436 | }
|
---|
| 437 | if (packing->SwapBytes) {
|
---|
| 438 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
| 439 | }
|
---|
| 440 | }
|
---|
| 441 | break;
|
---|
| 442 | case GL_FLOAT:
|
---|
| 443 | {
|
---|
[2938] | 444 | GLfloat *dst = (GLfloat *) dest;
|
---|
[3598] | 445 | for (i=0;i<readWidth;i++) {
|
---|
| 446 | dst[i] = (GLfloat) stencil[i];
|
---|
| 447 | }
|
---|
| 448 | if (packing->SwapBytes) {
|
---|
| 449 | _mesa_swap4( (GLuint *) dst, readWidth );
|
---|
| 450 | }
|
---|
| 451 | }
|
---|
| 452 | break;
|
---|
[2938] | 453 | case GL_BITMAP:
|
---|
| 454 | if (packing->LsbFirst) {
|
---|
| 455 | GLubyte *dst = (GLubyte*) dest;
|
---|
| 456 | GLint shift = 0;
|
---|
| 457 | for (i = 0; i < readWidth; i++) {
|
---|
| 458 | if (shift == 0)
|
---|
| 459 | *dst = 0;
|
---|
| 460 | *dst |= ((stencil != 0) << shift);
|
---|
| 461 | shift++;
|
---|
| 462 | if (shift == 8) {
|
---|
| 463 | shift = 0;
|
---|
| 464 | dst++;
|
---|
| 465 | }
|
---|
| 466 | }
|
---|
| 467 | }
|
---|
| 468 | else {
|
---|
| 469 | GLubyte *dst = (GLubyte*) dest;
|
---|
| 470 | GLint shift = 7;
|
---|
| 471 | for (i = 0; i < readWidth; i++) {
|
---|
| 472 | if (shift == 7)
|
---|
| 473 | *dst = 0;
|
---|
| 474 | *dst |= ((stencil != 0) << shift);
|
---|
| 475 | shift--;
|
---|
| 476 | if (shift < 0) {
|
---|
| 477 | shift = 7;
|
---|
| 478 | dst++;
|
---|
| 479 | }
|
---|
| 480 | }
|
---|
| 481 | }
|
---|
| 482 | break;
|
---|
| 483 | default:
|
---|
| 484 | gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
|
---|
| 485 | }
|
---|
| 486 | }
|
---|
| 487 | }
|
---|
| 488 |
|
---|
| 489 |
|
---|
| 490 |
|
---|
| 491 | /*
|
---|
| 492 | * Optimized glReadPixels for particular pixel formats:
|
---|
| 493 | * GL_UNSIGNED_BYTE, GL_RGBA
|
---|
| 494 | * when pixel scaling, biasing and mapping are disabled.
|
---|
| 495 | */
|
---|
| 496 | static GLboolean
|
---|
| 497 | read_fast_rgba_pixels( GLcontext *ctx,
|
---|
| 498 | GLint x, GLint y,
|
---|
| 499 | GLsizei width, GLsizei height,
|
---|
| 500 | GLenum format, GLenum type,
|
---|
| 501 | GLvoid *pixels,
|
---|
| 502 | const struct gl_pixelstore_attrib *packing )
|
---|
| 503 | {
|
---|
| 504 | /* can't do scale, bias or mapping */
|
---|
| 505 | if (ctx->Pixel.ScaleOrBiasRGBA || ctx->Pixel.MapColorFlag)
|
---|
| 506 | return GL_FALSE;
|
---|
| 507 |
|
---|
| 508 | /* can't do fancy pixel packing */
|
---|
| 509 | if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst)
|
---|
| 510 | return GL_FALSE;
|
---|
| 511 |
|
---|
| 512 | {
|
---|
| 513 | GLint srcX = x;
|
---|
| 514 | GLint srcY = y;
|
---|
| 515 | GLint readWidth = width; /* actual width read */
|
---|
| 516 | GLint readHeight = height; /* actual height read */
|
---|
| 517 | GLint skipPixels = packing->SkipPixels;
|
---|
| 518 | GLint skipRows = packing->SkipRows;
|
---|
| 519 | GLint rowLength;
|
---|
| 520 |
|
---|
| 521 | if (packing->RowLength > 0)
|
---|
| 522 | rowLength = packing->RowLength;
|
---|
| 523 | else
|
---|
| 524 | rowLength = width;
|
---|
| 525 |
|
---|
| 526 | /* horizontal clipping */
|
---|
[3598] | 527 | if (srcX < ctx->ReadBuffer->Xmin) {
|
---|
| 528 | skipPixels += (ctx->ReadBuffer->Xmin - srcX);
|
---|
| 529 | readWidth -= (ctx->ReadBuffer->Xmin - srcX);
|
---|
| 530 | srcX = ctx->ReadBuffer->Xmin;
|
---|
[2938] | 531 | }
|
---|
[3598] | 532 | if (srcX + readWidth > ctx->ReadBuffer->Xmax)
|
---|
| 533 | readWidth -= (srcX + readWidth - ctx->ReadBuffer->Xmax - 1);
|
---|
[2938] | 534 | if (readWidth <= 0)
|
---|
| 535 | return GL_TRUE;
|
---|
| 536 |
|
---|
| 537 | /* vertical clipping */
|
---|
[3598] | 538 | if (srcY < ctx->ReadBuffer->Ymin) {
|
---|
| 539 | skipRows += (ctx->ReadBuffer->Ymin - srcY);
|
---|
| 540 | readHeight -= (ctx->ReadBuffer->Ymin - srcY);
|
---|
| 541 | srcY = ctx->ReadBuffer->Ymin;
|
---|
[2938] | 542 | }
|
---|
[3598] | 543 | if (srcY + readHeight > ctx->ReadBuffer->Ymax)
|
---|
| 544 | readHeight -= (srcY + readHeight - ctx->ReadBuffer->Ymax - 1);
|
---|
[2938] | 545 | if (readHeight <= 0)
|
---|
| 546 | return GL_TRUE;
|
---|
| 547 |
|
---|
| 548 | /*
|
---|
| 549 | * Ready to read!
|
---|
| 550 | * The window region at (destX, destY) of size (readWidth, readHeight)
|
---|
| 551 | * will be read back.
|
---|
| 552 | * We'll write pixel data to buffer pointed to by "pixels" but we'll
|
---|
| 553 | * skip "skipRows" rows and skip "skipPixels" pixels/row.
|
---|
| 554 | */
|
---|
| 555 | if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
|
---|
| 556 | GLubyte *dest = (GLubyte *) pixels
|
---|
| 557 | + (skipRows * rowLength + skipPixels) * 4;
|
---|
| 558 | GLint row;
|
---|
| 559 | for (row=0; row<readHeight; row++) {
|
---|
| 560 | (*ctx->Driver.ReadRGBASpan)(ctx, readWidth, srcX, srcY,
|
---|
| 561 | (GLubyte (*)[4]) dest);
|
---|
| 562 | if (ctx->Visual->SoftwareAlpha) {
|
---|
| 563 | gl_read_alpha_span(ctx, readWidth, srcX, srcY,
|
---|
| 564 | (GLubyte (*)[4]) dest);
|
---|
| 565 | }
|
---|
| 566 | dest += rowLength * 4;
|
---|
| 567 | srcY++;
|
---|
| 568 | }
|
---|
| 569 | return GL_TRUE;
|
---|
| 570 | }
|
---|
| 571 | else {
|
---|
| 572 | /* can't do this format/type combination */
|
---|
| 573 | return GL_FALSE;
|
---|
| 574 | }
|
---|
| 575 | }
|
---|
| 576 | }
|
---|
| 577 |
|
---|
| 578 |
|
---|
| 579 |
|
---|
| 580 | /*
|
---|
| 581 | * Read R, G, B, A, RGB, L, or LA pixels.
|
---|
| 582 | */
|
---|
| 583 | static void read_rgba_pixels( GLcontext *ctx,
|
---|
| 584 | GLint x, GLint y,
|
---|
| 585 | GLsizei width, GLsizei height,
|
---|
| 586 | GLenum format, GLenum type, GLvoid *pixels,
|
---|
| 587 | const struct gl_pixelstore_attrib *packing )
|
---|
| 588 | {
|
---|
| 589 | GLint readWidth;
|
---|
| 590 |
|
---|
[3598] | 591 | (*ctx->Driver.SetReadBuffer)(ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer);
|
---|
[2938] | 592 |
|
---|
| 593 | /* Try optimized path first */
|
---|
| 594 | if (read_fast_rgba_pixels( ctx, x, y, width, height,
|
---|
| 595 | format, type, pixels, packing )) {
|
---|
| 596 |
|
---|
[3598] | 597 | (*ctx->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer);
|
---|
[2938] | 598 | return; /* done! */
|
---|
| 599 | }
|
---|
| 600 |
|
---|
| 601 | readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
|
---|
| 602 |
|
---|
| 603 | /* do error checking on pixel type, format was already checked by caller */
|
---|
| 604 | switch (type) {
|
---|
| 605 | case GL_UNSIGNED_BYTE:
|
---|
| 606 | case GL_BYTE:
|
---|
| 607 | case GL_UNSIGNED_SHORT:
|
---|
| 608 | case GL_SHORT:
|
---|
| 609 | case GL_UNSIGNED_INT:
|
---|
| 610 | case GL_INT:
|
---|
| 611 | case GL_FLOAT:
|
---|
| 612 | case GL_UNSIGNED_BYTE_3_3_2:
|
---|
| 613 | case GL_UNSIGNED_BYTE_2_3_3_REV:
|
---|
| 614 | case GL_UNSIGNED_SHORT_5_6_5:
|
---|
| 615 | case GL_UNSIGNED_SHORT_5_6_5_REV:
|
---|
| 616 | case GL_UNSIGNED_SHORT_4_4_4_4:
|
---|
| 617 | case GL_UNSIGNED_SHORT_4_4_4_4_REV:
|
---|
| 618 | case GL_UNSIGNED_SHORT_5_5_5_1:
|
---|
| 619 | case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
---|
| 620 | case GL_UNSIGNED_INT_8_8_8_8:
|
---|
| 621 | case GL_UNSIGNED_INT_8_8_8_8_REV:
|
---|
| 622 | case GL_UNSIGNED_INT_10_10_10_2:
|
---|
| 623 | case GL_UNSIGNED_INT_2_10_10_10_REV:
|
---|
| 624 | /* valid pixel type */
|
---|
| 625 | break;
|
---|
| 626 | default:
|
---|
| 627 | gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
|
---|
| 628 | return;
|
---|
| 629 | }
|
---|
| 630 |
|
---|
[3598] | 631 | if (!_mesa_is_legal_format_and_type(format, type)) {
|
---|
[2938] | 632 | gl_error(ctx, GL_INVALID_OPERATION, "glReadPixels(format or type)");
|
---|
| 633 | return;
|
---|
| 634 | }
|
---|
| 635 |
|
---|
| 636 | if (ctx->Visual->RGBAflag) {
|
---|
| 637 | GLint j;
|
---|
| 638 | for (j=0;j<height;j++,y++) {
|
---|
| 639 | GLubyte rgba[MAX_WIDTH][4];
|
---|
| 640 | GLvoid *dest;
|
---|
| 641 |
|
---|
[3598] | 642 | gl_read_rgba_span( ctx, ctx->ReadBuffer, readWidth, x, y, rgba );
|
---|
[2938] | 643 |
|
---|
[3598] | 644 | dest = _mesa_image_address( packing, pixels, width, height,
|
---|
[2938] | 645 | format, type, 0, j, 0);
|
---|
| 646 |
|
---|
[3598] | 647 | _mesa_pack_rgba_span( ctx, readWidth, (const GLubyte (*)[4]) rgba,
|
---|
| 648 | format, type, dest, packing, GL_TRUE );
|
---|
[2938] | 649 | }
|
---|
| 650 | }
|
---|
| 651 | else {
|
---|
| 652 | GLint j;
|
---|
| 653 | for (j=0;j<height;j++,y++) {
|
---|
| 654 | GLubyte rgba[MAX_WIDTH][4];
|
---|
[3598] | 655 | GLuint index[MAX_WIDTH];
|
---|
[2938] | 656 | GLvoid *dest;
|
---|
| 657 |
|
---|
[3598] | 658 | (*ctx->Driver.ReadCI32Span)( ctx, readWidth, x, y, index );
|
---|
[2938] | 659 |
|
---|
[3598] | 660 | if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) {
|
---|
[2938] | 661 | gl_map_ci( ctx, readWidth, index );
|
---|
[3598] | 662 | }
|
---|
[2938] | 663 |
|
---|
| 664 | gl_map_ci_to_rgba(ctx, readWidth, index, rgba );
|
---|
| 665 |
|
---|
[3598] | 666 | dest = _mesa_image_address( packing, pixels, width, height,
|
---|
[2938] | 667 | format, type, 0, j, 0);
|
---|
| 668 |
|
---|
[3598] | 669 | _mesa_pack_rgba_span( ctx, readWidth, (const GLubyte (*)[4]) rgba,
|
---|
| 670 | format, type, dest, packing, GL_TRUE );
|
---|
[2938] | 671 | }
|
---|
| 672 | }
|
---|
| 673 |
|
---|
[3598] | 674 | (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer );
|
---|
[2938] | 675 | }
|
---|
| 676 |
|
---|
| 677 |
|
---|
| 678 |
|
---|
[3598] | 679 | void
|
---|
| 680 | _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
|
---|
| 681 | GLenum format, GLenum type, GLvoid *pixels )
|
---|
[2938] | 682 | {
|
---|
[3598] | 683 | GET_CURRENT_CONTEXT(ctx);
|
---|
[2938] | 684 | ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glReadPixels");
|
---|
| 685 |
|
---|
| 686 | if (!pixels) {
|
---|
| 687 | gl_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
|
---|
| 688 | return;
|
---|
| 689 | }
|
---|
| 690 |
|
---|
[3598] | 691 | if (ctx->Driver.ReadPixels &&
|
---|
| 692 | (*ctx->Driver.ReadPixels)(ctx, x, y, width, height,
|
---|
| 693 | format, type, &ctx->Pack, pixels))
|
---|
| 694 | return;
|
---|
| 695 |
|
---|
[2938] | 696 | switch (format) {
|
---|
| 697 | case GL_COLOR_INDEX:
|
---|
[3598] | 698 | read_index_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack );
|
---|
| 699 | break;
|
---|
[2938] | 700 | case GL_STENCIL_INDEX:
|
---|
[3598] | 701 | read_stencil_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack );
|
---|
[2938] | 702 | break;
|
---|
| 703 | case GL_DEPTH_COMPONENT:
|
---|
[3598] | 704 | read_depth_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack );
|
---|
| 705 | break;
|
---|
[2938] | 706 | case GL_RED:
|
---|
| 707 | case GL_GREEN:
|
---|
| 708 | case GL_BLUE:
|
---|
| 709 | case GL_ALPHA:
|
---|
| 710 | case GL_RGB:
|
---|
| 711 | case GL_LUMINANCE:
|
---|
| 712 | case GL_LUMINANCE_ALPHA:
|
---|
| 713 | case GL_RGBA:
|
---|
| 714 | case GL_BGR:
|
---|
| 715 | case GL_BGRA:
|
---|
| 716 | case GL_ABGR_EXT:
|
---|
[3598] | 717 | read_rgba_pixels(ctx, x, y, width, height,
|
---|
| 718 | format, type, pixels, &ctx->Pack );
|
---|
| 719 | break;
|
---|
[2938] | 720 | default:
|
---|
[3598] | 721 | gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(format)" );
|
---|
[2938] | 722 | }
|
---|
| 723 | }
|
---|