home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / readpix.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  26KB  |  948 lines

  1. /* $Id: readpix.c,v 1.14 1996/05/01 15:49:44 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995-1996  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Log: readpix.c,v $
  26.  * Revision 1.14  1996/05/01  15:49:44  brianp
  27.  * optimized glReadPixels() for GLuint and GLushort GL_DEPTH reading
  28.  *
  29.  * Revision 1.13  1996/04/25  20:41:45  brianp
  30.  * replaced gl_read_depth_span() call with DD.read_depth_span()
  31.  *
  32.  * Revision 1.12  1996/04/15  14:13:22  brianp
  33.  * better pixel mapping
  34.  *
  35.  * Revision 1.11  1996/02/19  21:50:00  brianp
  36.  * added support for software alpha buffering
  37.  *
  38.  * Revision 1.10  1995/10/14  16:27:03  brianp
  39.  * use DD.set_buffer
  40.  *
  41.  * Revision 1.9  1995/10/04  22:08:52  brianp
  42.  * replaced i with j in byte swap function calls
  43.  *
  44.  * Revision 1.8  1995/08/31  21:26:39  brianp
  45.  * use DD.read_*_span instead of dd_read_*_span
  46.  *
  47.  * Revision 1.7  1995/07/24  20:34:16  brianp
  48.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  49.  *
  50.  * Revision 1.6  1995/06/12  15:52:41  brianp
  51.  * renamed from readpixels.c to readpix.c
  52.  *
  53.  * Revision 1.5  1995/06/12  15:42:37  brianp
  54.  * changed color arrays to GLubyte
  55.  *
  56.  * Revision 1.4  1995/05/22  21:02:41  brianp
  57.  * Release 1.2
  58.  *
  59.  * Revision 1.3  1995/03/13  20:54:53  brianp
  60.  * added read buffer logic
  61.  *
  62.  * Revision 1.2  1995/03/04  19:29:44  brianp
  63.  * 1.1 beta revision
  64.  *
  65.  * Revision 1.1  1995/02/24  14:27:03  brianp
  66.  * Initial revision
  67.  *
  68.  */
  69.  
  70.  
  71. #include <math.h>
  72. #include <stdlib.h>
  73. #include <string.h>
  74. #include "alphabuf.h"
  75. #include "context.h"
  76. #include "depth.h"
  77. #include "dd.h"
  78. #include "feedback.h"
  79. #include "list.h"
  80. #include "macros.h"
  81. #include "span.h"
  82. #include "stencil.h"
  83.  
  84.  
  85.  
  86.  
  87. /*
  88.  * Compute ceiling of integer quotient of A divided by B:
  89.  */
  90. #define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
  91.  
  92.  
  93.  
  94. /*
  95.  * Flip the order of the 4 bytes in each word in the given array.
  96.  */
  97. static void swap4( GLuint *p, GLuint n )
  98. {
  99.    register GLuint i, a, b;
  100.  
  101.    for (i=0;i<n;i++) {
  102.       b = p[i];
  103.       a =  (b >> 24)
  104.     | ((b >> 8) & 0xff00)
  105.     | ((b << 8) & 0xff0000)
  106.     | ((b << 24) & 0xff000000);
  107.       p[i] = a;
  108.    }
  109. }
  110.  
  111.  
  112. /*
  113.  * Flip the order of the 2 bytes in each word in the given array.
  114.  */
  115. static void swap2( GLushort *p, GLuint n )
  116. {
  117.    register GLuint i;
  118.  
  119.    for (i=0;i<n;i++) {
  120.       p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
  121.    }
  122. }
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129. /**********************************************************************/
  130. /*****                         glReadPixels                       *****/
  131. /**********************************************************************/
  132.  
  133.  
  134. /*
  135.  * Read a block of color index pixels.
  136.  */
  137. static void read_index_pixels( GLint x, GLint y,
  138.                    GLsizei width, GLsizei height,
  139.                    GLenum type, GLvoid *pixels )
  140. {
  141.    GLint i, j;
  142.    GLuint a, s, k, l, start;
  143.  
  144.    /* error checking */
  145.    if (CC.RGBAflag) {
  146.       gl_error( GL_INVALID_OPERATION, "glReadPixels" );
  147.       return;
  148.    }
  149.  
  150.    /* Size of each component */
  151.    switch (type) {
  152.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  153.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  154.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  155.       case GL_SHORT:        s = sizeof(GLshort);    break;
  156.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  157.       case GL_INT:        s = sizeof(GLint);    break;
  158.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  159.       default:
  160.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  161.      return;
  162.    }
  163.  
  164.    /* Compute packing parameters */
  165.    a = CC.PackAlignment;
  166.    if (CC.PackRowLength>0) {
  167.       l = CC.PackRowLength;
  168.    }
  169.    else {
  170.       l = width;
  171.    }
  172.    /* k = offset between rows in components */
  173.    if (s>=a) {
  174.       k = l;
  175.    }
  176.    else {
  177.       k = a/s * CEILING( s*l, a );
  178.    }
  179.  
  180.    /* offset to first component returned */
  181.    start = CC.PackSkipRows * k + CC.PackSkipPixels;
  182.  
  183.    /* process image row by row */
  184.    for (j=0;j<height;j++,y++) {
  185.       GLuint index[MAX_WIDTH];
  186.       (*DD.read_index_span)( width, x, y, index );
  187.  
  188.       if (CC.Pixel.IndexShift!=0 || CC.Pixel.IndexOffset!=0) {
  189.      GLuint s;
  190.      if (CC.Pixel.IndexShift<0) {
  191.         /* right shift */
  192.         s = -CC.Pixel.IndexShift;
  193.         for (i=0;i<width;i++) {
  194.            index[i] = (index[i] >> s) + CC.Pixel.IndexOffset;
  195.         }
  196.      }
  197.      else {
  198.         /* left shift */
  199.         s = CC.Pixel.IndexShift;
  200.         for (i=0;i<width;i++) {
  201.            index[i] = (index[i] << s) + CC.Pixel.IndexOffset;
  202.         }
  203.      }
  204.       }
  205.  
  206.       if (CC.Pixel.MapColorFlag) {
  207.      for (i=0;i<width;i++) {
  208.         index[i] = CC.Pixel.MapItoI[ index[i] ];
  209.      }
  210.       }
  211.  
  212.       switch (type) {
  213.      case GL_UNSIGNED_BYTE:
  214.         {
  215.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  216.            for (i=0;i<width;i++) {
  217.           *dst++ = (GLubyte) index[i];
  218.            }
  219.         }
  220.         break;
  221.      case GL_BYTE:
  222.         {
  223.            GLbyte *dst = (GLbyte *) pixels + start + j * k;
  224.            for (i=0;i<width;i++) {
  225.           *dst++ = (GLbyte) index[i];
  226.            }
  227.         }
  228.         break;
  229.      case GL_UNSIGNED_SHORT:
  230.         {
  231.            GLushort *dst = (GLushort *) pixels + start + j * k;
  232.            for (i=0;i<width;i++) {
  233.           *dst++ = (GLushort) index[i];
  234.            }
  235.            if (CC.PackSwapBytes) {
  236.           swap2( (GLushort *) pixels + start + j * k, width );
  237.            }
  238.         }
  239.         break;
  240.      case GL_SHORT:
  241.         {
  242.            GLshort *dst = (GLshort *) pixels + start + j * k;
  243.            for (i=0;i<width;i++) {
  244.           *dst++ = (GLshort) index[i];
  245.            }
  246.            if (CC.PackSwapBytes) {
  247.           swap2( (GLushort *) pixels + start + j * k, width );
  248.            }
  249.         }
  250.         break;
  251.      case GL_UNSIGNED_INT:
  252.         {
  253.            GLuint *dst = (GLuint *) pixels + start + j * k;
  254.            for (i=0;i<width;i++) {
  255.           *dst++ = (GLuint) index[i];
  256.            }
  257.            if (CC.PackSwapBytes) {
  258.           swap4( (GLuint *) pixels + start + j * k, width );
  259.            }
  260.         }
  261.         break;
  262.      case GL_INT:
  263.         {
  264.            GLint *dst = (GLint *) pixels + start + j * k;
  265.            for (i=0;i<width;i++) {
  266.           *dst++ = (GLint) index[i];
  267.            }
  268.            if (CC.PackSwapBytes) {
  269.           swap4( (GLuint *) pixels + start + j * k, width );
  270.            }
  271.         }
  272.         break;
  273.      case GL_FLOAT:
  274.         {
  275.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  276.            for (i=0;i<width;i++) {
  277.           *dst++ = (GLfloat) index[i];
  278.            }
  279.            if (CC.PackSwapBytes) {
  280.           swap4( (GLuint *) pixels + start + j * k, width );
  281.            }
  282.         }
  283.         break;
  284.       }
  285.  
  286.    }
  287. }
  288.  
  289.  
  290.  
  291. static void read_depth_pixels( GLint x, GLint y,
  292.                    GLsizei width, GLsizei height,
  293.                    GLenum type, GLvoid *pixels )
  294. {
  295.    GLint i, j;
  296.    GLuint a, s, k, l, start;
  297.    GLboolean bias_or_scale;
  298.  
  299.    /* Error checking */
  300.    if (!CC.DepthBuffer) {
  301.       gl_error( GL_INVALID_OPERATION, "glReadPixels" );
  302.       return;
  303.    }
  304.  
  305.    bias_or_scale = CC.Pixel.DepthBias!=0.0 || CC.Pixel.DepthScale!=1.0;
  306.  
  307.    /* Size of each component */
  308.    switch (type) {
  309.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  310.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  311.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  312.       case GL_SHORT:        s = sizeof(GLshort);    break;
  313.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  314.       case GL_INT:        s = sizeof(GLint);    break;
  315.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  316.       default:
  317.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  318.      return;
  319.    }
  320.  
  321.    /* Compute packing parameters */
  322.    a = CC.PackAlignment;
  323.    if (CC.PackRowLength>0) {
  324.       l = CC.PackRowLength;
  325.    }
  326.    else {
  327.       l = width;
  328.    }
  329.    /* k = offset between rows in components */
  330.    if (s>=a) {
  331.       k = l;
  332.    }
  333.    else {
  334.       k = a/s * CEILING( s*l, a );
  335.    }
  336.  
  337.    /* offset to first component returned */
  338.    start = CC.PackSkipRows * k + CC.PackSkipPixels;
  339.  
  340.    if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
  341.        && !bias_or_scale && !CC.PackSwapBytes) {
  342.       /* Special case: directly read 16-bit unsigned depth values. */
  343.       for (j=0;j<height;j++,y++) {
  344.          GLushort *dst = (GLushort *) pixels + start + j * k;
  345.          (*DD.read_depth_span_int)( width, x, y, (GLdepth *) dst );
  346.       }
  347.    }
  348.    else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
  349.             && !bias_or_scale && !CC.PackSwapBytes) {
  350.       /* Special case: directly read 32-bit unsigned depth values. */
  351.       /* Compute shift value to scale depth values up to 32-bit uints. */
  352.       GLuint shift = 0;
  353.       GLuint max = MAX_DEPTH;
  354.       while ((max&0x80000000)==0) {
  355.          max = max << 1;
  356.          shift++;
  357.       }
  358.       for (j=0;j<height;j++,y++) {
  359.          GLuint *dst = (GLuint *) pixels + start + j * k;
  360.          (*DD.read_depth_span_int)( width, x, y, (GLdepth *) dst );
  361.          for (i=0;i<width;i++) {
  362.             dst[i] = dst[i] << shift;
  363.          }
  364.       }
  365.    }
  366.    else {
  367.       /* General case (slow) */
  368.       for (j=0;j<height;j++,y++) {
  369.          GLfloat depth[MAX_WIDTH];
  370.  
  371.          (*DD.read_depth_span_float)( width, x, y, depth );
  372.  
  373.          if (bias_or_scale) {
  374.             for (i=0;i<width;i++) {
  375.                GLfloat d;
  376.                d = depth[i] * CC.Pixel.DepthScale + CC.Pixel.DepthBias;
  377.                depth[i] = CLAMP( d, 0.0, 1.0 );
  378.             }
  379.          }
  380.  
  381.          switch (type) {
  382.             case GL_UNSIGNED_BYTE:
  383.                {
  384.                   GLubyte *dst = (GLubyte *) pixels + start + j * k;
  385.                   for (i=0;i<width;i++) {
  386.                      *dst++ = FLOAT_TO_UBYTE( depth[i] );
  387.                   }
  388.                }
  389.                break;
  390.             case GL_BYTE:
  391.                {
  392.                   GLbyte *dst = (GLbyte *) pixels + start + j * k;
  393.                   for (i=0;i<width;i++) {
  394.                      *dst++ = FLOAT_TO_BYTE( depth[i] );
  395.                   }
  396.                }
  397.                break;
  398.             case GL_UNSIGNED_SHORT:
  399.                {
  400.                   GLushort *dst = (GLushort *) pixels + start + j * k;
  401.                   for (i=0;i<width;i++) {
  402.                      *dst++ = FLOAT_TO_USHORT( depth[i] );
  403.                   }
  404.                   if (CC.PackSwapBytes) {
  405.                      swap2( (GLushort *) pixels + start + j * k, width );
  406.                   }
  407.                }
  408.                break;
  409.             case GL_SHORT:
  410.                {
  411.                   GLshort *dst = (GLshort *) pixels + start + j * k;
  412.                   for (i=0;i<width;i++) {
  413.                      *dst++ = FLOAT_TO_SHORT( depth[i] );
  414.                   }
  415.                   if (CC.PackSwapBytes) {
  416.                      swap2( (GLushort *) pixels + start + j * k, width );
  417.                   }
  418.                }
  419.                break;
  420.             case GL_UNSIGNED_INT:
  421.                {
  422.                   GLuint *dst = (GLuint *) pixels + start + j * k;
  423.                   for (i=0;i<width;i++) {
  424.                      *dst++ = FLOAT_TO_UINT( depth[i] );
  425.                   }
  426.                   if (CC.PackSwapBytes) {
  427.                      swap4( (GLuint *) pixels + start + j * k, width );
  428.                   }
  429.                }
  430.                break;
  431.             case GL_INT:
  432.                {
  433.                   GLint *dst = (GLint *) pixels + start + j * k;
  434.                   for (i=0;i<width;i++) {
  435.                      *dst++ = FLOAT_TO_INT( depth[i] );
  436.                   }
  437.                   if (CC.PackSwapBytes) {
  438.                      swap4( (GLuint *) pixels + start + j * k, width );
  439.                   }
  440.                }
  441.                break;
  442.             case GL_FLOAT:
  443.                {
  444.                   GLfloat *dst = (GLfloat *) pixels + start + j * k;
  445.                   for (i=0;i<width;i++) {
  446.                      *dst++ = depth[i];
  447.                   }
  448.                   if (CC.PackSwapBytes) {
  449.                      swap4( (GLuint *) pixels + start + j * k, width );
  450.                   }
  451.                }
  452.                break;
  453.          }
  454.       }
  455.    }
  456. }
  457.  
  458.  
  459.  
  460.  
  461. static void read_stencil_pixels( GLint x, GLint y,
  462.                  GLsizei width, GLsizei height,
  463.                  GLenum type, GLvoid *pixels )
  464. {
  465.    GLint i, j;
  466.    GLuint a, s, k, l, start;
  467.    GLboolean shift_or_offset;
  468.  
  469.    if (!CC.StencilBuffer) {
  470.       gl_error( GL_INVALID_OPERATION, "glReadPixels" );
  471.       return;
  472.    }
  473.  
  474.    shift_or_offset = CC.Pixel.IndexShift!=0 || CC.Pixel.IndexOffset!=0;
  475.  
  476.    /* Size of each component */
  477.    switch (type) {
  478.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  479.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  480.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  481.       case GL_SHORT:        s = sizeof(GLshort);    break;
  482.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  483.       case GL_INT:        s = sizeof(GLint);    break;
  484.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  485.       default:
  486.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  487.      return;
  488.    }
  489.  
  490.    /* Compute packing parameters */
  491.    a = CC.PackAlignment;
  492.    if (CC.PackRowLength>0) {
  493.       l = CC.PackRowLength;
  494.    }
  495.    else {
  496.       l = width;
  497.    }
  498.    /* k = offset between rows in components */
  499.    if (s>=a) {
  500.       k = l;
  501.    }
  502.    else {
  503.       k = a/s * CEILING( s*l, a );
  504.    }
  505.  
  506.    /* offset to first component returned */
  507.    start = CC.PackSkipRows * k + CC.PackSkipPixels;
  508.  
  509.    /* process image row by row */
  510.    for (j=0;j<height;j++,y++) {
  511.       GLubyte stencil[MAX_WIDTH];
  512.  
  513.       gl_read_stencil_span( width, x, y, stencil );
  514.  
  515.       if (shift_or_offset) {
  516.      GLuint s;
  517.      if (CC.Pixel.IndexShift<0) {
  518.         /* right shift */
  519.         s = -CC.Pixel.IndexShift;
  520.         for (i=0;i<width;i++) {
  521.            stencil[i] = (stencil[i] >> s) + CC.Pixel.IndexOffset;
  522.         }
  523.      }
  524.      else {
  525.         /* left shift */
  526.         s = CC.Pixel.IndexShift;
  527.         for (i=0;i<width;i++) {
  528.            stencil[i] = (stencil[i] << s) + CC.Pixel.IndexOffset;
  529.         }
  530.      }
  531.       }
  532.  
  533.       if (CC.Pixel.MapStencilFlag) {
  534.      for (i=0;i<width;i++) {
  535.         stencil[i] = CC.Pixel.MapStoS[ stencil[i] ];
  536.      }
  537.       }
  538.  
  539.       switch (type) {
  540.      case GL_UNSIGNED_BYTE:
  541.         {
  542.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  543.            MEMCPY( dst, stencil, width );
  544.         }
  545.         break;
  546.      case GL_BYTE:
  547.         {
  548.            GLbyte *dst = (GLbyte  *) pixels + start + j * k;
  549.            MEMCPY( dst, stencil, width );
  550.         }
  551.         break;
  552.      case GL_UNSIGNED_SHORT:
  553.         {
  554.            GLushort *dst = (GLushort *) pixels + start + j * k;
  555.            for (i=0;i<width;i++) {
  556.           *dst++ = (GLushort) stencil[i];
  557.            }
  558.            if (CC.PackSwapBytes) {
  559.           swap2( (GLushort *) pixels + start +j * k, width );
  560.            }
  561.         }
  562.         break;
  563.      case GL_SHORT:
  564.         {
  565.            GLshort *dst = (GLshort *) pixels + start + j * k;
  566.            for (i=0;i<width;i++) {
  567.           *dst++ = (GLshort) stencil[i];
  568.            }
  569.            if (CC.PackSwapBytes) {
  570.           swap2( (GLushort *) pixels + start +j * k, width );
  571.            }
  572.         }
  573.         break;
  574.      case GL_UNSIGNED_INT:
  575.         {
  576.            GLuint *dst = (GLuint *) pixels + start + j * k;
  577.            for (i=0;i<width;i++) {
  578.           *dst++ = (GLuint) stencil[i];
  579.            }
  580.            if (CC.PackSwapBytes) {
  581.           swap4( (GLuint *) pixels + start +j * k, width );
  582.            }
  583.         }
  584.         break;
  585.      case GL_INT:
  586.         {
  587.            GLint *dst = (GLint *) pixels + start + j * k;
  588.            for (i=0;i<width;i++) {
  589.           *dst++ = (GLint) stencil[i];
  590.            }
  591.            if (CC.PackSwapBytes) {
  592.           swap4( (GLuint *) pixels + start +j * k, width );
  593.            }
  594.         }
  595.         break;
  596.      case GL_FLOAT:
  597.         {
  598.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  599.            for (i=0;i<width;i++) {
  600.           *dst++ = (GLfloat) stencil[i];
  601.            }
  602.            if (CC.PackSwapBytes) {
  603.           swap4( (GLuint *) pixels + start +j * k, width );
  604.            }
  605.         }
  606.         break;
  607.       }
  608.  
  609.    }
  610. }
  611.  
  612.  
  613.  
  614. /*
  615.  * Test if scaling or biasing of colors is needed.
  616.  */
  617. static GLboolean scale_or_bias_rgba( void )
  618. {
  619.    if (CC.Pixel.RedScale!=1.0F   || CC.Pixel.RedBias!=0.0F ||
  620.        CC.Pixel.GreenScale!=1.0F || CC.Pixel.GreenBias!=0.0F ||
  621.        CC.Pixel.BlueScale!=1.0F  || CC.Pixel.BlueBias!=0.0F ||
  622.        CC.Pixel.AlphaScale!=1.0F || CC.Pixel.AlphaBias!=0.0F) {
  623.       return GL_TRUE;
  624.    }
  625.    else {
  626.       return GL_FALSE;
  627.    }
  628. }
  629.  
  630.  
  631.  
  632. /*
  633.  * Apply scale and bias factors to an array of RGBA pixels.
  634.  */
  635. static void scale_and_bias_rgba( GLint n,
  636.                  GLfloat red[], GLfloat green[],
  637.                  GLfloat blue[], GLfloat alpha[] )
  638. {
  639.    register GLint i;
  640.    register GLfloat r, g, b, a;
  641.  
  642.    for (i=0;i<n;i++) {
  643.       r = red[i]   * CC.Pixel.RedScale   + CC.Pixel.RedBias;
  644.       g = green[i] * CC.Pixel.GreenScale + CC.Pixel.GreenBias;
  645.       b = blue[i]  * CC.Pixel.BlueScale  + CC.Pixel.BlueBias;
  646.       a = alpha[i] * CC.Pixel.AlphaScale + CC.Pixel.AlphaBias;
  647.       red[i]   = CLAMP( r, 0.0F, 1.0F );
  648.       green[i] = CLAMP( g, 0.0F, 1.0F );
  649.       blue[i]  = CLAMP( b, 0.0F, 1.0F );
  650.       alpha[i] = CLAMP( a, 0.0F, 1.0F );
  651.    }
  652. }
  653.  
  654.  
  655.  
  656. /*
  657.  * Apply pixel mapping to an array of RGBA pixels.
  658.  */
  659. static void map_rgba( GLint n,
  660.               GLfloat red[], GLfloat green[],
  661.               GLfloat blue[], GLfloat alpha[] )
  662. {
  663.    GLfloat rscale = CC.Pixel.MapRtoRsize-1;
  664.    GLfloat gscale = CC.Pixel.MapGtoGsize-1;
  665.    GLfloat bscale = CC.Pixel.MapBtoBsize-1;
  666.    GLfloat ascale = CC.Pixel.MapAtoAsize-1;
  667.    GLint i;
  668.  
  669.    for (i=0;i<n;i++) {
  670.       red[i]   = CC.Pixel.MapRtoR[ (GLint) (red[i]   * rscale) ];
  671.       green[i] = CC.Pixel.MapGtoG[ (GLint) (green[i] * gscale) ];
  672.       blue[i]  = CC.Pixel.MapBtoB[ (GLint) (blue[i]  * bscale) ];
  673.       alpha[i] = CC.Pixel.MapAtoA[ (GLint) (alpha[i] * ascale) ];
  674.    }
  675. }
  676.  
  677.  
  678.  
  679.  
  680. /*
  681.  * Read R, G, B, A, RGB, L, or LA pixels.
  682.  */
  683. static void read_color_pixels( GLint x, GLint y,
  684.                    GLsizei width, GLsizei height,
  685.                    GLenum format, GLenum type, GLvoid *pixels )
  686. {
  687.    GLint i, j, n, a, s, l, k;
  688.    GLboolean scale_or_bias;
  689.    GLfloat red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
  690.    GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
  691.    GLuint start;
  692.  
  693.    scale_or_bias = scale_or_bias_rgba();
  694.  
  695.    /* Determine how many / which components to return */
  696.    r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
  697.    switch (format) {
  698.       case GL_RED:                r_flag = GL_TRUE;  n = 1;  break;
  699.       case GL_GREEN:                g_flag = GL_TRUE;  n = 1;  break;
  700.       case GL_BLUE:                b_flag = GL_TRUE;  n = 1;  break;
  701.       case GL_ALPHA:                a_flag = GL_TRUE;  n = 1;  break;
  702.       case GL_LUMINANCE:            l_flag = GL_TRUE;  n = 1;  break;
  703.       case GL_LUMINANCE_ALPHA:           l_flag = a_flag = GL_TRUE;  n = 2;  break;
  704.       case GL_RGB:          r_flag = g_flag = b_flag = GL_TRUE;  n = 3;  break;
  705.       case GL_RGBA:  r_flag = g_flag = b_flag = a_flag = GL_TRUE;  n = 4;  break;
  706.       default:
  707.      gl_error( GL_INVALID_ENUM, "glReadPixels(format)" );
  708.    }
  709.  
  710.    /* Size of each component */
  711.    switch (type) {
  712.       case GL_UNSIGNED_BYTE:    s = sizeof(GLubyte);    break;
  713.       case GL_BYTE:        s = sizeof(GLbyte);    break;
  714.       case GL_UNSIGNED_SHORT:    s = sizeof(GLushort);    break;
  715.       case GL_SHORT:        s = sizeof(GLshort);    break;
  716.       case GL_UNSIGNED_INT:    s = sizeof(GLuint);    break;
  717.       case GL_INT:        s = sizeof(GLint);    break;
  718.       case GL_FLOAT:        s = sizeof(GLfloat);    break;
  719.       default:
  720.      gl_error( GL_INVALID_ENUM, "glReadPixels(type)" );
  721.      return;
  722.    }
  723.  
  724.    /* Compute packing parameters */
  725.    a = CC.PackAlignment;
  726.    if (CC.PackRowLength>0) {
  727.       l = CC.PackRowLength;
  728.    }
  729.    else {
  730.       l = width;
  731.    }
  732.    /* k = offset between rows in components */
  733.    if (s>=a) {
  734.       k = n * l;
  735.    }
  736.    else {
  737.       k = a/s * CEILING( s*n*l, a );
  738.    }
  739.  
  740.    /* offset to first component returned */
  741.    start = CC.PackSkipRows * k + CC.PackSkipPixels * n;
  742.  
  743.    /* process image row by row */
  744.    for (j=0;j<height;j++,y++) {
  745.  
  746.       /*
  747.        * Read the pixels from frame buffer
  748.        */
  749.       if (CC.RGBAflag) {
  750.      GLubyte r[MAX_WIDTH], g[MAX_WIDTH], b[MAX_WIDTH], a[MAX_WIDTH];
  751.      GLfloat rscale = 1.0F / CC.RedScale;
  752.      GLfloat gscale = 1.0F / CC.GreenScale;
  753.      GLfloat bscale = 1.0F / CC.BlueScale;
  754.      GLfloat ascale = 1.0F / CC.AlphaScale;
  755.  
  756.      /* read colors and convert to floats */
  757.      (*DD.read_color_span)( width, x, y, r, g, b, a );
  758.          if (CC.RasterMask & ALPHABUF_BIT) {
  759.             gl_read_alpha_span( width, x, y, a );
  760.          }
  761.      for (i=0;i<width;i++) {
  762.         red[i]   = r[i] * rscale;
  763.         green[i] = g[i] * gscale;
  764.         blue[i]  = b[i] * bscale;
  765.         alpha[i] = a[i] * ascale;
  766.      }
  767.  
  768.      if (scale_or_bias) {
  769.         scale_and_bias_rgba( width, red, green, blue, alpha );
  770.      }
  771.      if (CC.Pixel.MapColorFlag) {
  772.         map_rgba( width, red, green, blue, alpha );
  773.      }
  774.       }
  775.       else {
  776.      /* convert CI values to RGBA */
  777.      GLuint index[MAX_WIDTH];
  778.      (*DD.read_index_span)( width, x, y, index );
  779.  
  780.      if (CC.Pixel.IndexShift!=0 || CC.Pixel.IndexOffset!=0) {
  781.         GLuint s;
  782.         if (CC.Pixel.IndexShift<0) {
  783.            /* right shift */
  784.            s = -CC.Pixel.IndexShift;
  785.            for (i=0;i<width;i++) {
  786.           index[i] = (index[i] >> s) + CC.Pixel.IndexOffset;
  787.            }
  788.         }
  789.         else {
  790.            /* left shift */
  791.            s = CC.Pixel.IndexShift;
  792.            for (i=0;i<width;i++) {
  793.           index[i] = (index[i] << s) + CC.Pixel.IndexOffset;
  794.            }
  795.         }
  796.      }
  797.  
  798.      for (i=0;i<width;i++) {
  799.         red[i]   = CC.Pixel.MapItoR[ index[i] ];
  800.         green[i] = CC.Pixel.MapItoG[ index[i] ];
  801.         blue[i]  = CC.Pixel.MapItoB[ index[i] ];
  802.         alpha[i] = CC.Pixel.MapItoA[ index[i] ];
  803.      }
  804.       }
  805.  
  806.       /*
  807.        * Pack/transfer/store the pixels
  808.        */
  809.  
  810.       switch (type) {
  811.      case GL_UNSIGNED_BYTE:
  812.         {
  813.            GLubyte *dst = (GLubyte *) pixels + start + j * k;
  814.            for (i=0;i<width;i++) {
  815.           if (r_flag)  *dst++ = FLOAT_TO_UBYTE( red[i] );
  816.           if (g_flag)  *dst++ = FLOAT_TO_UBYTE( green[i] );
  817.           if (b_flag)  *dst++ = FLOAT_TO_UBYTE( blue[i] );
  818.           if (l_flag)  *dst++ = FLOAT_TO_UBYTE(red[i]+green[i]+blue[i]);
  819.           if (a_flag)  *dst++ = FLOAT_TO_UBYTE( alpha[i] );
  820.            }
  821.         }
  822.         break;
  823.      case GL_BYTE:
  824.         {
  825.            GLbyte *dst = (GLbyte *) pixels + start + j * k;
  826.            for (i=0;i<width;i++) {
  827.           if (r_flag)  *dst++ = FLOAT_TO_BYTE( red[i] );
  828.           if (g_flag)  *dst++ = FLOAT_TO_BYTE( green[i] );
  829.           if (b_flag)  *dst++ = FLOAT_TO_BYTE( blue[i] );
  830.           if (l_flag)  *dst++ = FLOAT_TO_BYTE(red[i]+green[i]+blue[i]);
  831.           if (a_flag)  *dst++ = FLOAT_TO_BYTE( alpha[i] );
  832.            }
  833.         }
  834.         break;
  835.      case GL_UNSIGNED_SHORT:
  836.         {
  837.            GLushort *dst = (GLushort *) pixels + start + j * k;
  838.            for (i=0;i<width;i++) {
  839.           if (r_flag)  *dst++ = FLOAT_TO_USHORT( red[i] );
  840.           if (g_flag)  *dst++ = FLOAT_TO_USHORT( green[i] );
  841.           if (b_flag)  *dst++ = FLOAT_TO_USHORT( blue[i] );
  842.           if (l_flag)  *dst++ = FLOAT_TO_USHORT(red[i]+green[i]+blue[i]);
  843.           if (a_flag)  *dst++ = FLOAT_TO_USHORT( alpha[i] );
  844.            }
  845.         }
  846.         if (CC.PackSwapBytes) {
  847.            swap2( (GLushort *) pixels + start + j * k, width*n );
  848.         }
  849.         break;
  850.      case GL_SHORT:
  851.         {
  852.            GLshort *dst = (GLshort *) pixels + start + j * k;
  853.            for (i=0;i<width;i++) {
  854.           if (r_flag)  *dst++ = FLOAT_TO_SHORT( red[i] );
  855.           if (g_flag)  *dst++ = FLOAT_TO_SHORT( green[i] );
  856.           if (b_flag)  *dst++ = FLOAT_TO_SHORT( blue[i] );
  857.           if (l_flag)  *dst++ = FLOAT_TO_SHORT(red[i]+green[i]+blue[i]);
  858.           if (a_flag)  *dst++ = FLOAT_TO_SHORT( alpha[i] );
  859.            }
  860.            if (CC.PackSwapBytes) {
  861.           swap2( (GLushort *) pixels + start + j * k, width*n );
  862.            }
  863.         }
  864.         break;
  865.      case GL_UNSIGNED_INT:
  866.         {
  867.            GLuint *dst = (GLuint *) pixels + start + j * k;
  868.            for (i=0;i<width;i++) {
  869.           if (r_flag)  *dst++ = FLOAT_TO_UINT( red[i] );
  870.           if (g_flag)  *dst++ = FLOAT_TO_UINT( green[i] );
  871.           if (b_flag)  *dst++ = FLOAT_TO_UINT( blue[i] );
  872.           if (l_flag)  *dst++ = FLOAT_TO_UINT(red[i]+green[i]+blue[i]);
  873.           if (a_flag)  *dst++ = FLOAT_TO_UINT( alpha[i] );
  874.            }
  875.            if (CC.PackSwapBytes) {
  876.           swap4( (GLuint *) pixels + start + j * k, width*n );
  877.            }
  878.         }
  879.         break;
  880.      case GL_INT:
  881.         {
  882.            GLint *dst = (GLint *) pixels + start + j * k;
  883.            for (i=0;i<width;i++) {
  884.           if (r_flag)  *dst++ = FLOAT_TO_INT( red[i] );
  885.           if (g_flag)  *dst++ = FLOAT_TO_INT( green[i] );
  886.           if (b_flag)  *dst++ = FLOAT_TO_INT( blue[i] );
  887.           if (l_flag)  *dst++ = FLOAT_TO_INT(red[i]+green[i]+blue[i]);
  888.           if (a_flag)  *dst++ = FLOAT_TO_INT( alpha[i] );
  889.            }
  890.            if (CC.PackSwapBytes) {
  891.           swap4( (GLuint *) pixels + start + j * k, width*n );
  892.            }
  893.         }
  894.         break;
  895.      case GL_FLOAT:
  896.         {
  897.            GLfloat *dst = (GLfloat *) pixels + start + j * k;
  898.            for (i=0;i<width;i++) {
  899.           if (r_flag)  *dst++ = red[i];
  900.           if (g_flag)  *dst++ = green[i];
  901.           if (b_flag)  *dst++ = blue[i];
  902.           if (l_flag)  *dst++ = red[i]+green[i]+blue[i];
  903.           if (a_flag)  *dst++ = alpha[i];
  904.            }
  905.            if (CC.PackSwapBytes) {
  906.           swap4( (GLuint *) pixels + start + j * k, width*n );
  907.            }
  908.         }
  909.         break;
  910.       }
  911.  
  912.    }
  913. }
  914.  
  915.  
  916.  
  917. void glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
  918.            GLenum format, GLenum type, GLvoid *pixels )
  919. {
  920.    (void) (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  921.  
  922.    switch (format) {
  923.       case GL_COLOR_INDEX:
  924.          read_index_pixels( x, y, width, height, type, pixels );
  925.      break;
  926.       case GL_STENCIL_INDEX:
  927.      read_stencil_pixels( x, y, width, height, type, pixels );
  928.          break;
  929.       case GL_DEPTH_COMPONENT:
  930.      read_depth_pixels( x, y, width, height, type, pixels );
  931.      break;
  932.       case GL_RED:
  933.       case GL_GREEN:
  934.       case GL_BLUE:
  935.       case GL_ALPHA:
  936.       case GL_RGB:
  937.       case GL_LUMINANCE:
  938.       case GL_LUMINANCE_ALPHA:
  939.       case GL_RGBA:
  940.      read_color_pixels( x, y, width, height, format, type, pixels );
  941.      break;
  942.       default:
  943.      gl_error( GL_INVALID_ENUM, "glReadPixels(format)" );
  944.    }
  945.  
  946.    (void) (*DD.set_buffer)( CC.Color.DrawBuffer );
  947. }
  948.