pack.c revision 01e04c3f
13464ebd5Sriastradh/*
23464ebd5Sriastradh * Mesa 3-D graphics library
33464ebd5Sriastradh *
43464ebd5Sriastradh * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
53464ebd5Sriastradh * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
63464ebd5Sriastradh *
73464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
83464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"),
93464ebd5Sriastradh * to deal in the Software without restriction, including without limitation
103464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
113464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the
123464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions:
133464ebd5Sriastradh *
143464ebd5Sriastradh * The above copyright notice and this permission notice shall be included
153464ebd5Sriastradh * in all copies or substantial portions of the Software.
163464ebd5Sriastradh *
173464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
183464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
193464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
203464ebd5Sriastradh * THEA AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
213464ebd5Sriastradh * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
223464ebd5Sriastradh * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
233464ebd5Sriastradh */
243464ebd5Sriastradh
253464ebd5Sriastradh
263464ebd5Sriastradh/**
273464ebd5Sriastradh * \file pack.c
283464ebd5Sriastradh * Image and pixel span packing and unpacking.
293464ebd5Sriastradh */
303464ebd5Sriastradh
313464ebd5Sriastradh
32af69d88dSmrg/*
33af69d88dSmrg * XXX: MSVC takes forever to compile this module for x86_64 unless we disable
34af69d88dSmrg * this global optimization.
35af69d88dSmrg *
36af69d88dSmrg * See also:
37af69d88dSmrg * - http://msdn.microsoft.com/en-us/library/1yk3ydd7.aspx
38af69d88dSmrg * - http://msdn.microsoft.com/en-us/library/chh3fb0k.aspx
39af69d88dSmrg */
40af69d88dSmrg#if defined(_MSC_VER) && defined(_M_X64)
41af69d88dSmrg#  pragma optimize( "g", off )
42af69d88dSmrg#endif
43af69d88dSmrg
44af69d88dSmrg
4501e04c3fSmrg#include "errors.h"
463464ebd5Sriastradh#include "glheader.h"
473464ebd5Sriastradh#include "enums.h"
483464ebd5Sriastradh#include "image.h"
493464ebd5Sriastradh#include "imports.h"
50af69d88dSmrg#include "macros.h"
513464ebd5Sriastradh#include "mtypes.h"
523464ebd5Sriastradh#include "pack.h"
533464ebd5Sriastradh#include "pixeltransfer.h"
543464ebd5Sriastradh#include "imports.h"
55af69d88dSmrg#include "glformats.h"
5601e04c3fSmrg#include "format_utils.h"
5701e04c3fSmrg#include "format_pack.h"
583464ebd5Sriastradh
593464ebd5Sriastradh
603464ebd5Sriastradh/**
613464ebd5Sriastradh * Flip the 8 bits in each byte of the given array.
623464ebd5Sriastradh *
633464ebd5Sriastradh * \param p array.
643464ebd5Sriastradh * \param n number of bytes.
653464ebd5Sriastradh *
663464ebd5Sriastradh * \todo try this trick to flip bytes someday:
673464ebd5Sriastradh * \code
683464ebd5Sriastradh *  v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555);
693464ebd5Sriastradh *  v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333);
703464ebd5Sriastradh *  v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f);
713464ebd5Sriastradh * \endcode
723464ebd5Sriastradh */
733464ebd5Sriastradhstatic void
743464ebd5Sriastradhflip_bytes( GLubyte *p, GLuint n )
753464ebd5Sriastradh{
763464ebd5Sriastradh   GLuint i, a, b;
773464ebd5Sriastradh   for (i = 0; i < n; i++) {
783464ebd5Sriastradh      b = (GLuint) p[i];        /* words are often faster than bytes */
793464ebd5Sriastradh      a = ((b & 0x01) << 7) |
803464ebd5Sriastradh	  ((b & 0x02) << 5) |
813464ebd5Sriastradh	  ((b & 0x04) << 3) |
823464ebd5Sriastradh	  ((b & 0x08) << 1) |
833464ebd5Sriastradh	  ((b & 0x10) >> 1) |
843464ebd5Sriastradh	  ((b & 0x20) >> 3) |
853464ebd5Sriastradh	  ((b & 0x40) >> 5) |
863464ebd5Sriastradh	  ((b & 0x80) >> 7);
873464ebd5Sriastradh      p[i] = (GLubyte) a;
883464ebd5Sriastradh   }
893464ebd5Sriastradh}
903464ebd5Sriastradh
913464ebd5Sriastradh
923464ebd5Sriastradh
933464ebd5Sriastradh/*
943464ebd5Sriastradh * Unpack a 32x32 pixel polygon stipple from user memory using the
953464ebd5Sriastradh * current pixel unpack settings.
963464ebd5Sriastradh */
973464ebd5Sriastradhvoid
983464ebd5Sriastradh_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32],
993464ebd5Sriastradh                              const struct gl_pixelstore_attrib *unpacking )
1003464ebd5Sriastradh{
10101e04c3fSmrg   GLubyte *ptrn = (GLubyte *) _mesa_unpack_image(2, 32, 32, 1, GL_COLOR_INDEX,
10201e04c3fSmrg                                                  GL_BITMAP, pattern, unpacking);
1033464ebd5Sriastradh   if (ptrn) {
1043464ebd5Sriastradh      /* Convert pattern from GLubytes to GLuints and handle big/little
1053464ebd5Sriastradh       * endian differences
1063464ebd5Sriastradh       */
1073464ebd5Sriastradh      GLubyte *p = ptrn;
1083464ebd5Sriastradh      GLint i;
1093464ebd5Sriastradh      for (i = 0; i < 32; i++) {
1103464ebd5Sriastradh         dest[i] = (p[0] << 24)
1113464ebd5Sriastradh                 | (p[1] << 16)
1123464ebd5Sriastradh                 | (p[2] <<  8)
1133464ebd5Sriastradh                 | (p[3]      );
1143464ebd5Sriastradh         p += 4;
1153464ebd5Sriastradh      }
1163464ebd5Sriastradh      free(ptrn);
1173464ebd5Sriastradh   }
1183464ebd5Sriastradh}
1193464ebd5Sriastradh
1203464ebd5Sriastradh
1213464ebd5Sriastradh/*
1223464ebd5Sriastradh * Pack polygon stipple into user memory given current pixel packing
1233464ebd5Sriastradh * settings.
1243464ebd5Sriastradh */
1253464ebd5Sriastradhvoid
1263464ebd5Sriastradh_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest,
1273464ebd5Sriastradh                            const struct gl_pixelstore_attrib *packing )
1283464ebd5Sriastradh{
1293464ebd5Sriastradh   /* Convert pattern from GLuints to GLubytes to handle big/little
1303464ebd5Sriastradh    * endian differences.
1313464ebd5Sriastradh    */
1323464ebd5Sriastradh   GLubyte ptrn[32*4];
1333464ebd5Sriastradh   GLint i;
1343464ebd5Sriastradh   for (i = 0; i < 32; i++) {
1353464ebd5Sriastradh      ptrn[i * 4 + 0] = (GLubyte) ((pattern[i] >> 24) & 0xff);
1363464ebd5Sriastradh      ptrn[i * 4 + 1] = (GLubyte) ((pattern[i] >> 16) & 0xff);
1373464ebd5Sriastradh      ptrn[i * 4 + 2] = (GLubyte) ((pattern[i] >> 8 ) & 0xff);
1383464ebd5Sriastradh      ptrn[i * 4 + 3] = (GLubyte) ((pattern[i]      ) & 0xff);
1393464ebd5Sriastradh   }
1403464ebd5Sriastradh
1413464ebd5Sriastradh   _mesa_pack_bitmap(32, 32, ptrn, dest, packing);
1423464ebd5Sriastradh}
1433464ebd5Sriastradh
1443464ebd5Sriastradh
1453464ebd5Sriastradh/*
1463464ebd5Sriastradh * Pack bitmap data.
1473464ebd5Sriastradh */
1483464ebd5Sriastradhvoid
1493464ebd5Sriastradh_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
1503464ebd5Sriastradh                   GLubyte *dest, const struct gl_pixelstore_attrib *packing )
1513464ebd5Sriastradh{
1523464ebd5Sriastradh   GLint row, width_in_bytes;
1533464ebd5Sriastradh   const GLubyte *src;
1543464ebd5Sriastradh
1553464ebd5Sriastradh   if (!source)
1563464ebd5Sriastradh      return;
1573464ebd5Sriastradh
15801e04c3fSmrg   width_in_bytes = DIV_ROUND_UP( width, 8 );
1593464ebd5Sriastradh   src = source;
1603464ebd5Sriastradh   for (row = 0; row < height; row++) {
1613464ebd5Sriastradh      GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest,
1623464ebd5Sriastradh                       width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
1633464ebd5Sriastradh      if (!dst)
1643464ebd5Sriastradh         return;
1653464ebd5Sriastradh
1663464ebd5Sriastradh      if ((packing->SkipPixels & 7) == 0) {
1673464ebd5Sriastradh         memcpy( dst, src, width_in_bytes );
1683464ebd5Sriastradh         if (packing->LsbFirst) {
1693464ebd5Sriastradh            flip_bytes( dst, width_in_bytes );
1703464ebd5Sriastradh         }
1713464ebd5Sriastradh      }
1723464ebd5Sriastradh      else {
1733464ebd5Sriastradh         /* handling SkipPixels is a bit tricky (no pun intended!) */
1743464ebd5Sriastradh         GLint i;
1753464ebd5Sriastradh         if (packing->LsbFirst) {
1763464ebd5Sriastradh            GLubyte srcMask = 128;
1773464ebd5Sriastradh            GLubyte dstMask = 1 << (packing->SkipPixels & 0x7);
1783464ebd5Sriastradh            const GLubyte *s = src;
1793464ebd5Sriastradh            GLubyte *d = dst;
1803464ebd5Sriastradh            *d = 0;
1813464ebd5Sriastradh            for (i = 0; i < width; i++) {
1823464ebd5Sriastradh               if (*s & srcMask) {
1833464ebd5Sriastradh                  *d |= dstMask;
1843464ebd5Sriastradh               }
1853464ebd5Sriastradh               if (srcMask == 1) {
1863464ebd5Sriastradh                  srcMask = 128;
1873464ebd5Sriastradh                  s++;
1883464ebd5Sriastradh               }
1893464ebd5Sriastradh               else {
1903464ebd5Sriastradh                  srcMask = srcMask >> 1;
1913464ebd5Sriastradh               }
1923464ebd5Sriastradh               if (dstMask == 128) {
1933464ebd5Sriastradh                  dstMask = 1;
1943464ebd5Sriastradh                  d++;
1953464ebd5Sriastradh                  *d = 0;
1963464ebd5Sriastradh               }
1973464ebd5Sriastradh               else {
1983464ebd5Sriastradh                  dstMask = dstMask << 1;
1993464ebd5Sriastradh               }
2003464ebd5Sriastradh            }
2013464ebd5Sriastradh         }
2023464ebd5Sriastradh         else {
2033464ebd5Sriastradh            GLubyte srcMask = 128;
2043464ebd5Sriastradh            GLubyte dstMask = 128 >> (packing->SkipPixels & 0x7);
2053464ebd5Sriastradh            const GLubyte *s = src;
2063464ebd5Sriastradh            GLubyte *d = dst;
2073464ebd5Sriastradh            *d = 0;
2083464ebd5Sriastradh            for (i = 0; i < width; i++) {
2093464ebd5Sriastradh               if (*s & srcMask) {
2103464ebd5Sriastradh                  *d |= dstMask;
2113464ebd5Sriastradh               }
2123464ebd5Sriastradh               if (srcMask == 1) {
2133464ebd5Sriastradh                  srcMask = 128;
2143464ebd5Sriastradh                  s++;
2153464ebd5Sriastradh               }
2163464ebd5Sriastradh               else {
2173464ebd5Sriastradh                  srcMask = srcMask >> 1;
2183464ebd5Sriastradh               }
2193464ebd5Sriastradh               if (dstMask == 1) {
2203464ebd5Sriastradh                  dstMask = 128;
2213464ebd5Sriastradh                  d++;
2223464ebd5Sriastradh                  *d = 0;
2233464ebd5Sriastradh               }
2243464ebd5Sriastradh               else {
2253464ebd5Sriastradh                  dstMask = dstMask >> 1;
2263464ebd5Sriastradh               }
2273464ebd5Sriastradh            }
2283464ebd5Sriastradh         }
2293464ebd5Sriastradh      }
2303464ebd5Sriastradh      src += width_in_bytes;
2313464ebd5Sriastradh   }
2323464ebd5Sriastradh}
2333464ebd5Sriastradh
2343464ebd5Sriastradh
23501e04c3fSmrg#define SWAP2BYTE(VALUE)			\
23601e04c3fSmrg   {						\
23701e04c3fSmrg      GLubyte *bytes = (GLubyte *) &(VALUE);	\
23801e04c3fSmrg      GLubyte tmp = bytes[0];			\
23901e04c3fSmrg      bytes[0] = bytes[1];			\
24001e04c3fSmrg      bytes[1] = tmp;				\
2413464ebd5Sriastradh   }
2423464ebd5Sriastradh
24301e04c3fSmrg#define SWAP4BYTE(VALUE)			\
24401e04c3fSmrg   {						\
24501e04c3fSmrg      GLubyte *bytes = (GLubyte *) &(VALUE);	\
24601e04c3fSmrg      GLubyte tmp = bytes[0];			\
24701e04c3fSmrg      bytes[0] = bytes[3];			\
24801e04c3fSmrg      bytes[3] = tmp;				\
24901e04c3fSmrg      tmp = bytes[1];				\
25001e04c3fSmrg      bytes[1] = bytes[2];			\
25101e04c3fSmrg      bytes[2] = tmp;				\
2523464ebd5Sriastradh   }
253af69d88dSmrg
254af69d88dSmrg
255af69d88dSmrgstatic void
25601e04c3fSmrgextract_uint_indexes(GLuint n, GLuint indexes[],
25701e04c3fSmrg                     GLenum srcFormat, GLenum srcType, const GLvoid *src,
25801e04c3fSmrg                     const struct gl_pixelstore_attrib *unpack )
259af69d88dSmrg{
26001e04c3fSmrg   assert(srcFormat == GL_COLOR_INDEX || srcFormat == GL_STENCIL_INDEX);
261af69d88dSmrg
26201e04c3fSmrg   assert(srcType == GL_BITMAP ||
26301e04c3fSmrg          srcType == GL_UNSIGNED_BYTE ||
26401e04c3fSmrg          srcType == GL_BYTE ||
26501e04c3fSmrg          srcType == GL_UNSIGNED_SHORT ||
26601e04c3fSmrg          srcType == GL_SHORT ||
26701e04c3fSmrg          srcType == GL_UNSIGNED_INT ||
26801e04c3fSmrg          srcType == GL_INT ||
26901e04c3fSmrg          srcType == GL_UNSIGNED_INT_24_8_EXT ||
27001e04c3fSmrg          srcType == GL_HALF_FLOAT_ARB ||
27101e04c3fSmrg          srcType == GL_HALF_FLOAT_OES ||
27201e04c3fSmrg          srcType == GL_FLOAT ||
27301e04c3fSmrg          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
274af69d88dSmrg
27501e04c3fSmrg   switch (srcType) {
27601e04c3fSmrg      case GL_BITMAP:
27701e04c3fSmrg         {
27801e04c3fSmrg            GLubyte *ubsrc = (GLubyte *) src;
27901e04c3fSmrg            if (unpack->LsbFirst) {
28001e04c3fSmrg               GLubyte mask = 1 << (unpack->SkipPixels & 0x7);
28101e04c3fSmrg               GLuint i;
28201e04c3fSmrg               for (i = 0; i < n; i++) {
28301e04c3fSmrg                  indexes[i] = (*ubsrc & mask) ? 1 : 0;
28401e04c3fSmrg                  if (mask == 128) {
28501e04c3fSmrg                     mask = 1;
28601e04c3fSmrg                     ubsrc++;
28701e04c3fSmrg                  }
28801e04c3fSmrg                  else {
28901e04c3fSmrg                     mask = mask << 1;
29001e04c3fSmrg                  }
29101e04c3fSmrg               }
29201e04c3fSmrg            }
29301e04c3fSmrg            else {
29401e04c3fSmrg               GLubyte mask = 128 >> (unpack->SkipPixels & 0x7);
29501e04c3fSmrg               GLuint i;
29601e04c3fSmrg               for (i = 0; i < n; i++) {
29701e04c3fSmrg                  indexes[i] = (*ubsrc & mask) ? 1 : 0;
29801e04c3fSmrg                  if (mask == 1) {
29901e04c3fSmrg                     mask = 128;
30001e04c3fSmrg                     ubsrc++;
30101e04c3fSmrg                  }
30201e04c3fSmrg                  else {
30301e04c3fSmrg                     mask = mask >> 1;
30401e04c3fSmrg                  }
30501e04c3fSmrg               }
30601e04c3fSmrg            }
307af69d88dSmrg         }
30801e04c3fSmrg         break;
30901e04c3fSmrg      case GL_UNSIGNED_BYTE:
31001e04c3fSmrg         {
31101e04c3fSmrg            GLuint i;
31201e04c3fSmrg            const GLubyte *s = (const GLubyte *) src;
31301e04c3fSmrg            for (i = 0; i < n; i++)
31401e04c3fSmrg               indexes[i] = s[i];
315af69d88dSmrg         }
31601e04c3fSmrg         break;
31701e04c3fSmrg      case GL_BYTE:
31801e04c3fSmrg         {
31901e04c3fSmrg            GLuint i;
32001e04c3fSmrg            const GLbyte *s = (const GLbyte *) src;
32101e04c3fSmrg            for (i = 0; i < n; i++)
32201e04c3fSmrg               indexes[i] = s[i];
323af69d88dSmrg         }
32401e04c3fSmrg         break;
32501e04c3fSmrg      case GL_UNSIGNED_SHORT:
32601e04c3fSmrg         {
32701e04c3fSmrg            GLuint i;
32801e04c3fSmrg            const GLushort *s = (const GLushort *) src;
32901e04c3fSmrg            if (unpack->SwapBytes) {
33001e04c3fSmrg               for (i = 0; i < n; i++) {
33101e04c3fSmrg                  GLushort value = s[i];
33201e04c3fSmrg                  SWAP2BYTE(value);
33301e04c3fSmrg                  indexes[i] = value;
33401e04c3fSmrg               }
33501e04c3fSmrg            }
33601e04c3fSmrg            else {
33701e04c3fSmrg               for (i = 0; i < n; i++)
33801e04c3fSmrg                  indexes[i] = s[i];
33901e04c3fSmrg            }
340af69d88dSmrg         }
34101e04c3fSmrg         break;
34201e04c3fSmrg      case GL_SHORT:
34301e04c3fSmrg         {
34401e04c3fSmrg            GLuint i;
34501e04c3fSmrg            const GLshort *s = (const GLshort *) src;
34601e04c3fSmrg            if (unpack->SwapBytes) {
34701e04c3fSmrg               for (i = 0; i < n; i++) {
34801e04c3fSmrg                  GLshort value = s[i];
34901e04c3fSmrg                  SWAP2BYTE(value);
35001e04c3fSmrg                  indexes[i] = value;
35101e04c3fSmrg               }
35201e04c3fSmrg            }
35301e04c3fSmrg            else {
35401e04c3fSmrg               for (i = 0; i < n; i++)
35501e04c3fSmrg                  indexes[i] = s[i];
35601e04c3fSmrg            }
357af69d88dSmrg         }
35801e04c3fSmrg         break;
35901e04c3fSmrg      case GL_UNSIGNED_INT:
36001e04c3fSmrg         {
36101e04c3fSmrg            GLuint i;
36201e04c3fSmrg            const GLuint *s = (const GLuint *) src;
36301e04c3fSmrg            if (unpack->SwapBytes) {
3643464ebd5Sriastradh               for (i = 0; i < n; i++) {
36501e04c3fSmrg                  GLuint value = s[i];
36601e04c3fSmrg                  SWAP4BYTE(value);
36701e04c3fSmrg                  indexes[i] = value;
3683464ebd5Sriastradh               }
3693464ebd5Sriastradh            }
37001e04c3fSmrg            else {
37101e04c3fSmrg               for (i = 0; i < n; i++)
37201e04c3fSmrg                  indexes[i] = s[i];
3733464ebd5Sriastradh            }
3743464ebd5Sriastradh         }
37501e04c3fSmrg         break;
37601e04c3fSmrg      case GL_INT:
37701e04c3fSmrg         {
37801e04c3fSmrg            GLuint i;
37901e04c3fSmrg            const GLint *s = (const GLint *) src;
38001e04c3fSmrg            if (unpack->SwapBytes) {
38101e04c3fSmrg               for (i = 0; i < n; i++) {
38201e04c3fSmrg                  GLint value = s[i];
38301e04c3fSmrg                  SWAP4BYTE(value);
38401e04c3fSmrg                  indexes[i] = value;
38501e04c3fSmrg               }
38601e04c3fSmrg            }
38701e04c3fSmrg            else {
38801e04c3fSmrg               for (i = 0; i < n; i++)
38901e04c3fSmrg                  indexes[i] = s[i];
39001e04c3fSmrg            }
3913464ebd5Sriastradh         }
39201e04c3fSmrg         break;
39301e04c3fSmrg      case GL_FLOAT:
39401e04c3fSmrg         {
39501e04c3fSmrg            GLuint i;
39601e04c3fSmrg            const GLfloat *s = (const GLfloat *) src;
39701e04c3fSmrg            if (unpack->SwapBytes) {
39801e04c3fSmrg               for (i = 0; i < n; i++) {
39901e04c3fSmrg                  GLfloat value = s[i];
40001e04c3fSmrg                  SWAP4BYTE(value);
40101e04c3fSmrg                  indexes[i] = (GLuint) value;
40201e04c3fSmrg               }
40301e04c3fSmrg            }
40401e04c3fSmrg            else {
40501e04c3fSmrg               for (i = 0; i < n; i++)
40601e04c3fSmrg                  indexes[i] = (GLuint) s[i];
40701e04c3fSmrg            }
4083464ebd5Sriastradh         }
40901e04c3fSmrg         break;
41001e04c3fSmrg      case GL_HALF_FLOAT_ARB:
41101e04c3fSmrg      case GL_HALF_FLOAT_OES:
41201e04c3fSmrg         {
41301e04c3fSmrg            GLuint i;
41401e04c3fSmrg            const GLhalfARB *s = (const GLhalfARB *) src;
41501e04c3fSmrg            if (unpack->SwapBytes) {
41601e04c3fSmrg               for (i = 0; i < n; i++) {
41701e04c3fSmrg                  GLhalfARB value = s[i];
41801e04c3fSmrg                  SWAP2BYTE(value);
41901e04c3fSmrg                  indexes[i] = (GLuint) _mesa_half_to_float(value);
42001e04c3fSmrg               }
42101e04c3fSmrg            }
42201e04c3fSmrg            else {
42301e04c3fSmrg               for (i = 0; i < n; i++)
42401e04c3fSmrg                  indexes[i] = (GLuint) _mesa_half_to_float(s[i]);
42501e04c3fSmrg            }
4263464ebd5Sriastradh         }
42701e04c3fSmrg         break;
42801e04c3fSmrg      case GL_UNSIGNED_INT_24_8_EXT:
42901e04c3fSmrg         {
43001e04c3fSmrg            GLuint i;
43101e04c3fSmrg            const GLuint *s = (const GLuint *) src;
43201e04c3fSmrg            if (unpack->SwapBytes) {
43301e04c3fSmrg               for (i = 0; i < n; i++) {
43401e04c3fSmrg                  GLuint value = s[i];
43501e04c3fSmrg                  SWAP4BYTE(value);
43601e04c3fSmrg                  indexes[i] = value & 0xff;  /* lower 8 bits */
43701e04c3fSmrg               }
43801e04c3fSmrg            }
43901e04c3fSmrg            else {
44001e04c3fSmrg               for (i = 0; i < n; i++)
44101e04c3fSmrg                  indexes[i] = s[i] & 0xff;  /* lower 8 bits */
44201e04c3fSmrg            }
4433464ebd5Sriastradh         }
44401e04c3fSmrg         break;
44501e04c3fSmrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
44601e04c3fSmrg         {
44701e04c3fSmrg            GLuint i;
44801e04c3fSmrg            const GLuint *s = (const GLuint *) src;
44901e04c3fSmrg            if (unpack->SwapBytes) {
45001e04c3fSmrg               for (i = 0; i < n; i++) {
45101e04c3fSmrg                  GLuint value = s[i*2+1];
45201e04c3fSmrg                  SWAP4BYTE(value);
45301e04c3fSmrg                  indexes[i] = value & 0xff;  /* lower 8 bits */
45401e04c3fSmrg               }
45501e04c3fSmrg            }
45601e04c3fSmrg            else {
45701e04c3fSmrg               for (i = 0; i < n; i++)
45801e04c3fSmrg                  indexes[i] = s[i*2+1] & 0xff;  /* lower 8 bits */
45901e04c3fSmrg            }
46001e04c3fSmrg         }
46101e04c3fSmrg         break;
4623464ebd5Sriastradh
46301e04c3fSmrg      default:
46401e04c3fSmrg         unreachable("bad srcType in extract_uint_indexes");
46501e04c3fSmrg   }
4663464ebd5Sriastradh}
4673464ebd5Sriastradh
4683464ebd5Sriastradh
4693464ebd5Sriastradh/*
4703464ebd5Sriastradh * Unpack a row of stencil data from a client buffer according to
4713464ebd5Sriastradh * the pixel unpacking parameters.
4723464ebd5Sriastradh * This is (or will be) used by glDrawPixels
4733464ebd5Sriastradh *
4743464ebd5Sriastradh * Args:  ctx - the context
4753464ebd5Sriastradh *        n - number of pixels
4763464ebd5Sriastradh *        dstType - destination data type
4773464ebd5Sriastradh *        dest - destination array
4783464ebd5Sriastradh *        srcType - source pixel type
4793464ebd5Sriastradh *        source - source data pointer
4803464ebd5Sriastradh *        srcPacking - pixel unpacking parameters
4813464ebd5Sriastradh *        transferOps - apply offset/bias/lookup ops?
4823464ebd5Sriastradh */
4833464ebd5Sriastradhvoid
4843464ebd5Sriastradh_mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n,
4853464ebd5Sriastradh                           GLenum dstType, GLvoid *dest,
4863464ebd5Sriastradh                           GLenum srcType, const GLvoid *source,
4873464ebd5Sriastradh                           const struct gl_pixelstore_attrib *srcPacking,
4883464ebd5Sriastradh                           GLbitfield transferOps )
4893464ebd5Sriastradh{
49001e04c3fSmrg   assert(srcType == GL_BITMAP ||
4913464ebd5Sriastradh          srcType == GL_UNSIGNED_BYTE ||
4923464ebd5Sriastradh          srcType == GL_BYTE ||
4933464ebd5Sriastradh          srcType == GL_UNSIGNED_SHORT ||
4943464ebd5Sriastradh          srcType == GL_SHORT ||
4953464ebd5Sriastradh          srcType == GL_UNSIGNED_INT ||
4963464ebd5Sriastradh          srcType == GL_INT ||
4973464ebd5Sriastradh          srcType == GL_UNSIGNED_INT_24_8_EXT ||
4983464ebd5Sriastradh          srcType == GL_HALF_FLOAT_ARB ||
49901e04c3fSmrg          srcType == GL_HALF_FLOAT_OES ||
500af69d88dSmrg          srcType == GL_FLOAT ||
501af69d88dSmrg          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
5023464ebd5Sriastradh
50301e04c3fSmrg   assert(dstType == GL_UNSIGNED_BYTE ||
5043464ebd5Sriastradh          dstType == GL_UNSIGNED_SHORT ||
505af69d88dSmrg          dstType == GL_UNSIGNED_INT ||
506af69d88dSmrg          dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
5073464ebd5Sriastradh
5083464ebd5Sriastradh   /* only shift and offset apply to stencil */
5093464ebd5Sriastradh   transferOps &= IMAGE_SHIFT_OFFSET_BIT;
5103464ebd5Sriastradh
5113464ebd5Sriastradh   /*
5123464ebd5Sriastradh    * Try simple cases first
5133464ebd5Sriastradh    */
5143464ebd5Sriastradh   if (transferOps == 0 &&
5153464ebd5Sriastradh       !ctx->Pixel.MapStencilFlag &&
5163464ebd5Sriastradh       srcType == GL_UNSIGNED_BYTE &&
5173464ebd5Sriastradh       dstType == GL_UNSIGNED_BYTE) {
5183464ebd5Sriastradh      memcpy(dest, source, n * sizeof(GLubyte));
5193464ebd5Sriastradh   }
5203464ebd5Sriastradh   else if (transferOps == 0 &&
5213464ebd5Sriastradh            !ctx->Pixel.MapStencilFlag &&
5223464ebd5Sriastradh            srcType == GL_UNSIGNED_INT &&
5233464ebd5Sriastradh            dstType == GL_UNSIGNED_INT &&
5243464ebd5Sriastradh            !srcPacking->SwapBytes) {
5253464ebd5Sriastradh      memcpy(dest, source, n * sizeof(GLuint));
5263464ebd5Sriastradh   }
5273464ebd5Sriastradh   else {
5283464ebd5Sriastradh      /*
5293464ebd5Sriastradh       * general solution
5303464ebd5Sriastradh       */
531af69d88dSmrg      GLuint *indexes = malloc(n * sizeof(GLuint));
5323464ebd5Sriastradh
5333464ebd5Sriastradh      if (!indexes) {
5343464ebd5Sriastradh         _mesa_error(ctx, GL_OUT_OF_MEMORY, "stencil unpacking");
5353464ebd5Sriastradh         return;
5363464ebd5Sriastradh      }
5373464ebd5Sriastradh
5383464ebd5Sriastradh      extract_uint_indexes(n, indexes, GL_STENCIL_INDEX, srcType, source,
5393464ebd5Sriastradh                           srcPacking);
5403464ebd5Sriastradh
5413464ebd5Sriastradh      if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
5423464ebd5Sriastradh         /* shift and offset indexes */
5433464ebd5Sriastradh         _mesa_shift_and_offset_ci(ctx, n, indexes);
5443464ebd5Sriastradh      }
5453464ebd5Sriastradh
5463464ebd5Sriastradh      if (ctx->Pixel.MapStencilFlag) {
5473464ebd5Sriastradh         /* Apply stencil lookup table */
5483464ebd5Sriastradh         const GLuint mask = ctx->PixelMaps.StoS.Size - 1;
5493464ebd5Sriastradh         GLuint i;
5503464ebd5Sriastradh         for (i = 0; i < n; i++) {
5513464ebd5Sriastradh            indexes[i] = (GLuint)ctx->PixelMaps.StoS.Map[ indexes[i] & mask ];
5523464ebd5Sriastradh         }
5533464ebd5Sriastradh      }
5543464ebd5Sriastradh
5553464ebd5Sriastradh      /* convert to dest type */
5563464ebd5Sriastradh      switch (dstType) {
5573464ebd5Sriastradh         case GL_UNSIGNED_BYTE:
5583464ebd5Sriastradh            {
5593464ebd5Sriastradh               GLubyte *dst = (GLubyte *) dest;
5603464ebd5Sriastradh               GLuint i;
5613464ebd5Sriastradh               for (i = 0; i < n; i++) {
5623464ebd5Sriastradh                  dst[i] = (GLubyte) (indexes[i] & 0xff);
5633464ebd5Sriastradh               }
5643464ebd5Sriastradh            }
5653464ebd5Sriastradh            break;
5663464ebd5Sriastradh         case GL_UNSIGNED_SHORT:
5673464ebd5Sriastradh            {
5683464ebd5Sriastradh               GLuint *dst = (GLuint *) dest;
5693464ebd5Sriastradh               GLuint i;
5703464ebd5Sriastradh               for (i = 0; i < n; i++) {
5713464ebd5Sriastradh                  dst[i] = (GLushort) (indexes[i] & 0xffff);
5723464ebd5Sriastradh               }
5733464ebd5Sriastradh            }
5743464ebd5Sriastradh            break;
5753464ebd5Sriastradh         case GL_UNSIGNED_INT:
5763464ebd5Sriastradh            memcpy(dest, indexes, n * sizeof(GLuint));
5773464ebd5Sriastradh            break;
578af69d88dSmrg         case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
579af69d88dSmrg            {
580af69d88dSmrg               GLuint *dst = (GLuint *) dest;
581af69d88dSmrg               GLuint i;
582af69d88dSmrg               for (i = 0; i < n; i++) {
583af69d88dSmrg                  dst[i*2+1] = indexes[i] & 0xff; /* lower 8 bits */
584af69d88dSmrg               }
585af69d88dSmrg            }
586af69d88dSmrg            break;
5873464ebd5Sriastradh         default:
58801e04c3fSmrg            unreachable("bad dstType in _mesa_unpack_stencil_span");
5893464ebd5Sriastradh      }
5903464ebd5Sriastradh
5913464ebd5Sriastradh      free(indexes);
5923464ebd5Sriastradh   }
5933464ebd5Sriastradh}
5943464ebd5Sriastradh
5953464ebd5Sriastradh
5963464ebd5Sriastradhvoid
5973464ebd5Sriastradh_mesa_pack_stencil_span( struct gl_context *ctx, GLuint n,
598af69d88dSmrg                         GLenum dstType, GLvoid *dest, const GLubyte *source,
5993464ebd5Sriastradh                         const struct gl_pixelstore_attrib *dstPacking )
6003464ebd5Sriastradh{
601af69d88dSmrg   GLubyte *stencil = malloc(n * sizeof(GLubyte));
6023464ebd5Sriastradh
6033464ebd5Sriastradh   if (!stencil) {
6043464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "stencil packing");
6053464ebd5Sriastradh      return;
6063464ebd5Sriastradh   }
6073464ebd5Sriastradh
6083464ebd5Sriastradh   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
6093464ebd5Sriastradh       ctx->Pixel.MapStencilFlag) {
6103464ebd5Sriastradh      /* make a copy of input */
611af69d88dSmrg      memcpy(stencil, source, n * sizeof(GLubyte));
6123464ebd5Sriastradh      _mesa_apply_stencil_transfer_ops(ctx, n, stencil);
6133464ebd5Sriastradh      source = stencil;
6143464ebd5Sriastradh   }
6153464ebd5Sriastradh
6163464ebd5Sriastradh   switch (dstType) {
6173464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
618af69d88dSmrg      memcpy(dest, source, n);
6193464ebd5Sriastradh      break;
6203464ebd5Sriastradh   case GL_BYTE:
6213464ebd5Sriastradh      {
6223464ebd5Sriastradh         GLbyte *dst = (GLbyte *) dest;
6233464ebd5Sriastradh         GLuint i;
6243464ebd5Sriastradh         for (i=0;i<n;i++) {
6253464ebd5Sriastradh            dst[i] = (GLbyte) (source[i] & 0x7f);
6263464ebd5Sriastradh         }
6273464ebd5Sriastradh      }
6283464ebd5Sriastradh      break;
6293464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
6303464ebd5Sriastradh      {
6313464ebd5Sriastradh         GLushort *dst = (GLushort *) dest;
6323464ebd5Sriastradh         GLuint i;
6333464ebd5Sriastradh         for (i=0;i<n;i++) {
6343464ebd5Sriastradh            dst[i] = (GLushort) source[i];
6353464ebd5Sriastradh         }
6363464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6373464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
6383464ebd5Sriastradh         }
6393464ebd5Sriastradh      }
6403464ebd5Sriastradh      break;
6413464ebd5Sriastradh   case GL_SHORT:
6423464ebd5Sriastradh      {
6433464ebd5Sriastradh         GLshort *dst = (GLshort *) dest;
6443464ebd5Sriastradh         GLuint i;
6453464ebd5Sriastradh         for (i=0;i<n;i++) {
6463464ebd5Sriastradh            dst[i] = (GLshort) source[i];
6473464ebd5Sriastradh         }
6483464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6493464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
6503464ebd5Sriastradh         }
6513464ebd5Sriastradh      }
6523464ebd5Sriastradh      break;
6533464ebd5Sriastradh   case GL_UNSIGNED_INT:
6543464ebd5Sriastradh      {
6553464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
6563464ebd5Sriastradh         GLuint i;
6573464ebd5Sriastradh         for (i=0;i<n;i++) {
6583464ebd5Sriastradh            dst[i] = (GLuint) source[i];
6593464ebd5Sriastradh         }
6603464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6613464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
6623464ebd5Sriastradh         }
6633464ebd5Sriastradh      }
6643464ebd5Sriastradh      break;
6653464ebd5Sriastradh   case GL_INT:
6663464ebd5Sriastradh      {
6673464ebd5Sriastradh         GLint *dst = (GLint *) dest;
6683464ebd5Sriastradh         GLuint i;
6693464ebd5Sriastradh         for (i=0;i<n;i++) {
6703464ebd5Sriastradh            dst[i] = (GLint) source[i];
6713464ebd5Sriastradh         }
6723464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6733464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
6743464ebd5Sriastradh         }
6753464ebd5Sriastradh      }
6763464ebd5Sriastradh      break;
6773464ebd5Sriastradh   case GL_FLOAT:
6783464ebd5Sriastradh      {
6793464ebd5Sriastradh         GLfloat *dst = (GLfloat *) dest;
6803464ebd5Sriastradh         GLuint i;
6813464ebd5Sriastradh         for (i=0;i<n;i++) {
6823464ebd5Sriastradh            dst[i] = (GLfloat) source[i];
6833464ebd5Sriastradh         }
6843464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6853464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
6863464ebd5Sriastradh         }
6873464ebd5Sriastradh      }
6883464ebd5Sriastradh      break;
6893464ebd5Sriastradh   case GL_HALF_FLOAT_ARB:
69001e04c3fSmrg   case GL_HALF_FLOAT_OES:
6913464ebd5Sriastradh      {
6923464ebd5Sriastradh         GLhalfARB *dst = (GLhalfARB *) dest;
6933464ebd5Sriastradh         GLuint i;
6943464ebd5Sriastradh         for (i=0;i<n;i++) {
6953464ebd5Sriastradh            dst[i] = _mesa_float_to_half( (float) source[i] );
6963464ebd5Sriastradh         }
6973464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6983464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
6993464ebd5Sriastradh         }
7003464ebd5Sriastradh      }
7013464ebd5Sriastradh      break;
7023464ebd5Sriastradh   case GL_BITMAP:
7033464ebd5Sriastradh      if (dstPacking->LsbFirst) {
7043464ebd5Sriastradh         GLubyte *dst = (GLubyte *) dest;
7053464ebd5Sriastradh         GLint shift = 0;
7063464ebd5Sriastradh         GLuint i;
7073464ebd5Sriastradh         for (i = 0; i < n; i++) {
7083464ebd5Sriastradh            if (shift == 0)
7093464ebd5Sriastradh               *dst = 0;
7103464ebd5Sriastradh            *dst |= ((source[i] != 0) << shift);
7113464ebd5Sriastradh            shift++;
7123464ebd5Sriastradh            if (shift == 8) {
7133464ebd5Sriastradh               shift = 0;
7143464ebd5Sriastradh               dst++;
7153464ebd5Sriastradh            }
7163464ebd5Sriastradh         }
7173464ebd5Sriastradh      }
7183464ebd5Sriastradh      else {
7193464ebd5Sriastradh         GLubyte *dst = (GLubyte *) dest;
7203464ebd5Sriastradh         GLint shift = 7;
7213464ebd5Sriastradh         GLuint i;
7223464ebd5Sriastradh         for (i = 0; i < n; i++) {
7233464ebd5Sriastradh            if (shift == 7)
7243464ebd5Sriastradh               *dst = 0;
7253464ebd5Sriastradh            *dst |= ((source[i] != 0) << shift);
7263464ebd5Sriastradh            shift--;
7273464ebd5Sriastradh            if (shift < 0) {
7283464ebd5Sriastradh               shift = 7;
7293464ebd5Sriastradh               dst++;
7303464ebd5Sriastradh            }
7313464ebd5Sriastradh         }
7323464ebd5Sriastradh      }
7333464ebd5Sriastradh      break;
7343464ebd5Sriastradh   default:
73501e04c3fSmrg      unreachable("bad type in _mesa_pack_index_span");
7363464ebd5Sriastradh   }
7373464ebd5Sriastradh
7383464ebd5Sriastradh   free(stencil);
7393464ebd5Sriastradh}
7403464ebd5Sriastradh
7413464ebd5Sriastradh#define DEPTH_VALUES(GLTYPE, GLTYPE2FLOAT)                              \
7423464ebd5Sriastradh    do {                                                                \
7433464ebd5Sriastradh        GLuint i;                                                       \
7443464ebd5Sriastradh        const GLTYPE *src = (const GLTYPE *)source;                     \
7453464ebd5Sriastradh        for (i = 0; i < n; i++) {                                       \
7463464ebd5Sriastradh            GLTYPE value = src[i];                                      \
7473464ebd5Sriastradh            if (srcPacking->SwapBytes) {                                \
7483464ebd5Sriastradh                if (sizeof(GLTYPE) == 2) {                              \
7493464ebd5Sriastradh                    SWAP2BYTE(value);                                   \
7503464ebd5Sriastradh                } else if (sizeof(GLTYPE) == 4) {                       \
7513464ebd5Sriastradh                    SWAP4BYTE(value);                                   \
7523464ebd5Sriastradh                }                                                       \
7533464ebd5Sriastradh            }                                                           \
7543464ebd5Sriastradh            depthValues[i] = GLTYPE2FLOAT(value);                       \
7553464ebd5Sriastradh        }                                                               \
7563464ebd5Sriastradh    } while (0)
7573464ebd5Sriastradh
7583464ebd5Sriastradh
7593464ebd5Sriastradh/**
7603464ebd5Sriastradh * Unpack a row of depth/z values from memory, returning GLushort, GLuint
7613464ebd5Sriastradh * or GLfloat values.
7623464ebd5Sriastradh * The glPixelTransfer (scale/bias) params will be applied.
7633464ebd5Sriastradh *
7643464ebd5Sriastradh * \param dstType  one of GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_FLOAT
7653464ebd5Sriastradh * \param depthMax  max value for returned GLushort or GLuint values
7663464ebd5Sriastradh *                  (ignored for GLfloat).
7673464ebd5Sriastradh */
7683464ebd5Sriastradhvoid
7693464ebd5Sriastradh_mesa_unpack_depth_span( struct gl_context *ctx, GLuint n,
7703464ebd5Sriastradh                         GLenum dstType, GLvoid *dest, GLuint depthMax,
7713464ebd5Sriastradh                         GLenum srcType, const GLvoid *source,
7723464ebd5Sriastradh                         const struct gl_pixelstore_attrib *srcPacking )
7733464ebd5Sriastradh{
7743464ebd5Sriastradh   GLfloat *depthTemp = NULL, *depthValues;
7753464ebd5Sriastradh   GLboolean needClamp = GL_FALSE;
7763464ebd5Sriastradh
7773464ebd5Sriastradh   /* Look for special cases first.
7783464ebd5Sriastradh    * Not only are these faster, they're less prone to numeric conversion
7793464ebd5Sriastradh    * problems.  Otherwise, converting from an int type to a float then
7803464ebd5Sriastradh    * back to an int type can introduce errors that will show up as
7813464ebd5Sriastradh    * artifacts in things like depth peeling which uses glCopyTexImage.
7823464ebd5Sriastradh    */
78301e04c3fSmrg   if (ctx->Pixel.DepthScale == 1.0F && ctx->Pixel.DepthBias == 0.0F) {
7843464ebd5Sriastradh      if (srcType == GL_UNSIGNED_INT && dstType == GL_UNSIGNED_SHORT) {
7853464ebd5Sriastradh         const GLuint *src = (const GLuint *) source;
7863464ebd5Sriastradh         GLushort *dst = (GLushort *) dest;
7873464ebd5Sriastradh         GLuint i;
7883464ebd5Sriastradh         for (i = 0; i < n; i++) {
7893464ebd5Sriastradh            dst[i] = src[i] >> 16;
7903464ebd5Sriastradh         }
7913464ebd5Sriastradh         return;
7923464ebd5Sriastradh      }
7933464ebd5Sriastradh      if (srcType == GL_UNSIGNED_SHORT
7943464ebd5Sriastradh          && dstType == GL_UNSIGNED_INT
7953464ebd5Sriastradh          && depthMax == 0xffffffff) {
7963464ebd5Sriastradh         const GLushort *src = (const GLushort *) source;
7973464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
7983464ebd5Sriastradh         GLuint i;
7993464ebd5Sriastradh         for (i = 0; i < n; i++) {
8003464ebd5Sriastradh            dst[i] = src[i] | (src[i] << 16);
8013464ebd5Sriastradh         }
8023464ebd5Sriastradh         return;
8033464ebd5Sriastradh      }
8043464ebd5Sriastradh      if (srcType == GL_UNSIGNED_INT_24_8
8053464ebd5Sriastradh          && dstType == GL_UNSIGNED_INT
8063464ebd5Sriastradh          && depthMax == 0xffffff) {
8073464ebd5Sriastradh         const GLuint *src = (const GLuint *) source;
8083464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
8093464ebd5Sriastradh         GLuint i;
8103464ebd5Sriastradh         for (i = 0; i < n; i++) {
8113464ebd5Sriastradh            dst[i] = src[i] >> 8;
8123464ebd5Sriastradh         }
8133464ebd5Sriastradh         return;
8143464ebd5Sriastradh      }
8153464ebd5Sriastradh      /* XXX may want to add additional cases here someday */
8163464ebd5Sriastradh   }
8173464ebd5Sriastradh
8183464ebd5Sriastradh   /* general case path follows */
8193464ebd5Sriastradh
8203464ebd5Sriastradh   if (dstType == GL_FLOAT) {
8213464ebd5Sriastradh      depthValues = (GLfloat *) dest;
8223464ebd5Sriastradh   }
8233464ebd5Sriastradh   else {
824af69d88dSmrg      depthTemp = malloc(n * sizeof(GLfloat));
8253464ebd5Sriastradh      if (!depthTemp) {
8263464ebd5Sriastradh         _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
8273464ebd5Sriastradh         return;
8283464ebd5Sriastradh      }
8293464ebd5Sriastradh
8303464ebd5Sriastradh      depthValues = depthTemp;
8313464ebd5Sriastradh   }
8323464ebd5Sriastradh
8333464ebd5Sriastradh   /* Convert incoming values to GLfloat.  Some conversions will require
8343464ebd5Sriastradh    * clamping, below.
8353464ebd5Sriastradh    */
8363464ebd5Sriastradh   switch (srcType) {
8373464ebd5Sriastradh      case GL_BYTE:
838af69d88dSmrg         DEPTH_VALUES(GLbyte, BYTE_TO_FLOATZ);
8393464ebd5Sriastradh         needClamp = GL_TRUE;
8403464ebd5Sriastradh         break;
8413464ebd5Sriastradh      case GL_UNSIGNED_BYTE:
8423464ebd5Sriastradh         DEPTH_VALUES(GLubyte, UBYTE_TO_FLOAT);
8433464ebd5Sriastradh         break;
8443464ebd5Sriastradh      case GL_SHORT:
845af69d88dSmrg         DEPTH_VALUES(GLshort, SHORT_TO_FLOATZ);
8463464ebd5Sriastradh         needClamp = GL_TRUE;
8473464ebd5Sriastradh         break;
8483464ebd5Sriastradh      case GL_UNSIGNED_SHORT:
8493464ebd5Sriastradh         DEPTH_VALUES(GLushort, USHORT_TO_FLOAT);
8503464ebd5Sriastradh         break;
8513464ebd5Sriastradh      case GL_INT:
8523464ebd5Sriastradh         DEPTH_VALUES(GLint, INT_TO_FLOAT);
8533464ebd5Sriastradh         needClamp = GL_TRUE;
8543464ebd5Sriastradh         break;
8553464ebd5Sriastradh      case GL_UNSIGNED_INT:
8563464ebd5Sriastradh         DEPTH_VALUES(GLuint, UINT_TO_FLOAT);
8573464ebd5Sriastradh         break;
8583464ebd5Sriastradh      case GL_UNSIGNED_INT_24_8_EXT: /* GL_EXT_packed_depth_stencil */
8593464ebd5Sriastradh         if (dstType == GL_UNSIGNED_INT_24_8_EXT &&
8603464ebd5Sriastradh             depthMax == 0xffffff &&
86101e04c3fSmrg             ctx->Pixel.DepthScale == 1.0F &&
86201e04c3fSmrg             ctx->Pixel.DepthBias == 0.0F) {
8633464ebd5Sriastradh            const GLuint *src = (const GLuint *) source;
8643464ebd5Sriastradh            GLuint *zValues = (GLuint *) dest;
8653464ebd5Sriastradh            GLuint i;
8663464ebd5Sriastradh            for (i = 0; i < n; i++) {
8673464ebd5Sriastradh                GLuint value = src[i];
8683464ebd5Sriastradh                if (srcPacking->SwapBytes) {
8693464ebd5Sriastradh                    SWAP4BYTE(value);
8703464ebd5Sriastradh                }
8713464ebd5Sriastradh                zValues[i] = value & 0xffffff00;
8723464ebd5Sriastradh            }
8733464ebd5Sriastradh            free(depthTemp);
8743464ebd5Sriastradh            return;
8753464ebd5Sriastradh         }
8763464ebd5Sriastradh         else {
8773464ebd5Sriastradh            const GLuint *src = (const GLuint *) source;
8783464ebd5Sriastradh            const GLfloat scale = 1.0f / 0xffffff;
8793464ebd5Sriastradh            GLuint i;
8803464ebd5Sriastradh            for (i = 0; i < n; i++) {
8813464ebd5Sriastradh                GLuint value = src[i];
8823464ebd5Sriastradh                if (srcPacking->SwapBytes) {
8833464ebd5Sriastradh                    SWAP4BYTE(value);
8843464ebd5Sriastradh                }
8853464ebd5Sriastradh                depthValues[i] = (value >> 8) * scale;
8863464ebd5Sriastradh            }
8873464ebd5Sriastradh         }
8883464ebd5Sriastradh         break;
889af69d88dSmrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
890af69d88dSmrg         {
891af69d88dSmrg            GLuint i;
892af69d88dSmrg            const GLfloat *src = (const GLfloat *)source;
893af69d88dSmrg            for (i = 0; i < n; i++) {
894af69d88dSmrg               GLfloat value = src[i * 2];
895af69d88dSmrg               if (srcPacking->SwapBytes) {
896af69d88dSmrg                  SWAP4BYTE(value);
897af69d88dSmrg               }
898af69d88dSmrg               depthValues[i] = value;
899af69d88dSmrg            }
900af69d88dSmrg            needClamp = GL_TRUE;
901af69d88dSmrg         }
902af69d88dSmrg         break;
9033464ebd5Sriastradh      case GL_FLOAT:
9043464ebd5Sriastradh         DEPTH_VALUES(GLfloat, 1*);
9053464ebd5Sriastradh         needClamp = GL_TRUE;
9063464ebd5Sriastradh         break;
9073464ebd5Sriastradh      case GL_HALF_FLOAT_ARB:
90801e04c3fSmrg      case GL_HALF_FLOAT_OES:
9093464ebd5Sriastradh         {
9103464ebd5Sriastradh            GLuint i;
9113464ebd5Sriastradh            const GLhalfARB *src = (const GLhalfARB *) source;
9123464ebd5Sriastradh            for (i = 0; i < n; i++) {
9133464ebd5Sriastradh               GLhalfARB value = src[i];
9143464ebd5Sriastradh               if (srcPacking->SwapBytes) {
9153464ebd5Sriastradh                  SWAP2BYTE(value);
9163464ebd5Sriastradh               }
9173464ebd5Sriastradh               depthValues[i] = _mesa_half_to_float(value);
9183464ebd5Sriastradh            }
9193464ebd5Sriastradh            needClamp = GL_TRUE;
9203464ebd5Sriastradh         }
9213464ebd5Sriastradh         break;
9223464ebd5Sriastradh      default:
9233464ebd5Sriastradh         _mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()");
9243464ebd5Sriastradh         free(depthTemp);
9253464ebd5Sriastradh         return;
9263464ebd5Sriastradh   }
9273464ebd5Sriastradh
9283464ebd5Sriastradh   /* apply depth scale and bias */
9293464ebd5Sriastradh   {
9303464ebd5Sriastradh      const GLfloat scale = ctx->Pixel.DepthScale;
9313464ebd5Sriastradh      const GLfloat bias = ctx->Pixel.DepthBias;
93201e04c3fSmrg      if (scale != 1.0F || bias != 0.0F) {
9333464ebd5Sriastradh         GLuint i;
9343464ebd5Sriastradh         for (i = 0; i < n; i++) {
9353464ebd5Sriastradh            depthValues[i] = depthValues[i] * scale + bias;
9363464ebd5Sriastradh         }
9373464ebd5Sriastradh         needClamp = GL_TRUE;
9383464ebd5Sriastradh      }
9393464ebd5Sriastradh   }
9403464ebd5Sriastradh
9413464ebd5Sriastradh   /* clamp to [0, 1] */
9423464ebd5Sriastradh   if (needClamp) {
9433464ebd5Sriastradh      GLuint i;
9443464ebd5Sriastradh      for (i = 0; i < n; i++) {
94501e04c3fSmrg         depthValues[i] = CLAMP(depthValues[i], 0.0F, 1.0F);
9463464ebd5Sriastradh      }
9473464ebd5Sriastradh   }
9483464ebd5Sriastradh
9493464ebd5Sriastradh   /*
9503464ebd5Sriastradh    * Convert values to dstType
9513464ebd5Sriastradh    */
9523464ebd5Sriastradh   if (dstType == GL_UNSIGNED_INT) {
9533464ebd5Sriastradh      GLuint *zValues = (GLuint *) dest;
9543464ebd5Sriastradh      GLuint i;
9553464ebd5Sriastradh      if (depthMax <= 0xffffff) {
9563464ebd5Sriastradh         /* no overflow worries */
9573464ebd5Sriastradh         for (i = 0; i < n; i++) {
9583464ebd5Sriastradh            zValues[i] = (GLuint) (depthValues[i] * (GLfloat) depthMax);
9593464ebd5Sriastradh         }
9603464ebd5Sriastradh      }
9613464ebd5Sriastradh      else {
9623464ebd5Sriastradh         /* need to use double precision to prevent overflow problems */
9633464ebd5Sriastradh         for (i = 0; i < n; i++) {
964af69d88dSmrg            GLdouble z = depthValues[i] * (GLdouble) depthMax;
9653464ebd5Sriastradh            if (z >= (GLdouble) 0xffffffff)
9663464ebd5Sriastradh               zValues[i] = 0xffffffff;
9673464ebd5Sriastradh            else
9683464ebd5Sriastradh               zValues[i] = (GLuint) z;
9693464ebd5Sriastradh         }
9703464ebd5Sriastradh      }
9713464ebd5Sriastradh   }
9723464ebd5Sriastradh   else if (dstType == GL_UNSIGNED_SHORT) {
9733464ebd5Sriastradh      GLushort *zValues = (GLushort *) dest;
9743464ebd5Sriastradh      GLuint i;
97501e04c3fSmrg      assert(depthMax <= 0xffff);
9763464ebd5Sriastradh      for (i = 0; i < n; i++) {
9773464ebd5Sriastradh         zValues[i] = (GLushort) (depthValues[i] * (GLfloat) depthMax);
9783464ebd5Sriastradh      }
9793464ebd5Sriastradh   }
980af69d88dSmrg   else if (dstType == GL_FLOAT) {
981af69d88dSmrg      /* Nothing to do. depthValues is pointing to dest. */
982af69d88dSmrg   }
983af69d88dSmrg   else if (dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) {
984af69d88dSmrg      GLfloat *zValues = (GLfloat*) dest;
985af69d88dSmrg      GLuint i;
986af69d88dSmrg      for (i = 0; i < n; i++) {
987af69d88dSmrg         zValues[i*2] = depthValues[i];
988af69d88dSmrg      }
989af69d88dSmrg   }
9903464ebd5Sriastradh   else {
99101e04c3fSmrg      assert(0);
9923464ebd5Sriastradh   }
9933464ebd5Sriastradh
9943464ebd5Sriastradh   free(depthTemp);
9953464ebd5Sriastradh}
9963464ebd5Sriastradh
9973464ebd5Sriastradh
9983464ebd5Sriastradh/*
9993464ebd5Sriastradh * Pack an array of depth values.  The values are floats in [0,1].
10003464ebd5Sriastradh */
10013464ebd5Sriastradhvoid
10023464ebd5Sriastradh_mesa_pack_depth_span( struct gl_context *ctx, GLuint n, GLvoid *dest,
10033464ebd5Sriastradh                       GLenum dstType, const GLfloat *depthSpan,
10043464ebd5Sriastradh                       const struct gl_pixelstore_attrib *dstPacking )
10053464ebd5Sriastradh{
1006af69d88dSmrg   GLfloat *depthCopy = malloc(n * sizeof(GLfloat));
10073464ebd5Sriastradh   if (!depthCopy) {
10083464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel packing");
10093464ebd5Sriastradh      return;
10103464ebd5Sriastradh   }
10113464ebd5Sriastradh
101201e04c3fSmrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) {
10133464ebd5Sriastradh      memcpy(depthCopy, depthSpan, n * sizeof(GLfloat));
10143464ebd5Sriastradh      _mesa_scale_and_bias_depth(ctx, n, depthCopy);
10153464ebd5Sriastradh      depthSpan = depthCopy;
10163464ebd5Sriastradh   }
10173464ebd5Sriastradh
10183464ebd5Sriastradh   switch (dstType) {
10193464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
10203464ebd5Sriastradh      {
10213464ebd5Sriastradh         GLubyte *dst = (GLubyte *) dest;
10223464ebd5Sriastradh         GLuint i;
10233464ebd5Sriastradh         for (i = 0; i < n; i++) {
10243464ebd5Sriastradh            dst[i] = FLOAT_TO_UBYTE( depthSpan[i] );
10253464ebd5Sriastradh         }
10263464ebd5Sriastradh      }
10273464ebd5Sriastradh      break;
10283464ebd5Sriastradh   case GL_BYTE:
10293464ebd5Sriastradh      {
10303464ebd5Sriastradh         GLbyte *dst = (GLbyte *) dest;
10313464ebd5Sriastradh         GLuint i;
10323464ebd5Sriastradh         for (i = 0; i < n; i++) {
10333464ebd5Sriastradh            dst[i] = FLOAT_TO_BYTE( depthSpan[i] );
10343464ebd5Sriastradh         }
10353464ebd5Sriastradh      }
10363464ebd5Sriastradh      break;
10373464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
10383464ebd5Sriastradh      {
10393464ebd5Sriastradh         GLushort *dst = (GLushort *) dest;
10403464ebd5Sriastradh         GLuint i;
10413464ebd5Sriastradh         for (i = 0; i < n; i++) {
10423464ebd5Sriastradh            CLAMPED_FLOAT_TO_USHORT(dst[i], depthSpan[i]);
10433464ebd5Sriastradh         }
10443464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10453464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
10463464ebd5Sriastradh         }
10473464ebd5Sriastradh      }
10483464ebd5Sriastradh      break;
10493464ebd5Sriastradh   case GL_SHORT:
10503464ebd5Sriastradh      {
10513464ebd5Sriastradh         GLshort *dst = (GLshort *) dest;
10523464ebd5Sriastradh         GLuint i;
10533464ebd5Sriastradh         for (i = 0; i < n; i++) {
10543464ebd5Sriastradh            dst[i] = FLOAT_TO_SHORT( depthSpan[i] );
10553464ebd5Sriastradh         }
10563464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10573464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
10583464ebd5Sriastradh         }
10593464ebd5Sriastradh      }
10603464ebd5Sriastradh      break;
106101e04c3fSmrg   case GL_UNSIGNED_INT_24_8:
106201e04c3fSmrg      {
106301e04c3fSmrg         const GLdouble scale = (GLdouble) 0xffffff;
106401e04c3fSmrg         GLuint *dst = (GLuint *) dest;
106501e04c3fSmrg         GLuint i;
106601e04c3fSmrg         for (i = 0; i < n; i++) {
106701e04c3fSmrg            GLuint z = (GLuint) (depthSpan[i] * scale);
106801e04c3fSmrg            assert(z <= 0xffffff);
106901e04c3fSmrg            dst[i] = (z << 8);
107001e04c3fSmrg         }
107101e04c3fSmrg         if (dstPacking->SwapBytes) {
107201e04c3fSmrg            _mesa_swap4( (GLuint *) dst, n );
107301e04c3fSmrg         }
107401e04c3fSmrg         break;
107501e04c3fSmrg      }
10763464ebd5Sriastradh   case GL_UNSIGNED_INT:
10773464ebd5Sriastradh      {
10783464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
10793464ebd5Sriastradh         GLuint i;
10803464ebd5Sriastradh         for (i = 0; i < n; i++) {
10813464ebd5Sriastradh            dst[i] = FLOAT_TO_UINT( depthSpan[i] );
10823464ebd5Sriastradh         }
10833464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10843464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
10853464ebd5Sriastradh         }
10863464ebd5Sriastradh      }
10873464ebd5Sriastradh      break;
10883464ebd5Sriastradh   case GL_INT:
10893464ebd5Sriastradh      {
10903464ebd5Sriastradh         GLint *dst = (GLint *) dest;
10913464ebd5Sriastradh         GLuint i;
10923464ebd5Sriastradh         for (i = 0; i < n; i++) {
10933464ebd5Sriastradh            dst[i] = FLOAT_TO_INT( depthSpan[i] );
10943464ebd5Sriastradh         }
10953464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10963464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
10973464ebd5Sriastradh         }
10983464ebd5Sriastradh      }
10993464ebd5Sriastradh      break;
11003464ebd5Sriastradh   case GL_FLOAT:
11013464ebd5Sriastradh      {
11023464ebd5Sriastradh         GLfloat *dst = (GLfloat *) dest;
11033464ebd5Sriastradh         GLuint i;
11043464ebd5Sriastradh         for (i = 0; i < n; i++) {
11053464ebd5Sriastradh            dst[i] = depthSpan[i];
11063464ebd5Sriastradh         }
11073464ebd5Sriastradh         if (dstPacking->SwapBytes) {
11083464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
11093464ebd5Sriastradh         }
11103464ebd5Sriastradh      }
11113464ebd5Sriastradh      break;
11123464ebd5Sriastradh   case GL_HALF_FLOAT_ARB:
111301e04c3fSmrg   case GL_HALF_FLOAT_OES:
11143464ebd5Sriastradh      {
11153464ebd5Sriastradh         GLhalfARB *dst = (GLhalfARB *) dest;
11163464ebd5Sriastradh         GLuint i;
11173464ebd5Sriastradh         for (i = 0; i < n; i++) {
11183464ebd5Sriastradh            dst[i] = _mesa_float_to_half(depthSpan[i]);
11193464ebd5Sriastradh         }
11203464ebd5Sriastradh         if (dstPacking->SwapBytes) {
11213464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
11223464ebd5Sriastradh         }
11233464ebd5Sriastradh      }
11243464ebd5Sriastradh      break;
11253464ebd5Sriastradh   default:
112601e04c3fSmrg      unreachable("bad type in _mesa_pack_depth_span()");
11273464ebd5Sriastradh   }
11283464ebd5Sriastradh
11293464ebd5Sriastradh   free(depthCopy);
11303464ebd5Sriastradh}
11313464ebd5Sriastradh
11323464ebd5Sriastradh
11333464ebd5Sriastradh
11343464ebd5Sriastradh/**
1135af69d88dSmrg * Pack depth and stencil values as GL_DEPTH_STENCIL (GL_UNSIGNED_INT_24_8 etc)
11363464ebd5Sriastradh */
11373464ebd5Sriastradhvoid
1138af69d88dSmrg_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n,
1139af69d88dSmrg                              GLenum dstType, GLuint *dest,
11403464ebd5Sriastradh                              const GLfloat *depthVals,
1141af69d88dSmrg                              const GLubyte *stencilVals,
11423464ebd5Sriastradh                              const struct gl_pixelstore_attrib *dstPacking)
11433464ebd5Sriastradh{
1144af69d88dSmrg   GLfloat *depthCopy = malloc(n * sizeof(GLfloat));
1145af69d88dSmrg   GLubyte *stencilCopy = malloc(n * sizeof(GLubyte));
11463464ebd5Sriastradh   GLuint i;
11473464ebd5Sriastradh
11483464ebd5Sriastradh   if (!depthCopy || !stencilCopy) {
11493464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel packing");
11503464ebd5Sriastradh      free(depthCopy);
11513464ebd5Sriastradh      free(stencilCopy);
11523464ebd5Sriastradh      return;
11533464ebd5Sriastradh   }
11543464ebd5Sriastradh
115501e04c3fSmrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) {
11563464ebd5Sriastradh      memcpy(depthCopy, depthVals, n * sizeof(GLfloat));
11573464ebd5Sriastradh      _mesa_scale_and_bias_depth(ctx, n, depthCopy);
11583464ebd5Sriastradh      depthVals = depthCopy;
11593464ebd5Sriastradh   }
11603464ebd5Sriastradh
11613464ebd5Sriastradh   if (ctx->Pixel.IndexShift ||
11623464ebd5Sriastradh       ctx->Pixel.IndexOffset ||
11633464ebd5Sriastradh       ctx->Pixel.MapStencilFlag) {
1164af69d88dSmrg      memcpy(stencilCopy, stencilVals, n * sizeof(GLubyte));
11653464ebd5Sriastradh      _mesa_apply_stencil_transfer_ops(ctx, n, stencilCopy);
11663464ebd5Sriastradh      stencilVals = stencilCopy;
11673464ebd5Sriastradh   }
11683464ebd5Sriastradh
1169af69d88dSmrg   switch (dstType) {
1170af69d88dSmrg   case GL_UNSIGNED_INT_24_8:
1171af69d88dSmrg      for (i = 0; i < n; i++) {
1172af69d88dSmrg         GLuint z = (GLuint) (depthVals[i] * 0xffffff);
1173af69d88dSmrg         dest[i] = (z << 8) | (stencilVals[i] & 0xff);
1174af69d88dSmrg      }
1175af69d88dSmrg      break;
1176af69d88dSmrg   case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
1177af69d88dSmrg      for (i = 0; i < n; i++) {
1178af69d88dSmrg         ((GLfloat*)dest)[i*2] = depthVals[i];
1179af69d88dSmrg         dest[i*2+1] = stencilVals[i] & 0xff;
1180af69d88dSmrg      }
1181af69d88dSmrg      break;
11823464ebd5Sriastradh   }
11833464ebd5Sriastradh
11843464ebd5Sriastradh   if (dstPacking->SwapBytes) {
11853464ebd5Sriastradh      _mesa_swap4(dest, n);
11863464ebd5Sriastradh   }
11873464ebd5Sriastradh
11883464ebd5Sriastradh   free(depthCopy);
11893464ebd5Sriastradh   free(stencilCopy);
11903464ebd5Sriastradh}
11913464ebd5Sriastradh
11923464ebd5Sriastradh
11933464ebd5Sriastradh
11943464ebd5Sriastradh/**
11953464ebd5Sriastradh * Unpack image data.  Apply byte swapping, byte flipping (bitmap).
11963464ebd5Sriastradh * Return all image data in a contiguous block.  This is used when we
11973464ebd5Sriastradh * compile glDrawPixels, glTexImage, etc into a display list.  We
11983464ebd5Sriastradh * need a copy of the data in a standard format.
11993464ebd5Sriastradh */
12003464ebd5Sriastradhvoid *
12013464ebd5Sriastradh_mesa_unpack_image( GLuint dimensions,
12023464ebd5Sriastradh                    GLsizei width, GLsizei height, GLsizei depth,
12033464ebd5Sriastradh                    GLenum format, GLenum type, const GLvoid *pixels,
12043464ebd5Sriastradh                    const struct gl_pixelstore_attrib *unpack )
12053464ebd5Sriastradh{
12063464ebd5Sriastradh   GLint bytesPerRow, compsPerRow;
12073464ebd5Sriastradh   GLboolean flipBytes, swap2, swap4;
12083464ebd5Sriastradh
12093464ebd5Sriastradh   if (!pixels)
12103464ebd5Sriastradh      return NULL;  /* not necessarily an error */
12113464ebd5Sriastradh
12123464ebd5Sriastradh   if (width <= 0 || height <= 0 || depth <= 0)
12133464ebd5Sriastradh      return NULL;  /* generate error later */
12143464ebd5Sriastradh
12153464ebd5Sriastradh   if (type == GL_BITMAP) {
12163464ebd5Sriastradh      bytesPerRow = (width + 7) >> 3;
12173464ebd5Sriastradh      flipBytes = unpack->LsbFirst;
12183464ebd5Sriastradh      swap2 = swap4 = GL_FALSE;
12193464ebd5Sriastradh      compsPerRow = 0;
12203464ebd5Sriastradh   }
12213464ebd5Sriastradh   else {
12223464ebd5Sriastradh      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
12233464ebd5Sriastradh      GLint components = _mesa_components_in_format(format);
12243464ebd5Sriastradh      GLint bytesPerComp;
12253464ebd5Sriastradh
12263464ebd5Sriastradh      if (_mesa_type_is_packed(type))
12273464ebd5Sriastradh          components = 1;
12283464ebd5Sriastradh
12293464ebd5Sriastradh      if (bytesPerPixel <= 0 || components <= 0)
12303464ebd5Sriastradh         return NULL;   /* bad format or type.  generate error later */
12313464ebd5Sriastradh      bytesPerRow = bytesPerPixel * width;
12323464ebd5Sriastradh      bytesPerComp = bytesPerPixel / components;
12333464ebd5Sriastradh      flipBytes = GL_FALSE;
12343464ebd5Sriastradh      swap2 = (bytesPerComp == 2) && unpack->SwapBytes;
12353464ebd5Sriastradh      swap4 = (bytesPerComp == 4) && unpack->SwapBytes;
12363464ebd5Sriastradh      compsPerRow = components * width;
12373464ebd5Sriastradh      assert(compsPerRow >= width);
12383464ebd5Sriastradh   }
12393464ebd5Sriastradh
12403464ebd5Sriastradh   {
12413464ebd5Sriastradh      GLubyte *destBuffer
1242af69d88dSmrg         = malloc(bytesPerRow * height * depth);
12433464ebd5Sriastradh      GLubyte *dst;
12443464ebd5Sriastradh      GLint img, row;
12453464ebd5Sriastradh      if (!destBuffer)
12463464ebd5Sriastradh         return NULL;   /* generate GL_OUT_OF_MEMORY later */
12473464ebd5Sriastradh
12483464ebd5Sriastradh      dst = destBuffer;
12493464ebd5Sriastradh      for (img = 0; img < depth; img++) {
12503464ebd5Sriastradh         for (row = 0; row < height; row++) {
12513464ebd5Sriastradh            const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels,
12523464ebd5Sriastradh                               width, height, format, type, img, row, 0);
12533464ebd5Sriastradh
12543464ebd5Sriastradh            if ((type == GL_BITMAP) && (unpack->SkipPixels & 0x7)) {
12553464ebd5Sriastradh               GLint i;
12563464ebd5Sriastradh               flipBytes = GL_FALSE;
12573464ebd5Sriastradh               if (unpack->LsbFirst) {
12583464ebd5Sriastradh                  GLubyte srcMask = 1 << (unpack->SkipPixels & 0x7);
12593464ebd5Sriastradh                  GLubyte dstMask = 128;
12603464ebd5Sriastradh                  const GLubyte *s = src;
12613464ebd5Sriastradh                  GLubyte *d = dst;
12623464ebd5Sriastradh                  *d = 0;
12633464ebd5Sriastradh                  for (i = 0; i < width; i++) {
12643464ebd5Sriastradh                     if (*s & srcMask) {
12653464ebd5Sriastradh                        *d |= dstMask;
12663464ebd5Sriastradh                     }
12673464ebd5Sriastradh                     if (srcMask == 128) {
12683464ebd5Sriastradh                        srcMask = 1;
12693464ebd5Sriastradh                        s++;
12703464ebd5Sriastradh                     }
12713464ebd5Sriastradh                     else {
12723464ebd5Sriastradh                        srcMask = srcMask << 1;
12733464ebd5Sriastradh                     }
12743464ebd5Sriastradh                     if (dstMask == 1) {
12753464ebd5Sriastradh                        dstMask = 128;
12763464ebd5Sriastradh                        d++;
12773464ebd5Sriastradh                        *d = 0;
12783464ebd5Sriastradh                     }
12793464ebd5Sriastradh                     else {
12803464ebd5Sriastradh                        dstMask = dstMask >> 1;
12813464ebd5Sriastradh                     }
12823464ebd5Sriastradh                  }
12833464ebd5Sriastradh               }
12843464ebd5Sriastradh               else {
12853464ebd5Sriastradh                  GLubyte srcMask = 128 >> (unpack->SkipPixels & 0x7);
12863464ebd5Sriastradh                  GLubyte dstMask = 128;
12873464ebd5Sriastradh                  const GLubyte *s = src;
12883464ebd5Sriastradh                  GLubyte *d = dst;
12893464ebd5Sriastradh                  *d = 0;
12903464ebd5Sriastradh                  for (i = 0; i < width; i++) {
12913464ebd5Sriastradh                     if (*s & srcMask) {
12923464ebd5Sriastradh                        *d |= dstMask;
12933464ebd5Sriastradh                     }
12943464ebd5Sriastradh                     if (srcMask == 1) {
12953464ebd5Sriastradh                        srcMask = 128;
12963464ebd5Sriastradh                        s++;
12973464ebd5Sriastradh                     }
12983464ebd5Sriastradh                     else {
12993464ebd5Sriastradh                        srcMask = srcMask >> 1;
13003464ebd5Sriastradh                     }
13013464ebd5Sriastradh                     if (dstMask == 1) {
13023464ebd5Sriastradh                        dstMask = 128;
13033464ebd5Sriastradh                        d++;
13043464ebd5Sriastradh                        *d = 0;
13053464ebd5Sriastradh                     }
13063464ebd5Sriastradh                     else {
13073464ebd5Sriastradh                        dstMask = dstMask >> 1;
13083464ebd5Sriastradh                     }
13093464ebd5Sriastradh                  }
13103464ebd5Sriastradh               }
13113464ebd5Sriastradh            }
13123464ebd5Sriastradh            else {
13133464ebd5Sriastradh               memcpy(dst, src, bytesPerRow);
13143464ebd5Sriastradh            }
13153464ebd5Sriastradh
13163464ebd5Sriastradh            /* byte flipping/swapping */
13173464ebd5Sriastradh            if (flipBytes) {
13183464ebd5Sriastradh               flip_bytes((GLubyte *) dst, bytesPerRow);
13193464ebd5Sriastradh            }
13203464ebd5Sriastradh            else if (swap2) {
13213464ebd5Sriastradh               _mesa_swap2((GLushort*) dst, compsPerRow);
13223464ebd5Sriastradh            }
13233464ebd5Sriastradh            else if (swap4) {
13243464ebd5Sriastradh               _mesa_swap4((GLuint*) dst, compsPerRow);
13253464ebd5Sriastradh            }
13263464ebd5Sriastradh            dst += bytesPerRow;
13273464ebd5Sriastradh         }
13283464ebd5Sriastradh      }
13293464ebd5Sriastradh      return destBuffer;
13303464ebd5Sriastradh   }
13313464ebd5Sriastradh}
13323464ebd5Sriastradh
1333af69d88dSmrgvoid
133401e04c3fSmrg_mesa_pack_luminance_from_rgba_float(GLuint n, GLfloat rgba[][4],
133501e04c3fSmrg                                     GLvoid *dstAddr, GLenum dst_format,
133601e04c3fSmrg                                     GLbitfield transferOps)
1337af69d88dSmrg{
133801e04c3fSmrg   int i;
133901e04c3fSmrg   GLfloat *dst = (GLfloat *) dstAddr;
1340af69d88dSmrg
134101e04c3fSmrg   switch (dst_format) {
1342af69d88dSmrg   case GL_LUMINANCE:
134301e04c3fSmrg      if (transferOps & IMAGE_CLAMP_BIT) {
134401e04c3fSmrg         for (i = 0; i < n; i++) {
134501e04c3fSmrg            GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
134601e04c3fSmrg            dst[i] = CLAMP(sum, 0.0F, 1.0F);
134701e04c3fSmrg         }
134801e04c3fSmrg      } else {
134901e04c3fSmrg         for (i = 0; i < n; i++) {
135001e04c3fSmrg            dst[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
135101e04c3fSmrg         }
1352af69d88dSmrg      }
135301e04c3fSmrg      return;
1354af69d88dSmrg   case GL_LUMINANCE_ALPHA:
135501e04c3fSmrg      if (transferOps & IMAGE_CLAMP_BIT) {
135601e04c3fSmrg         for (i = 0; i < n; i++) {
135701e04c3fSmrg            GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
135801e04c3fSmrg            dst[2*i] = CLAMP(sum, 0.0F, 1.0F);
135901e04c3fSmrg            dst[2*i+1] = rgba[i][ACOMP];
136001e04c3fSmrg         }
136101e04c3fSmrg      } else {
136201e04c3fSmrg         for (i = 0; i < n; i++) {
136301e04c3fSmrg            dst[2*i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
136401e04c3fSmrg            dst[2*i+1] = rgba[i][ACOMP];
136501e04c3fSmrg         }
1366af69d88dSmrg      }
136701e04c3fSmrg      return;
1368af69d88dSmrg   default:
136901e04c3fSmrg      assert(!"Unsupported format");
137001e04c3fSmrg   }
137101e04c3fSmrg}
137201e04c3fSmrg
137301e04c3fSmrgstatic int32_t
137401e04c3fSmrgclamp_sint64_to_sint32(int64_t src)
137501e04c3fSmrg{
137601e04c3fSmrg   return CLAMP(src, INT32_MIN, INT32_MAX);
137701e04c3fSmrg}
137801e04c3fSmrg
137901e04c3fSmrgstatic int32_t
138001e04c3fSmrgclamp_sint64_to_uint32(int64_t src)
138101e04c3fSmrg{
138201e04c3fSmrg   return CLAMP(src, 0, UINT32_MAX);
138301e04c3fSmrg}
138401e04c3fSmrg
138501e04c3fSmrgstatic int32_t
138601e04c3fSmrgclamp_uint64_to_uint32(uint64_t src)
138701e04c3fSmrg{
138801e04c3fSmrg   return MIN2(src, UINT32_MAX);
138901e04c3fSmrg}
139001e04c3fSmrg
139101e04c3fSmrgstatic int32_t
139201e04c3fSmrgclamp_uint64_to_sint32(uint64_t src)
139301e04c3fSmrg{
139401e04c3fSmrg   return MIN2(src, INT32_MAX);
139501e04c3fSmrg}
139601e04c3fSmrg
139701e04c3fSmrgstatic int32_t
139801e04c3fSmrgconvert_integer_luminance64(int64_t src64, int bits,
139901e04c3fSmrg                            bool dst_is_signed, bool src_is_signed)
140001e04c3fSmrg{
140101e04c3fSmrg   int32_t src32;
140201e04c3fSmrg
140301e04c3fSmrg   /* Clamp Luminance value from 64-bit to 32-bit. Consider if we need
140401e04c3fSmrg    * any signed<->unsigned conversion too.
140501e04c3fSmrg    */
140601e04c3fSmrg   if (src_is_signed && dst_is_signed)
140701e04c3fSmrg      src32 = clamp_sint64_to_sint32(src64);
140801e04c3fSmrg   else if (src_is_signed && !dst_is_signed)
140901e04c3fSmrg      src32 = clamp_sint64_to_uint32(src64);
141001e04c3fSmrg   else if (!src_is_signed && dst_is_signed)
141101e04c3fSmrg      src32 = clamp_uint64_to_sint32(src64);
141201e04c3fSmrg   else
141301e04c3fSmrg      src32 = clamp_uint64_to_uint32(src64);
141401e04c3fSmrg
141501e04c3fSmrg   /* If the dst type is < 32-bit, we need an extra clamp */
141601e04c3fSmrg   if (bits == 32) {
141701e04c3fSmrg      return src32;
141801e04c3fSmrg   } else {
141901e04c3fSmrg      if (dst_is_signed)
142001e04c3fSmrg         return _mesa_signed_to_signed(src32, bits);
142101e04c3fSmrg      else
142201e04c3fSmrg         return _mesa_unsigned_to_unsigned(src32, bits);
1423af69d88dSmrg   }
1424af69d88dSmrg}
1425af69d88dSmrg
142601e04c3fSmrgstatic int32_t
142701e04c3fSmrgconvert_integer(int32_t src, int bits, bool dst_is_signed, bool src_is_signed)
142801e04c3fSmrg{
142901e04c3fSmrg   if (src_is_signed && dst_is_signed)
143001e04c3fSmrg      return _mesa_signed_to_signed(src, bits);
143101e04c3fSmrg   else if (src_is_signed && !dst_is_signed)
143201e04c3fSmrg      return _mesa_signed_to_unsigned(src, bits);
143301e04c3fSmrg   else if (!src_is_signed && dst_is_signed)
143401e04c3fSmrg      return _mesa_unsigned_to_signed(src, bits);
143501e04c3fSmrg   else
143601e04c3fSmrg      return _mesa_unsigned_to_unsigned(src, bits);
143701e04c3fSmrg}
1438af69d88dSmrg
1439af69d88dSmrgvoid
144001e04c3fSmrg_mesa_pack_luminance_from_rgba_integer(GLuint n,
144101e04c3fSmrg                                       GLuint rgba[][4], bool rgba_is_signed,
144201e04c3fSmrg                                       GLvoid *dstAddr,
144301e04c3fSmrg                                       GLenum dst_format,
144401e04c3fSmrg                                       GLenum dst_type)
1445af69d88dSmrg{
144601e04c3fSmrg   int i;
144701e04c3fSmrg   int64_t lum64;
144801e04c3fSmrg   int32_t lum32, alpha;
144901e04c3fSmrg   bool dst_is_signed;
145001e04c3fSmrg   int dst_bits;
145101e04c3fSmrg
145201e04c3fSmrg   assert(dst_format == GL_LUMINANCE_INTEGER_EXT ||
145301e04c3fSmrg          dst_format == GL_LUMINANCE_ALPHA_INTEGER_EXT);
145401e04c3fSmrg
145501e04c3fSmrg   /* We first compute luminance values as a 64-bit addition of the
145601e04c3fSmrg    * 32-bit R,G,B components, then we clamp the result to the dst type size.
145701e04c3fSmrg    *
145801e04c3fSmrg    * Notice that this operation involves casting the 32-bit R,G,B components
145901e04c3fSmrg    * to 64-bit before the addition. Since rgba is defined as a GLuint array
146001e04c3fSmrg    * we need to be careful when rgba packs signed data and make sure
146101e04c3fSmrg    * that we cast to a 32-bit signed integer values before casting them to
146201e04c3fSmrg    * 64-bit signed integers.
146301e04c3fSmrg    */
146401e04c3fSmrg   dst_is_signed = (dst_type == GL_BYTE || dst_type == GL_SHORT ||
146501e04c3fSmrg                    dst_type == GL_INT);
1466af69d88dSmrg
146701e04c3fSmrg   dst_bits = _mesa_sizeof_type(dst_type) * 8;
146801e04c3fSmrg   assert(dst_bits > 0);
146901e04c3fSmrg
147001e04c3fSmrg   switch (dst_format) {
147101e04c3fSmrg   case GL_LUMINANCE_INTEGER_EXT:
1472af69d88dSmrg      for (i = 0; i < n; i++) {
147301e04c3fSmrg         if (!rgba_is_signed) {
147401e04c3fSmrg            lum64 = (uint64_t) rgba[i][RCOMP] +
147501e04c3fSmrg                    (uint64_t) rgba[i][GCOMP] +
147601e04c3fSmrg                    (uint64_t) rgba[i][BCOMP];
147701e04c3fSmrg         } else {
147801e04c3fSmrg            lum64 = (int64_t) ((int32_t) rgba[i][RCOMP]) +
147901e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][GCOMP]) +
148001e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][BCOMP]);
148101e04c3fSmrg         }
148201e04c3fSmrg         lum32 = convert_integer_luminance64(lum64, dst_bits,
148301e04c3fSmrg                                             dst_is_signed, rgba_is_signed);
148401e04c3fSmrg         switch (dst_type) {
148501e04c3fSmrg         case GL_BYTE:
148601e04c3fSmrg         case GL_UNSIGNED_BYTE: {
148701e04c3fSmrg            GLbyte *dst = (GLbyte *) dstAddr;
148801e04c3fSmrg            dst[i] = lum32;
148901e04c3fSmrg            break;
149001e04c3fSmrg         }
149101e04c3fSmrg         case GL_SHORT:
149201e04c3fSmrg         case GL_UNSIGNED_SHORT: {
149301e04c3fSmrg            GLshort *dst = (GLshort *) dstAddr;
149401e04c3fSmrg            dst[i] = lum32;
149501e04c3fSmrg            break;
149601e04c3fSmrg         }
149701e04c3fSmrg         case GL_INT:
149801e04c3fSmrg         case GL_UNSIGNED_INT: {
149901e04c3fSmrg            GLint *dst = (GLint *) dstAddr;
150001e04c3fSmrg            dst[i] = lum32;
150101e04c3fSmrg            break;
150201e04c3fSmrg         }
150301e04c3fSmrg         }
1504af69d88dSmrg      }
150501e04c3fSmrg      return;
150601e04c3fSmrg   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
1507af69d88dSmrg      for (i = 0; i < n; i++) {
150801e04c3fSmrg         if (!rgba_is_signed) {
150901e04c3fSmrg            lum64 = (uint64_t) rgba[i][RCOMP] +
151001e04c3fSmrg                    (uint64_t) rgba[i][GCOMP] +
151101e04c3fSmrg                    (uint64_t) rgba[i][BCOMP];
151201e04c3fSmrg         } else {
151301e04c3fSmrg            lum64 = (int64_t) ((int32_t) rgba[i][RCOMP]) +
151401e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][GCOMP]) +
151501e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][BCOMP]);
151601e04c3fSmrg         }
151701e04c3fSmrg         lum32 = convert_integer_luminance64(lum64, dst_bits,
151801e04c3fSmrg                                             dst_is_signed, rgba_is_signed);
151901e04c3fSmrg         alpha = convert_integer(rgba[i][ACOMP], dst_bits,
152001e04c3fSmrg                                 dst_is_signed, rgba_is_signed);
152101e04c3fSmrg         switch (dst_type) {
152201e04c3fSmrg         case GL_BYTE:
152301e04c3fSmrg         case GL_UNSIGNED_BYTE: {
152401e04c3fSmrg            GLbyte *dst = (GLbyte *) dstAddr;
152501e04c3fSmrg            dst[2*i] = lum32;
152601e04c3fSmrg            dst[2*i+1] = alpha;
152701e04c3fSmrg            break;
152801e04c3fSmrg         }
152901e04c3fSmrg         case GL_SHORT:
153001e04c3fSmrg         case GL_UNSIGNED_SHORT: {
153101e04c3fSmrg            GLshort *dst = (GLshort *) dstAddr;
153201e04c3fSmrg            dst[i] = lum32;
153301e04c3fSmrg            dst[2*i+1] = alpha;
153401e04c3fSmrg            break;
153501e04c3fSmrg         }
153601e04c3fSmrg         case GL_INT:
153701e04c3fSmrg         case GL_UNSIGNED_INT: {
153801e04c3fSmrg            GLint *dst = (GLint *) dstAddr;
153901e04c3fSmrg            dst[i] = lum32;
154001e04c3fSmrg            dst[2*i+1] = alpha;
154101e04c3fSmrg            break;
154201e04c3fSmrg         }
154301e04c3fSmrg         }
1544af69d88dSmrg      }
154501e04c3fSmrg      return;
1546af69d88dSmrg   }
1547af69d88dSmrg}
1548af69d88dSmrg
154901e04c3fSmrgGLfloat *
155001e04c3fSmrg_mesa_unpack_color_index_to_rgba_float(struct gl_context *ctx, GLuint dims,
155101e04c3fSmrg                                       const void *src, GLenum srcFormat, GLenum srcType,
155201e04c3fSmrg                                       int srcWidth, int srcHeight, int srcDepth,
155301e04c3fSmrg                                       const struct gl_pixelstore_attrib *srcPacking,
155401e04c3fSmrg                                       GLbitfield transferOps)
155501e04c3fSmrg{
155601e04c3fSmrg   int count, img;
155701e04c3fSmrg   GLuint *indexes;
155801e04c3fSmrg   GLfloat *rgba, *dstPtr;
155901e04c3fSmrg
156001e04c3fSmrg   count = srcWidth * srcHeight;
156101e04c3fSmrg   indexes = malloc(count * sizeof(GLuint));
156201e04c3fSmrg   if (!indexes) {
156301e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
156401e04c3fSmrg      return NULL;
156501e04c3fSmrg   }
156601e04c3fSmrg
156701e04c3fSmrg   rgba = malloc(4 * count * srcDepth * sizeof(GLfloat));
156801e04c3fSmrg   if (!rgba) {
156901e04c3fSmrg      free(indexes);
157001e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
157101e04c3fSmrg      return NULL;
157201e04c3fSmrg   }
157301e04c3fSmrg
157401e04c3fSmrg   /* Convert indexes to RGBA float */
157501e04c3fSmrg   dstPtr = rgba;
157601e04c3fSmrg   for (img = 0; img < srcDepth; img++) {
157701e04c3fSmrg      const GLubyte *srcPtr =
157801e04c3fSmrg         (const GLubyte *) _mesa_image_address(dims, srcPacking, src,
157901e04c3fSmrg                                               srcWidth, srcHeight,
158001e04c3fSmrg                                               srcFormat, srcType,
158101e04c3fSmrg                                               img, 0, 0);
158201e04c3fSmrg
158301e04c3fSmrg      extract_uint_indexes(count, indexes, srcFormat, srcType, srcPtr, srcPacking);
158401e04c3fSmrg
158501e04c3fSmrg      if (transferOps & IMAGE_SHIFT_OFFSET_BIT)
158601e04c3fSmrg         _mesa_shift_and_offset_ci(ctx, count, indexes);
158701e04c3fSmrg
158801e04c3fSmrg      _mesa_map_ci_to_rgba(ctx, count, indexes, (float (*)[4])dstPtr);
1589af69d88dSmrg
159001e04c3fSmrg      /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting
159101e04c3fSmrg       * with color indexes.
159201e04c3fSmrg       */
159301e04c3fSmrg      transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT);
159401e04c3fSmrg      _mesa_apply_rgba_transfer_ops(ctx, transferOps, count, (float (*)[4])dstPtr);
159501e04c3fSmrg
159601e04c3fSmrg      dstPtr += srcHeight * srcWidth * 4;
159701e04c3fSmrg   }
159801e04c3fSmrg
159901e04c3fSmrg   free(indexes);
160001e04c3fSmrg
160101e04c3fSmrg   return rgba;
160201e04c3fSmrg}
160301e04c3fSmrg
160401e04c3fSmrgGLubyte *
160501e04c3fSmrg_mesa_unpack_color_index_to_rgba_ubyte(struct gl_context *ctx, GLuint dims,
160601e04c3fSmrg                                       const void *src, GLenum srcFormat, GLenum srcType,
160701e04c3fSmrg                                       int srcWidth, int srcHeight, int srcDepth,
160801e04c3fSmrg                                       const struct gl_pixelstore_attrib *srcPacking,
160901e04c3fSmrg                                       GLbitfield transferOps)
161001e04c3fSmrg{
161101e04c3fSmrg   GLfloat *rgba;
161201e04c3fSmrg   GLubyte *dst;
161301e04c3fSmrg   int count, i;
161401e04c3fSmrg
161501e04c3fSmrg   transferOps |= IMAGE_CLAMP_BIT;
161601e04c3fSmrg   rgba = _mesa_unpack_color_index_to_rgba_float(ctx, dims,
161701e04c3fSmrg                                                 src, srcFormat, srcType,
161801e04c3fSmrg                                                 srcWidth, srcHeight, srcDepth,
161901e04c3fSmrg                                                 srcPacking, transferOps);
162001e04c3fSmrg
162101e04c3fSmrg   count = srcWidth * srcHeight * srcDepth;
162201e04c3fSmrg   dst = malloc(count * 4 * sizeof(GLubyte));
162301e04c3fSmrg   for (i = 0; i < count; i++) {
162401e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 0], rgba[i * 4 + 0]);
162501e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 1], rgba[i * 4 + 1]);
162601e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 2], rgba[i * 4 + 2]);
162701e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 3], rgba[i * 4 + 3]);
162801e04c3fSmrg   }
162901e04c3fSmrg
163001e04c3fSmrg   free(rgba);
163101e04c3fSmrg
163201e04c3fSmrg   return dst;
163301e04c3fSmrg}
1634