This is readpix.c in view mode; [Download] [Up]
/* $Id: readpix.c,v 1.9 1997/05/28 03:26:18 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 2.3 * Copyright (C) 1995-1997 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Log: readpix.c,v $ * Revision 1.9 1997/05/28 03:26:18 brianp * added precompiled header (PCH) support * * Revision 1.8 1997/05/08 01:43:50 brianp * added error check to gl_ReadPixels() for inside glBegin/glEnd * * Revision 1.7 1997/02/03 20:31:15 brianp * added a few DEFARRAY macros for BeOS * * Revision 1.6 1997/01/16 19:24:05 brianp * replaced a few abort()'s with gl_error() calls * * Revision 1.5 1996/12/20 20:28:04 brianp * use DEF/UNDEFARRAY() macros in read_color_pixels() for Mac compilers * * Revision 1.4 1996/11/01 03:20:47 brianp * reading GL_LUMINANCE pixels weren't clamped * * Revision 1.3 1996/09/27 01:29:47 brianp * added missing default cases to switches * * Revision 1.2 1996/09/15 14:18:37 brianp * now use GLframebuffer and GLvisual * * Revision 1.1 1996/09/13 01:38:16 brianp * Initial revision * */ #ifdef PCH #include "all.h" #else #include <math.h> #include <stdlib.h> #include <string.h> #include "alphabuf.h" #include "context.h" #include "depth.h" #include "feedback.h" #include "dlist.h" #include "macros.h" #include "image.h" #include "readpix.h" #include "span.h" #include "stencil.h" #include "types.h" #endif /* * Read a block of color index pixels. */ static void read_index_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, GLvoid *pixels ) { GLint i, j; GLuint a, s, k, l, start; /* error checking */ if (ctx->Visual->RGBAflag) { gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); return; } /* Size of each component */ s = gl_sizeof_type( type ); if (s<=0) { gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); return; } /* Compute packing parameters */ a = ctx->Pack.Alignment; if (ctx->Pack.RowLength>0) { l = ctx->Pack.RowLength; } else { l = width; } /* k = offset between rows in components */ if (s>=a) { k = l; } else { k = a/s * CEILING( s*l, a ); } /* offset to first component returned */ start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels; /* process image row by row */ for (j=0;j<height;j++,y++) { GLuint index[MAX_WIDTH]; (*ctx->Driver.ReadIndexSpan)( ctx, width, x, y, index ); if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) { GLuint s; if (ctx->Pixel.IndexShift<0) { /* right shift */ s = -ctx->Pixel.IndexShift; for (i=0;i<width;i++) { index[i] = (index[i] >> s) + ctx->Pixel.IndexOffset; } } else { /* left shift */ s = ctx->Pixel.IndexShift; for (i=0;i<width;i++) { index[i] = (index[i] << s) + ctx->Pixel.IndexOffset; } } } if (ctx->Pixel.MapColorFlag) { for (i=0;i<width;i++) { index[i] = ctx->Pixel.MapItoI[ index[i] ]; } } switch (type) { case GL_UNSIGNED_BYTE: { GLubyte *dst = (GLubyte *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLubyte) index[i]; } } break; case GL_BYTE: { GLbyte *dst = (GLbyte *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLbyte) index[i]; } } break; case GL_UNSIGNED_SHORT: { GLushort *dst = (GLushort *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLushort) index[i]; } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start + j * k, width ); } } break; case GL_SHORT: { GLshort *dst = (GLshort *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLshort) index[i]; } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start + j * k, width ); } } break; case GL_UNSIGNED_INT: { GLuint *dst = (GLuint *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLuint) index[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width ); } } break; case GL_INT: { GLint *dst = (GLint *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLint) index[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width ); } } break; case GL_FLOAT: { GLfloat *dst = (GLfloat *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLfloat) index[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width ); } } break; default: gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); } } } static void read_depth_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, GLvoid *pixels ) { GLint i, j; GLuint a, s, k, l, start; GLboolean bias_or_scale; /* Error checking */ if (ctx->Visual->DepthBits<=0) { /* No depth buffer */ gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); return; } bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; /* Size of each component */ s = gl_sizeof_type( type ); if (s<=0) { gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); return; } /* Compute packing parameters */ a = ctx->Pack.Alignment; if (ctx->Pack.RowLength>0) { l = ctx->Pack.RowLength; } else { l = width; } /* k = offset between rows in components */ if (s>=a) { k = l; } else { k = a/s * CEILING( s*l, a ); } /* offset to first component returned */ start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels; if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort) && !bias_or_scale && !ctx->Pack.SwapBytes) { /* Special case: directly read 16-bit unsigned depth values. */ for (j=0;j<height;j++,y++) { GLushort *dst = (GLushort *) pixels + start + j * k; (*ctx->Driver.ReadDepthSpanInt)( ctx, width, x, y, (GLdepth*) dst); } } else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint) && !bias_or_scale && !ctx->Pack.SwapBytes) { /* Special case: directly read 32-bit unsigned depth values. */ /* Compute shift value to scale depth values up to 32-bit uints. */ GLuint shift = 0; GLuint max = MAX_DEPTH; while ((max&0x80000000)==0) { max = max << 1; shift++; } for (j=0;j<height;j++,y++) { GLuint *dst = (GLuint *) pixels + start + j * k; (*ctx->Driver.ReadDepthSpanInt)( ctx, width, x, y, (GLdepth*) dst); for (i=0;i<width;i++) { dst[i] = dst[i] << shift; } } } else { /* General case (slow) */ for (j=0;j<height;j++,y++) { GLfloat depth[MAX_WIDTH]; (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, x, y, depth ); if (bias_or_scale) { for (i=0;i<width;i++) { GLfloat d; d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; depth[i] = CLAMP( d, 0.0, 1.0 ); } } switch (type) { case GL_UNSIGNED_BYTE: { GLubyte *dst = (GLubyte *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = FLOAT_TO_UBYTE( depth[i] ); } } break; case GL_BYTE: { GLbyte *dst = (GLbyte *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = FLOAT_TO_BYTE( depth[i] ); } } break; case GL_UNSIGNED_SHORT: { GLushort *dst = (GLushort *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = FLOAT_TO_USHORT( depth[i] ); } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start + j * k, width ); } } break; case GL_SHORT: { GLshort *dst = (GLshort *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = FLOAT_TO_SHORT( depth[i] ); } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start + j * k, width ); } } break; case GL_UNSIGNED_INT: { GLuint *dst = (GLuint *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = FLOAT_TO_UINT( depth[i] ); } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width ); } } break; case GL_INT: { GLint *dst = (GLint *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = FLOAT_TO_INT( depth[i] ); } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width ); } } break; case GL_FLOAT: { GLfloat *dst = (GLfloat *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = depth[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width ); } } break; default: gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); } } } } static void read_stencil_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, GLvoid *pixels ) { GLint i, j; GLuint a, s, k, l, start; GLboolean shift_or_offset; if (ctx->Visual->StencilBits<=0) { /* No stencil buffer */ gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); return; } shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0; /* Size of each component */ s = gl_sizeof_type( type ); if (s<=0) { gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); return; } /* Compute packing parameters */ a = ctx->Pack.Alignment; if (ctx->Pack.RowLength>0) { l = ctx->Pack.RowLength; } else { l = width; } /* k = offset between rows in components */ if (s>=a) { k = l; } else { k = a/s * CEILING( s*l, a ); } /* offset to first component returned */ start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels; /* process image row by row */ for (j=0;j<height;j++,y++) { GLubyte stencil[MAX_WIDTH]; gl_read_stencil_span( ctx, width, x, y, stencil ); if (shift_or_offset) { GLuint s; if (ctx->Pixel.IndexShift<0) { /* right shift */ s = -ctx->Pixel.IndexShift; for (i=0;i<width;i++) { stencil[i] = (stencil[i] >> s) + ctx->Pixel.IndexOffset; } } else { /* left shift */ s = ctx->Pixel.IndexShift; for (i=0;i<width;i++) { stencil[i] = (stencil[i] << s) + ctx->Pixel.IndexOffset; } } } if (ctx->Pixel.MapStencilFlag) { for (i=0;i<width;i++) { stencil[i] = ctx->Pixel.MapStoS[ stencil[i] ]; } } switch (type) { case GL_UNSIGNED_BYTE: { GLubyte *dst = (GLubyte *) pixels + start + j * k; MEMCPY( dst, stencil, width ); } break; case GL_BYTE: { GLbyte *dst = (GLbyte *) pixels + start + j * k; MEMCPY( dst, stencil, width ); } break; case GL_UNSIGNED_SHORT: { GLushort *dst = (GLushort *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLushort) stencil[i]; } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start +j * k, width ); } } break; case GL_SHORT: { GLshort *dst = (GLshort *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLshort) stencil[i]; } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start +j * k, width ); } } break; case GL_UNSIGNED_INT: { GLuint *dst = (GLuint *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLuint) stencil[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start +j * k, width ); } } break; case GL_INT: { GLint *dst = (GLint *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLint) stencil[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start +j * k, width ); } } break; case GL_FLOAT: { GLfloat *dst = (GLfloat *) pixels + start + j * k; for (i=0;i<width;i++) { *dst++ = (GLfloat) stencil[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start +j * k, width ); } } break; default: gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); } } } /* * Test if scaling or biasing of colors is needed. */ static GLboolean scale_or_bias_rgba( GLcontext *ctx ) { if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F || ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F || ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F || ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) { return GL_TRUE; } else { return GL_FALSE; } } /* * Apply scale and bias factors to an array of RGBA pixels. */ static void scale_and_bias_rgba( GLcontext *ctx, GLint n, GLfloat red[], GLfloat green[], GLfloat blue[], GLfloat alpha[] ) { register GLint i; register GLfloat r, g, b, a; for (i=0;i<n;i++) { r = red[i] * ctx->Pixel.RedScale + ctx->Pixel.RedBias; g = green[i] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; b = blue[i] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; a = alpha[i] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; red[i] = CLAMP( r, 0.0F, 1.0F ); green[i] = CLAMP( g, 0.0F, 1.0F ); blue[i] = CLAMP( b, 0.0F, 1.0F ); alpha[i] = CLAMP( a, 0.0F, 1.0F ); } } /* * Apply pixel mapping to an array of RGBA pixels. */ static void map_rgba( GLcontext *ctx, GLint n, GLfloat red[], GLfloat green[], GLfloat blue[], GLfloat alpha[] ) { GLfloat rscale = ctx->Pixel.MapRtoRsize-1; GLfloat gscale = ctx->Pixel.MapGtoGsize-1; GLfloat bscale = ctx->Pixel.MapBtoBsize-1; GLfloat ascale = ctx->Pixel.MapAtoAsize-1; GLint i; for (i=0;i<n;i++) { red[i] = ctx->Pixel.MapRtoR[ (GLint) (red[i] * rscale) ]; green[i] = ctx->Pixel.MapGtoG[ (GLint) (green[i] * gscale) ]; blue[i] = ctx->Pixel.MapBtoB[ (GLint) (blue[i] * bscale) ]; alpha[i] = ctx->Pixel.MapAtoA[ (GLint) (alpha[i] * ascale) ]; } } /* * Read R, G, B, A, RGB, L, or LA pixels. */ static void read_color_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) { GLint i, j, n, a, s, l, k; GLboolean scale_or_bias; DEFARRAY(GLfloat, red, MAX_WIDTH); DEFARRAY(GLfloat, green, MAX_WIDTH); DEFARRAY(GLfloat, blue, MAX_WIDTH); DEFARRAY(GLfloat, alpha, MAX_WIDTH); DEFARRAY(GLfloat, luminance, MAX_WIDTH); GLboolean r_flag, g_flag, b_flag, a_flag, l_flag; GLuint start; scale_or_bias = scale_or_bias_rgba( ctx ); /* Determine how many / which components to return */ r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE; switch (format) { case GL_RED: r_flag = GL_TRUE; n = 1; break; case GL_GREEN: g_flag = GL_TRUE; n = 1; break; case GL_BLUE: b_flag = GL_TRUE; n = 1; break; case GL_ALPHA: a_flag = GL_TRUE; n = 1; break; case GL_LUMINANCE: l_flag = GL_TRUE; n = 1; break; case GL_LUMINANCE_ALPHA: l_flag = a_flag = GL_TRUE; n = 2; break; case GL_RGB: r_flag = g_flag = b_flag = GL_TRUE; n = 3; break; case GL_RGBA: r_flag = g_flag = b_flag = a_flag = GL_TRUE; n = 4; break; default: gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(format)" ); UNDEFARRAY( red ); UNDEFARRAY( green ); UNDEFARRAY( blue ); UNDEFARRAY( alpha ); UNDEFARRAY( luminance ); return; } /* Size of each component */ s = gl_sizeof_type( type ); if (s<=0) { gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); UNDEFARRAY( red ); UNDEFARRAY( green ); UNDEFARRAY( blue ); UNDEFARRAY( alpha ); UNDEFARRAY( luminance ); return; } /* Compute packing parameters */ a = ctx->Pack.Alignment; if (ctx->Pack.RowLength>0) { l = ctx->Pack.RowLength; } else { l = width; } /* k = offset between rows in components */ if (s>=a) { k = n * l; } else { k = a/s * CEILING( s*n*l, a ); } /* offset to first component returned */ start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels * n; /* process image row by row */ for (j=0;j<height;j++,y++) { /* * Read the pixels from frame buffer */ if (ctx->Visual->RGBAflag) { DEFARRAY(GLubyte, r, MAX_WIDTH); DEFARRAY(GLubyte, g, MAX_WIDTH); DEFARRAY(GLubyte, b, MAX_WIDTH); DEFARRAY(GLubyte, a, MAX_WIDTH); GLfloat rscale = 1.0F * ctx->Visual->InvRedScale; GLfloat gscale = 1.0F * ctx->Visual->InvGreenScale; GLfloat bscale = 1.0F * ctx->Visual->InvBlueScale; GLfloat ascale = 1.0F * ctx->Visual->InvAlphaScale; /* read colors and convert to floats */ (*ctx->Driver.ReadColorSpan)( ctx, width, x, y, r, g, b, a ); if (ctx->RasterMask & ALPHABUF_BIT) { gl_read_alpha_span( ctx, width, x, y, a ); } for (i=0;i<width;i++) { red[i] = r[i] * rscale; green[i] = g[i] * gscale; blue[i] = b[i] * bscale; alpha[i] = a[i] * ascale; } if (scale_or_bias) { scale_and_bias_rgba( ctx, width, red, green, blue, alpha ); } if (ctx->Pixel.MapColorFlag) { map_rgba( ctx, width, red, green, blue, alpha ); } UNDEFARRAY(r); UNDEFARRAY(g); UNDEFARRAY(b); UNDEFARRAY(a); } else { /* convert CI values to RGBA */ GLuint index[MAX_WIDTH]; (*ctx->Driver.ReadIndexSpan)( ctx, width, x, y, index ); if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) { GLuint s; if (ctx->Pixel.IndexShift<0) { /* right shift */ s = -ctx->Pixel.IndexShift; for (i=0;i<width;i++) { index[i] = (index[i] >> s) + ctx->Pixel.IndexOffset; } } else { /* left shift */ s = ctx->Pixel.IndexShift; for (i=0;i<width;i++) { index[i] = (index[i] << s) + ctx->Pixel.IndexOffset; } } } for (i=0;i<width;i++) { red[i] = ctx->Pixel.MapItoR[ index[i] ]; green[i] = ctx->Pixel.MapItoG[ index[i] ]; blue[i] = ctx->Pixel.MapItoB[ index[i] ]; alpha[i] = ctx->Pixel.MapItoA[ index[i] ]; } } if (l_flag) { for (i=0;i<width;i++) { GLfloat sum = red[i] + green[i] + blue[i]; luminance[i] = CLAMP( sum, 0.0F, 1.0F ); } } /* * Pack/transfer/store the pixels */ switch (type) { case GL_UNSIGNED_BYTE: { GLubyte *dst = (GLubyte *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = FLOAT_TO_UBYTE( red[i] ); if (g_flag) *dst++ = FLOAT_TO_UBYTE( green[i] ); if (b_flag) *dst++ = FLOAT_TO_UBYTE( blue[i] ); if (l_flag) *dst++ = FLOAT_TO_UBYTE( luminance[i] ); if (a_flag) *dst++ = FLOAT_TO_UBYTE( alpha[i] ); } } break; case GL_BYTE: { GLbyte *dst = (GLbyte *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = FLOAT_TO_BYTE( red[i] ); if (g_flag) *dst++ = FLOAT_TO_BYTE( green[i] ); if (b_flag) *dst++ = FLOAT_TO_BYTE( blue[i] ); if (l_flag) *dst++ = FLOAT_TO_BYTE( luminance[i] ); if (a_flag) *dst++ = FLOAT_TO_BYTE( alpha[i] ); } } break; case GL_UNSIGNED_SHORT: { GLushort *dst = (GLushort *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = FLOAT_TO_USHORT( red[i] ); if (g_flag) *dst++ = FLOAT_TO_USHORT( green[i] ); if (b_flag) *dst++ = FLOAT_TO_USHORT( blue[i] ); if (l_flag) *dst++ = FLOAT_TO_USHORT( luminance[i] ); if (a_flag) *dst++ = FLOAT_TO_USHORT( alpha[i] ); } } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start + j * k, width*n ); } break; case GL_SHORT: { GLshort *dst = (GLshort *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = FLOAT_TO_SHORT( red[i] ); if (g_flag) *dst++ = FLOAT_TO_SHORT( green[i] ); if (b_flag) *dst++ = FLOAT_TO_SHORT( blue[i] ); if (l_flag) *dst++ = FLOAT_TO_SHORT( luminance[i] ); if (a_flag) *dst++ = FLOAT_TO_SHORT( alpha[i] ); } if (ctx->Pack.SwapBytes) { gl_swap2( (GLushort *) pixels + start + j * k, width*n ); } } break; case GL_UNSIGNED_INT: { GLuint *dst = (GLuint *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = FLOAT_TO_UINT( red[i] ); if (g_flag) *dst++ = FLOAT_TO_UINT( green[i] ); if (b_flag) *dst++ = FLOAT_TO_UINT( blue[i] ); if (l_flag) *dst++ = FLOAT_TO_UINT( luminance[i] ); if (a_flag) *dst++ = FLOAT_TO_UINT( alpha[i] ); } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width*n ); } } break; case GL_INT: { GLint *dst = (GLint *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = FLOAT_TO_INT( red[i] ); if (g_flag) *dst++ = FLOAT_TO_INT( green[i] ); if (b_flag) *dst++ = FLOAT_TO_INT( blue[i] ); if (l_flag) *dst++ = FLOAT_TO_INT( luminance[i] ); if (a_flag) *dst++ = FLOAT_TO_INT( alpha[i] ); } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width*n ); } } break; case GL_FLOAT: { GLfloat *dst = (GLfloat *) pixels + start + j * k; for (i=0;i<width;i++) { if (r_flag) *dst++ = red[i]; if (g_flag) *dst++ = green[i]; if (b_flag) *dst++ = blue[i]; if (l_flag) *dst++ = luminance[i]; if (a_flag) *dst++ = alpha[i]; } if (ctx->Pack.SwapBytes) { gl_swap4( (GLuint *) pixels + start + j * k, width*n ); } } break; default: gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" ); } } UNDEFARRAY( red ); UNDEFARRAY( green ); UNDEFARRAY( blue ); UNDEFARRAY( alpha ); UNDEFARRAY( luminance ); } void gl_ReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) { if (INSIDE_BEGIN_END(ctx)) { gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" ); return; } (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer ); switch (format) { case GL_COLOR_INDEX: read_index_pixels( ctx, x, y, width, height, type, pixels ); break; case GL_STENCIL_INDEX: read_stencil_pixels( ctx, x, y, width, height, type, pixels ); break; case GL_DEPTH_COMPONENT: read_depth_pixels( ctx, x, y, width, height, type, pixels ); break; case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_RGB: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_RGBA: read_color_pixels( ctx, x, y, width, height, format, type, pixels ); break; default: gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(format)" ); } (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer ); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.