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"
497ec681f3Smrg
50af69d88dSmrg#include "macros.h"
513464ebd5Sriastradh#include "mtypes.h"
523464ebd5Sriastradh#include "pack.h"
533464ebd5Sriastradh#include "pixeltransfer.h"
547ec681f3Smrg
55af69d88dSmrg#include "glformats.h"
5601e04c3fSmrg#include "format_utils.h"
5701e04c3fSmrg#include "format_pack.h"
587ec681f3Smrg#include "format_unpack.h"
597ec681f3Smrg#include "util/format/u_format.h"
603464ebd5Sriastradh
613464ebd5Sriastradh/**
623464ebd5Sriastradh * Flip the 8 bits in each byte of the given array.
633464ebd5Sriastradh *
643464ebd5Sriastradh * \param p array.
653464ebd5Sriastradh * \param n number of bytes.
663464ebd5Sriastradh *
673464ebd5Sriastradh * \todo try this trick to flip bytes someday:
683464ebd5Sriastradh * \code
693464ebd5Sriastradh *  v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555);
703464ebd5Sriastradh *  v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333);
713464ebd5Sriastradh *  v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f);
723464ebd5Sriastradh * \endcode
733464ebd5Sriastradh */
743464ebd5Sriastradhstatic void
753464ebd5Sriastradhflip_bytes( GLubyte *p, GLuint n )
763464ebd5Sriastradh{
773464ebd5Sriastradh   GLuint i, a, b;
783464ebd5Sriastradh   for (i = 0; i < n; i++) {
793464ebd5Sriastradh      b = (GLuint) p[i];        /* words are often faster than bytes */
803464ebd5Sriastradh      a = ((b & 0x01) << 7) |
813464ebd5Sriastradh	  ((b & 0x02) << 5) |
823464ebd5Sriastradh	  ((b & 0x04) << 3) |
833464ebd5Sriastradh	  ((b & 0x08) << 1) |
843464ebd5Sriastradh	  ((b & 0x10) >> 1) |
853464ebd5Sriastradh	  ((b & 0x20) >> 3) |
863464ebd5Sriastradh	  ((b & 0x40) >> 5) |
873464ebd5Sriastradh	  ((b & 0x80) >> 7);
883464ebd5Sriastradh      p[i] = (GLubyte) a;
893464ebd5Sriastradh   }
903464ebd5Sriastradh}
913464ebd5Sriastradh
923464ebd5Sriastradh
933464ebd5Sriastradh
943464ebd5Sriastradh/*
953464ebd5Sriastradh * Unpack a 32x32 pixel polygon stipple from user memory using the
963464ebd5Sriastradh * current pixel unpack settings.
973464ebd5Sriastradh */
983464ebd5Sriastradhvoid
993464ebd5Sriastradh_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32],
1003464ebd5Sriastradh                              const struct gl_pixelstore_attrib *unpacking )
1013464ebd5Sriastradh{
10201e04c3fSmrg   GLubyte *ptrn = (GLubyte *) _mesa_unpack_image(2, 32, 32, 1, GL_COLOR_INDEX,
10301e04c3fSmrg                                                  GL_BITMAP, pattern, unpacking);
1043464ebd5Sriastradh   if (ptrn) {
1053464ebd5Sriastradh      /* Convert pattern from GLubytes to GLuints and handle big/little
1063464ebd5Sriastradh       * endian differences
1073464ebd5Sriastradh       */
1083464ebd5Sriastradh      GLubyte *p = ptrn;
1093464ebd5Sriastradh      GLint i;
1103464ebd5Sriastradh      for (i = 0; i < 32; i++) {
1113464ebd5Sriastradh         dest[i] = (p[0] << 24)
1123464ebd5Sriastradh                 | (p[1] << 16)
1133464ebd5Sriastradh                 | (p[2] <<  8)
1143464ebd5Sriastradh                 | (p[3]      );
1153464ebd5Sriastradh         p += 4;
1163464ebd5Sriastradh      }
1173464ebd5Sriastradh      free(ptrn);
1183464ebd5Sriastradh   }
1193464ebd5Sriastradh}
1203464ebd5Sriastradh
1213464ebd5Sriastradh
1223464ebd5Sriastradh/*
1233464ebd5Sriastradh * Pack polygon stipple into user memory given current pixel packing
1243464ebd5Sriastradh * settings.
1253464ebd5Sriastradh */
1263464ebd5Sriastradhvoid
1273464ebd5Sriastradh_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest,
1283464ebd5Sriastradh                            const struct gl_pixelstore_attrib *packing )
1293464ebd5Sriastradh{
1303464ebd5Sriastradh   /* Convert pattern from GLuints to GLubytes to handle big/little
1313464ebd5Sriastradh    * endian differences.
1323464ebd5Sriastradh    */
1333464ebd5Sriastradh   GLubyte ptrn[32*4];
1343464ebd5Sriastradh   GLint i;
1353464ebd5Sriastradh   for (i = 0; i < 32; i++) {
1363464ebd5Sriastradh      ptrn[i * 4 + 0] = (GLubyte) ((pattern[i] >> 24) & 0xff);
1373464ebd5Sriastradh      ptrn[i * 4 + 1] = (GLubyte) ((pattern[i] >> 16) & 0xff);
1383464ebd5Sriastradh      ptrn[i * 4 + 2] = (GLubyte) ((pattern[i] >> 8 ) & 0xff);
1393464ebd5Sriastradh      ptrn[i * 4 + 3] = (GLubyte) ((pattern[i]      ) & 0xff);
1403464ebd5Sriastradh   }
1413464ebd5Sriastradh
1423464ebd5Sriastradh   _mesa_pack_bitmap(32, 32, ptrn, dest, packing);
1433464ebd5Sriastradh}
1443464ebd5Sriastradh
1453464ebd5Sriastradh
1463464ebd5Sriastradh/*
1473464ebd5Sriastradh * Pack bitmap data.
1483464ebd5Sriastradh */
1493464ebd5Sriastradhvoid
1503464ebd5Sriastradh_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
1513464ebd5Sriastradh                   GLubyte *dest, const struct gl_pixelstore_attrib *packing )
1523464ebd5Sriastradh{
1533464ebd5Sriastradh   GLint row, width_in_bytes;
1543464ebd5Sriastradh   const GLubyte *src;
1553464ebd5Sriastradh
1563464ebd5Sriastradh   if (!source)
1573464ebd5Sriastradh      return;
1583464ebd5Sriastradh
15901e04c3fSmrg   width_in_bytes = DIV_ROUND_UP( width, 8 );
1603464ebd5Sriastradh   src = source;
1613464ebd5Sriastradh   for (row = 0; row < height; row++) {
1623464ebd5Sriastradh      GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest,
1633464ebd5Sriastradh                       width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
1643464ebd5Sriastradh      if (!dst)
1653464ebd5Sriastradh         return;
1663464ebd5Sriastradh
1673464ebd5Sriastradh      if ((packing->SkipPixels & 7) == 0) {
1683464ebd5Sriastradh         memcpy( dst, src, width_in_bytes );
1693464ebd5Sriastradh         if (packing->LsbFirst) {
1703464ebd5Sriastradh            flip_bytes( dst, width_in_bytes );
1713464ebd5Sriastradh         }
1723464ebd5Sriastradh      }
1733464ebd5Sriastradh      else {
1743464ebd5Sriastradh         /* handling SkipPixels is a bit tricky (no pun intended!) */
1753464ebd5Sriastradh         GLint i;
1763464ebd5Sriastradh         if (packing->LsbFirst) {
1773464ebd5Sriastradh            GLubyte srcMask = 128;
1783464ebd5Sriastradh            GLubyte dstMask = 1 << (packing->SkipPixels & 0x7);
1793464ebd5Sriastradh            const GLubyte *s = src;
1803464ebd5Sriastradh            GLubyte *d = dst;
1813464ebd5Sriastradh            *d = 0;
1823464ebd5Sriastradh            for (i = 0; i < width; i++) {
1833464ebd5Sriastradh               if (*s & srcMask) {
1843464ebd5Sriastradh                  *d |= dstMask;
1853464ebd5Sriastradh               }
1863464ebd5Sriastradh               if (srcMask == 1) {
1873464ebd5Sriastradh                  srcMask = 128;
1883464ebd5Sriastradh                  s++;
1893464ebd5Sriastradh               }
1903464ebd5Sriastradh               else {
1913464ebd5Sriastradh                  srcMask = srcMask >> 1;
1923464ebd5Sriastradh               }
1933464ebd5Sriastradh               if (dstMask == 128) {
1943464ebd5Sriastradh                  dstMask = 1;
1953464ebd5Sriastradh                  d++;
1963464ebd5Sriastradh                  *d = 0;
1973464ebd5Sriastradh               }
1983464ebd5Sriastradh               else {
1993464ebd5Sriastradh                  dstMask = dstMask << 1;
2003464ebd5Sriastradh               }
2013464ebd5Sriastradh            }
2023464ebd5Sriastradh         }
2033464ebd5Sriastradh         else {
2043464ebd5Sriastradh            GLubyte srcMask = 128;
2053464ebd5Sriastradh            GLubyte dstMask = 128 >> (packing->SkipPixels & 0x7);
2063464ebd5Sriastradh            const GLubyte *s = src;
2073464ebd5Sriastradh            GLubyte *d = dst;
2083464ebd5Sriastradh            *d = 0;
2093464ebd5Sriastradh            for (i = 0; i < width; i++) {
2103464ebd5Sriastradh               if (*s & srcMask) {
2113464ebd5Sriastradh                  *d |= dstMask;
2123464ebd5Sriastradh               }
2133464ebd5Sriastradh               if (srcMask == 1) {
2143464ebd5Sriastradh                  srcMask = 128;
2153464ebd5Sriastradh                  s++;
2163464ebd5Sriastradh               }
2173464ebd5Sriastradh               else {
2183464ebd5Sriastradh                  srcMask = srcMask >> 1;
2193464ebd5Sriastradh               }
2203464ebd5Sriastradh               if (dstMask == 1) {
2213464ebd5Sriastradh                  dstMask = 128;
2223464ebd5Sriastradh                  d++;
2233464ebd5Sriastradh                  *d = 0;
2243464ebd5Sriastradh               }
2253464ebd5Sriastradh               else {
2263464ebd5Sriastradh                  dstMask = dstMask >> 1;
2273464ebd5Sriastradh               }
2283464ebd5Sriastradh            }
2293464ebd5Sriastradh         }
2303464ebd5Sriastradh      }
2313464ebd5Sriastradh      src += width_in_bytes;
2323464ebd5Sriastradh   }
2333464ebd5Sriastradh}
2343464ebd5Sriastradh
2353464ebd5Sriastradh
23601e04c3fSmrg#define SWAP2BYTE(VALUE)			\
23701e04c3fSmrg   {						\
23801e04c3fSmrg      GLubyte *bytes = (GLubyte *) &(VALUE);	\
23901e04c3fSmrg      GLubyte tmp = bytes[0];			\
24001e04c3fSmrg      bytes[0] = bytes[1];			\
24101e04c3fSmrg      bytes[1] = tmp;				\
2423464ebd5Sriastradh   }
2433464ebd5Sriastradh
24401e04c3fSmrg#define SWAP4BYTE(VALUE)			\
24501e04c3fSmrg   {						\
24601e04c3fSmrg      GLubyte *bytes = (GLubyte *) &(VALUE);	\
24701e04c3fSmrg      GLubyte tmp = bytes[0];			\
24801e04c3fSmrg      bytes[0] = bytes[3];			\
24901e04c3fSmrg      bytes[3] = tmp;				\
25001e04c3fSmrg      tmp = bytes[1];				\
25101e04c3fSmrg      bytes[1] = bytes[2];			\
25201e04c3fSmrg      bytes[2] = tmp;				\
2533464ebd5Sriastradh   }
254af69d88dSmrg
255af69d88dSmrg
256af69d88dSmrgstatic void
25701e04c3fSmrgextract_uint_indexes(GLuint n, GLuint indexes[],
25801e04c3fSmrg                     GLenum srcFormat, GLenum srcType, const GLvoid *src,
25901e04c3fSmrg                     const struct gl_pixelstore_attrib *unpack )
260af69d88dSmrg{
26101e04c3fSmrg   assert(srcFormat == GL_COLOR_INDEX || srcFormat == GL_STENCIL_INDEX);
262af69d88dSmrg
26301e04c3fSmrg   assert(srcType == GL_BITMAP ||
26401e04c3fSmrg          srcType == GL_UNSIGNED_BYTE ||
26501e04c3fSmrg          srcType == GL_BYTE ||
26601e04c3fSmrg          srcType == GL_UNSIGNED_SHORT ||
26701e04c3fSmrg          srcType == GL_SHORT ||
26801e04c3fSmrg          srcType == GL_UNSIGNED_INT ||
26901e04c3fSmrg          srcType == GL_INT ||
27001e04c3fSmrg          srcType == GL_UNSIGNED_INT_24_8_EXT ||
27101e04c3fSmrg          srcType == GL_HALF_FLOAT_ARB ||
27201e04c3fSmrg          srcType == GL_HALF_FLOAT_OES ||
27301e04c3fSmrg          srcType == GL_FLOAT ||
27401e04c3fSmrg          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
275af69d88dSmrg
27601e04c3fSmrg   switch (srcType) {
27701e04c3fSmrg      case GL_BITMAP:
27801e04c3fSmrg         {
27901e04c3fSmrg            GLubyte *ubsrc = (GLubyte *) src;
28001e04c3fSmrg            if (unpack->LsbFirst) {
28101e04c3fSmrg               GLubyte mask = 1 << (unpack->SkipPixels & 0x7);
28201e04c3fSmrg               GLuint i;
28301e04c3fSmrg               for (i = 0; i < n; i++) {
28401e04c3fSmrg                  indexes[i] = (*ubsrc & mask) ? 1 : 0;
28501e04c3fSmrg                  if (mask == 128) {
28601e04c3fSmrg                     mask = 1;
28701e04c3fSmrg                     ubsrc++;
28801e04c3fSmrg                  }
28901e04c3fSmrg                  else {
29001e04c3fSmrg                     mask = mask << 1;
29101e04c3fSmrg                  }
29201e04c3fSmrg               }
29301e04c3fSmrg            }
29401e04c3fSmrg            else {
29501e04c3fSmrg               GLubyte mask = 128 >> (unpack->SkipPixels & 0x7);
29601e04c3fSmrg               GLuint i;
29701e04c3fSmrg               for (i = 0; i < n; i++) {
29801e04c3fSmrg                  indexes[i] = (*ubsrc & mask) ? 1 : 0;
29901e04c3fSmrg                  if (mask == 1) {
30001e04c3fSmrg                     mask = 128;
30101e04c3fSmrg                     ubsrc++;
30201e04c3fSmrg                  }
30301e04c3fSmrg                  else {
30401e04c3fSmrg                     mask = mask >> 1;
30501e04c3fSmrg                  }
30601e04c3fSmrg               }
30701e04c3fSmrg            }
308af69d88dSmrg         }
30901e04c3fSmrg         break;
31001e04c3fSmrg      case GL_UNSIGNED_BYTE:
31101e04c3fSmrg         {
31201e04c3fSmrg            GLuint i;
31301e04c3fSmrg            const GLubyte *s = (const GLubyte *) src;
31401e04c3fSmrg            for (i = 0; i < n; i++)
31501e04c3fSmrg               indexes[i] = s[i];
316af69d88dSmrg         }
31701e04c3fSmrg         break;
31801e04c3fSmrg      case GL_BYTE:
31901e04c3fSmrg         {
32001e04c3fSmrg            GLuint i;
32101e04c3fSmrg            const GLbyte *s = (const GLbyte *) src;
32201e04c3fSmrg            for (i = 0; i < n; i++)
32301e04c3fSmrg               indexes[i] = s[i];
324af69d88dSmrg         }
32501e04c3fSmrg         break;
32601e04c3fSmrg      case GL_UNSIGNED_SHORT:
32701e04c3fSmrg         {
32801e04c3fSmrg            GLuint i;
32901e04c3fSmrg            const GLushort *s = (const GLushort *) src;
33001e04c3fSmrg            if (unpack->SwapBytes) {
33101e04c3fSmrg               for (i = 0; i < n; i++) {
33201e04c3fSmrg                  GLushort value = s[i];
33301e04c3fSmrg                  SWAP2BYTE(value);
33401e04c3fSmrg                  indexes[i] = value;
33501e04c3fSmrg               }
33601e04c3fSmrg            }
33701e04c3fSmrg            else {
33801e04c3fSmrg               for (i = 0; i < n; i++)
33901e04c3fSmrg                  indexes[i] = s[i];
34001e04c3fSmrg            }
341af69d88dSmrg         }
34201e04c3fSmrg         break;
34301e04c3fSmrg      case GL_SHORT:
34401e04c3fSmrg         {
34501e04c3fSmrg            GLuint i;
34601e04c3fSmrg            const GLshort *s = (const GLshort *) src;
34701e04c3fSmrg            if (unpack->SwapBytes) {
34801e04c3fSmrg               for (i = 0; i < n; i++) {
34901e04c3fSmrg                  GLshort value = s[i];
35001e04c3fSmrg                  SWAP2BYTE(value);
35101e04c3fSmrg                  indexes[i] = value;
35201e04c3fSmrg               }
35301e04c3fSmrg            }
35401e04c3fSmrg            else {
35501e04c3fSmrg               for (i = 0; i < n; i++)
35601e04c3fSmrg                  indexes[i] = s[i];
35701e04c3fSmrg            }
358af69d88dSmrg         }
35901e04c3fSmrg         break;
36001e04c3fSmrg      case GL_UNSIGNED_INT:
36101e04c3fSmrg         {
36201e04c3fSmrg            GLuint i;
36301e04c3fSmrg            const GLuint *s = (const GLuint *) src;
36401e04c3fSmrg            if (unpack->SwapBytes) {
3653464ebd5Sriastradh               for (i = 0; i < n; i++) {
36601e04c3fSmrg                  GLuint value = s[i];
36701e04c3fSmrg                  SWAP4BYTE(value);
36801e04c3fSmrg                  indexes[i] = value;
3693464ebd5Sriastradh               }
3703464ebd5Sriastradh            }
37101e04c3fSmrg            else {
37201e04c3fSmrg               for (i = 0; i < n; i++)
37301e04c3fSmrg                  indexes[i] = s[i];
3743464ebd5Sriastradh            }
3753464ebd5Sriastradh         }
37601e04c3fSmrg         break;
37701e04c3fSmrg      case GL_INT:
37801e04c3fSmrg         {
37901e04c3fSmrg            GLuint i;
38001e04c3fSmrg            const GLint *s = (const GLint *) src;
38101e04c3fSmrg            if (unpack->SwapBytes) {
38201e04c3fSmrg               for (i = 0; i < n; i++) {
38301e04c3fSmrg                  GLint value = s[i];
38401e04c3fSmrg                  SWAP4BYTE(value);
38501e04c3fSmrg                  indexes[i] = value;
38601e04c3fSmrg               }
38701e04c3fSmrg            }
38801e04c3fSmrg            else {
38901e04c3fSmrg               for (i = 0; i < n; i++)
39001e04c3fSmrg                  indexes[i] = s[i];
39101e04c3fSmrg            }
3923464ebd5Sriastradh         }
39301e04c3fSmrg         break;
39401e04c3fSmrg      case GL_FLOAT:
39501e04c3fSmrg         {
39601e04c3fSmrg            GLuint i;
39701e04c3fSmrg            const GLfloat *s = (const GLfloat *) src;
39801e04c3fSmrg            if (unpack->SwapBytes) {
39901e04c3fSmrg               for (i = 0; i < n; i++) {
40001e04c3fSmrg                  GLfloat value = s[i];
40101e04c3fSmrg                  SWAP4BYTE(value);
40201e04c3fSmrg                  indexes[i] = (GLuint) value;
40301e04c3fSmrg               }
40401e04c3fSmrg            }
40501e04c3fSmrg            else {
40601e04c3fSmrg               for (i = 0; i < n; i++)
40701e04c3fSmrg                  indexes[i] = (GLuint) s[i];
40801e04c3fSmrg            }
4093464ebd5Sriastradh         }
41001e04c3fSmrg         break;
41101e04c3fSmrg      case GL_HALF_FLOAT_ARB:
41201e04c3fSmrg      case GL_HALF_FLOAT_OES:
41301e04c3fSmrg         {
41401e04c3fSmrg            GLuint i;
41501e04c3fSmrg            const GLhalfARB *s = (const GLhalfARB *) src;
41601e04c3fSmrg            if (unpack->SwapBytes) {
41701e04c3fSmrg               for (i = 0; i < n; i++) {
41801e04c3fSmrg                  GLhalfARB value = s[i];
41901e04c3fSmrg                  SWAP2BYTE(value);
42001e04c3fSmrg                  indexes[i] = (GLuint) _mesa_half_to_float(value);
42101e04c3fSmrg               }
42201e04c3fSmrg            }
42301e04c3fSmrg            else {
42401e04c3fSmrg               for (i = 0; i < n; i++)
42501e04c3fSmrg                  indexes[i] = (GLuint) _mesa_half_to_float(s[i]);
42601e04c3fSmrg            }
4273464ebd5Sriastradh         }
42801e04c3fSmrg         break;
42901e04c3fSmrg      case GL_UNSIGNED_INT_24_8_EXT:
43001e04c3fSmrg         {
43101e04c3fSmrg            GLuint i;
43201e04c3fSmrg            const GLuint *s = (const GLuint *) src;
43301e04c3fSmrg            if (unpack->SwapBytes) {
43401e04c3fSmrg               for (i = 0; i < n; i++) {
43501e04c3fSmrg                  GLuint value = s[i];
43601e04c3fSmrg                  SWAP4BYTE(value);
43701e04c3fSmrg                  indexes[i] = value & 0xff;  /* lower 8 bits */
43801e04c3fSmrg               }
43901e04c3fSmrg            }
44001e04c3fSmrg            else {
44101e04c3fSmrg               for (i = 0; i < n; i++)
44201e04c3fSmrg                  indexes[i] = s[i] & 0xff;  /* lower 8 bits */
44301e04c3fSmrg            }
4443464ebd5Sriastradh         }
44501e04c3fSmrg         break;
44601e04c3fSmrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
44701e04c3fSmrg         {
44801e04c3fSmrg            GLuint i;
44901e04c3fSmrg            const GLuint *s = (const GLuint *) src;
45001e04c3fSmrg            if (unpack->SwapBytes) {
45101e04c3fSmrg               for (i = 0; i < n; i++) {
45201e04c3fSmrg                  GLuint value = s[i*2+1];
45301e04c3fSmrg                  SWAP4BYTE(value);
45401e04c3fSmrg                  indexes[i] = value & 0xff;  /* lower 8 bits */
45501e04c3fSmrg               }
45601e04c3fSmrg            }
45701e04c3fSmrg            else {
45801e04c3fSmrg               for (i = 0; i < n; i++)
45901e04c3fSmrg                  indexes[i] = s[i*2+1] & 0xff;  /* lower 8 bits */
46001e04c3fSmrg            }
46101e04c3fSmrg         }
46201e04c3fSmrg         break;
4633464ebd5Sriastradh
46401e04c3fSmrg      default:
46501e04c3fSmrg         unreachable("bad srcType in extract_uint_indexes");
46601e04c3fSmrg   }
4673464ebd5Sriastradh}
4683464ebd5Sriastradh
4693464ebd5Sriastradh
4703464ebd5Sriastradh/*
4713464ebd5Sriastradh * Unpack a row of stencil data from a client buffer according to
4723464ebd5Sriastradh * the pixel unpacking parameters.
4733464ebd5Sriastradh * This is (or will be) used by glDrawPixels
4743464ebd5Sriastradh *
4753464ebd5Sriastradh * Args:  ctx - the context
4763464ebd5Sriastradh *        n - number of pixels
4773464ebd5Sriastradh *        dstType - destination data type
4783464ebd5Sriastradh *        dest - destination array
4793464ebd5Sriastradh *        srcType - source pixel type
4803464ebd5Sriastradh *        source - source data pointer
4813464ebd5Sriastradh *        srcPacking - pixel unpacking parameters
4823464ebd5Sriastradh *        transferOps - apply offset/bias/lookup ops?
4833464ebd5Sriastradh */
4843464ebd5Sriastradhvoid
4853464ebd5Sriastradh_mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n,
4863464ebd5Sriastradh                           GLenum dstType, GLvoid *dest,
4873464ebd5Sriastradh                           GLenum srcType, const GLvoid *source,
4883464ebd5Sriastradh                           const struct gl_pixelstore_attrib *srcPacking,
4893464ebd5Sriastradh                           GLbitfield transferOps )
4903464ebd5Sriastradh{
49101e04c3fSmrg   assert(srcType == GL_BITMAP ||
4923464ebd5Sriastradh          srcType == GL_UNSIGNED_BYTE ||
4933464ebd5Sriastradh          srcType == GL_BYTE ||
4943464ebd5Sriastradh          srcType == GL_UNSIGNED_SHORT ||
4953464ebd5Sriastradh          srcType == GL_SHORT ||
4963464ebd5Sriastradh          srcType == GL_UNSIGNED_INT ||
4973464ebd5Sriastradh          srcType == GL_INT ||
4983464ebd5Sriastradh          srcType == GL_UNSIGNED_INT_24_8_EXT ||
4993464ebd5Sriastradh          srcType == GL_HALF_FLOAT_ARB ||
50001e04c3fSmrg          srcType == GL_HALF_FLOAT_OES ||
501af69d88dSmrg          srcType == GL_FLOAT ||
502af69d88dSmrg          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
5033464ebd5Sriastradh
50401e04c3fSmrg   assert(dstType == GL_UNSIGNED_BYTE ||
5053464ebd5Sriastradh          dstType == GL_UNSIGNED_SHORT ||
506af69d88dSmrg          dstType == GL_UNSIGNED_INT ||
507af69d88dSmrg          dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
5083464ebd5Sriastradh
5093464ebd5Sriastradh   /* only shift and offset apply to stencil */
5103464ebd5Sriastradh   transferOps &= IMAGE_SHIFT_OFFSET_BIT;
5113464ebd5Sriastradh
5123464ebd5Sriastradh   /*
5133464ebd5Sriastradh    * Try simple cases first
5143464ebd5Sriastradh    */
5153464ebd5Sriastradh   if (transferOps == 0 &&
5163464ebd5Sriastradh       !ctx->Pixel.MapStencilFlag &&
5173464ebd5Sriastradh       srcType == GL_UNSIGNED_BYTE &&
5183464ebd5Sriastradh       dstType == GL_UNSIGNED_BYTE) {
5193464ebd5Sriastradh      memcpy(dest, source, n * sizeof(GLubyte));
5203464ebd5Sriastradh   }
5213464ebd5Sriastradh   else if (transferOps == 0 &&
5223464ebd5Sriastradh            !ctx->Pixel.MapStencilFlag &&
5233464ebd5Sriastradh            srcType == GL_UNSIGNED_INT &&
5243464ebd5Sriastradh            dstType == GL_UNSIGNED_INT &&
5253464ebd5Sriastradh            !srcPacking->SwapBytes) {
5263464ebd5Sriastradh      memcpy(dest, source, n * sizeof(GLuint));
5273464ebd5Sriastradh   }
5283464ebd5Sriastradh   else {
5293464ebd5Sriastradh      /*
5303464ebd5Sriastradh       * general solution
5313464ebd5Sriastradh       */
532af69d88dSmrg      GLuint *indexes = malloc(n * sizeof(GLuint));
5333464ebd5Sriastradh
5343464ebd5Sriastradh      if (!indexes) {
5353464ebd5Sriastradh         _mesa_error(ctx, GL_OUT_OF_MEMORY, "stencil unpacking");
5363464ebd5Sriastradh         return;
5373464ebd5Sriastradh      }
5383464ebd5Sriastradh
5393464ebd5Sriastradh      extract_uint_indexes(n, indexes, GL_STENCIL_INDEX, srcType, source,
5403464ebd5Sriastradh                           srcPacking);
5413464ebd5Sriastradh
5423464ebd5Sriastradh      if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
5433464ebd5Sriastradh         /* shift and offset indexes */
5443464ebd5Sriastradh         _mesa_shift_and_offset_ci(ctx, n, indexes);
5453464ebd5Sriastradh      }
5463464ebd5Sriastradh
5473464ebd5Sriastradh      if (ctx->Pixel.MapStencilFlag) {
5483464ebd5Sriastradh         /* Apply stencil lookup table */
5493464ebd5Sriastradh         const GLuint mask = ctx->PixelMaps.StoS.Size - 1;
5503464ebd5Sriastradh         GLuint i;
5513464ebd5Sriastradh         for (i = 0; i < n; i++) {
5523464ebd5Sriastradh            indexes[i] = (GLuint)ctx->PixelMaps.StoS.Map[ indexes[i] & mask ];
5533464ebd5Sriastradh         }
5543464ebd5Sriastradh      }
5553464ebd5Sriastradh
5563464ebd5Sriastradh      /* convert to dest type */
5573464ebd5Sriastradh      switch (dstType) {
5583464ebd5Sriastradh         case GL_UNSIGNED_BYTE:
5593464ebd5Sriastradh            {
5603464ebd5Sriastradh               GLubyte *dst = (GLubyte *) dest;
5613464ebd5Sriastradh               GLuint i;
5623464ebd5Sriastradh               for (i = 0; i < n; i++) {
5633464ebd5Sriastradh                  dst[i] = (GLubyte) (indexes[i] & 0xff);
5643464ebd5Sriastradh               }
5653464ebd5Sriastradh            }
5663464ebd5Sriastradh            break;
5673464ebd5Sriastradh         case GL_UNSIGNED_SHORT:
5683464ebd5Sriastradh            {
5693464ebd5Sriastradh               GLuint *dst = (GLuint *) dest;
5703464ebd5Sriastradh               GLuint i;
5713464ebd5Sriastradh               for (i = 0; i < n; i++) {
5723464ebd5Sriastradh                  dst[i] = (GLushort) (indexes[i] & 0xffff);
5733464ebd5Sriastradh               }
5743464ebd5Sriastradh            }
5753464ebd5Sriastradh            break;
5763464ebd5Sriastradh         case GL_UNSIGNED_INT:
5773464ebd5Sriastradh            memcpy(dest, indexes, n * sizeof(GLuint));
5783464ebd5Sriastradh            break;
579af69d88dSmrg         case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
580af69d88dSmrg            {
581af69d88dSmrg               GLuint *dst = (GLuint *) dest;
582af69d88dSmrg               GLuint i;
583af69d88dSmrg               for (i = 0; i < n; i++) {
584af69d88dSmrg                  dst[i*2+1] = indexes[i] & 0xff; /* lower 8 bits */
585af69d88dSmrg               }
586af69d88dSmrg            }
587af69d88dSmrg            break;
5883464ebd5Sriastradh         default:
58901e04c3fSmrg            unreachable("bad dstType in _mesa_unpack_stencil_span");
5903464ebd5Sriastradh      }
5913464ebd5Sriastradh
5923464ebd5Sriastradh      free(indexes);
5933464ebd5Sriastradh   }
5943464ebd5Sriastradh}
5953464ebd5Sriastradh
5963464ebd5Sriastradh
5973464ebd5Sriastradhvoid
5983464ebd5Sriastradh_mesa_pack_stencil_span( struct gl_context *ctx, GLuint n,
599af69d88dSmrg                         GLenum dstType, GLvoid *dest, const GLubyte *source,
6003464ebd5Sriastradh                         const struct gl_pixelstore_attrib *dstPacking )
6013464ebd5Sriastradh{
602af69d88dSmrg   GLubyte *stencil = malloc(n * sizeof(GLubyte));
6033464ebd5Sriastradh
6043464ebd5Sriastradh   if (!stencil) {
6053464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "stencil packing");
6063464ebd5Sriastradh      return;
6073464ebd5Sriastradh   }
6083464ebd5Sriastradh
6093464ebd5Sriastradh   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
6103464ebd5Sriastradh       ctx->Pixel.MapStencilFlag) {
6113464ebd5Sriastradh      /* make a copy of input */
612af69d88dSmrg      memcpy(stencil, source, n * sizeof(GLubyte));
6133464ebd5Sriastradh      _mesa_apply_stencil_transfer_ops(ctx, n, stencil);
6143464ebd5Sriastradh      source = stencil;
6153464ebd5Sriastradh   }
6163464ebd5Sriastradh
6173464ebd5Sriastradh   switch (dstType) {
6183464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
619af69d88dSmrg      memcpy(dest, source, n);
6203464ebd5Sriastradh      break;
6213464ebd5Sriastradh   case GL_BYTE:
6223464ebd5Sriastradh      {
6233464ebd5Sriastradh         GLbyte *dst = (GLbyte *) dest;
6243464ebd5Sriastradh         GLuint i;
6253464ebd5Sriastradh         for (i=0;i<n;i++) {
6263464ebd5Sriastradh            dst[i] = (GLbyte) (source[i] & 0x7f);
6273464ebd5Sriastradh         }
6283464ebd5Sriastradh      }
6293464ebd5Sriastradh      break;
6303464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
6313464ebd5Sriastradh      {
6323464ebd5Sriastradh         GLushort *dst = (GLushort *) dest;
6333464ebd5Sriastradh         GLuint i;
6343464ebd5Sriastradh         for (i=0;i<n;i++) {
6353464ebd5Sriastradh            dst[i] = (GLushort) source[i];
6363464ebd5Sriastradh         }
6373464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6383464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
6393464ebd5Sriastradh         }
6403464ebd5Sriastradh      }
6413464ebd5Sriastradh      break;
6423464ebd5Sriastradh   case GL_SHORT:
6433464ebd5Sriastradh      {
6443464ebd5Sriastradh         GLshort *dst = (GLshort *) dest;
6453464ebd5Sriastradh         GLuint i;
6463464ebd5Sriastradh         for (i=0;i<n;i++) {
6473464ebd5Sriastradh            dst[i] = (GLshort) source[i];
6483464ebd5Sriastradh         }
6493464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6503464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
6513464ebd5Sriastradh         }
6523464ebd5Sriastradh      }
6533464ebd5Sriastradh      break;
6543464ebd5Sriastradh   case GL_UNSIGNED_INT:
6553464ebd5Sriastradh      {
6563464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
6573464ebd5Sriastradh         GLuint i;
6583464ebd5Sriastradh         for (i=0;i<n;i++) {
6593464ebd5Sriastradh            dst[i] = (GLuint) source[i];
6603464ebd5Sriastradh         }
6613464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6623464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
6633464ebd5Sriastradh         }
6643464ebd5Sriastradh      }
6653464ebd5Sriastradh      break;
6663464ebd5Sriastradh   case GL_INT:
6673464ebd5Sriastradh      {
6683464ebd5Sriastradh         GLint *dst = (GLint *) dest;
6693464ebd5Sriastradh         GLuint i;
6703464ebd5Sriastradh         for (i=0;i<n;i++) {
6713464ebd5Sriastradh            dst[i] = (GLint) source[i];
6723464ebd5Sriastradh         }
6733464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6743464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
6753464ebd5Sriastradh         }
6763464ebd5Sriastradh      }
6773464ebd5Sriastradh      break;
6783464ebd5Sriastradh   case GL_FLOAT:
6793464ebd5Sriastradh      {
6803464ebd5Sriastradh         GLfloat *dst = (GLfloat *) dest;
6813464ebd5Sriastradh         GLuint i;
6823464ebd5Sriastradh         for (i=0;i<n;i++) {
6833464ebd5Sriastradh            dst[i] = (GLfloat) source[i];
6843464ebd5Sriastradh         }
6853464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6863464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
6873464ebd5Sriastradh         }
6883464ebd5Sriastradh      }
6893464ebd5Sriastradh      break;
6903464ebd5Sriastradh   case GL_HALF_FLOAT_ARB:
69101e04c3fSmrg   case GL_HALF_FLOAT_OES:
6923464ebd5Sriastradh      {
6933464ebd5Sriastradh         GLhalfARB *dst = (GLhalfARB *) dest;
6943464ebd5Sriastradh         GLuint i;
6953464ebd5Sriastradh         for (i=0;i<n;i++) {
6963464ebd5Sriastradh            dst[i] = _mesa_float_to_half( (float) source[i] );
6973464ebd5Sriastradh         }
6983464ebd5Sriastradh         if (dstPacking->SwapBytes) {
6993464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
7003464ebd5Sriastradh         }
7013464ebd5Sriastradh      }
7023464ebd5Sriastradh      break;
7033464ebd5Sriastradh   case GL_BITMAP:
7043464ebd5Sriastradh      if (dstPacking->LsbFirst) {
7053464ebd5Sriastradh         GLubyte *dst = (GLubyte *) dest;
7063464ebd5Sriastradh         GLint shift = 0;
7073464ebd5Sriastradh         GLuint i;
7083464ebd5Sriastradh         for (i = 0; i < n; i++) {
7093464ebd5Sriastradh            if (shift == 0)
7103464ebd5Sriastradh               *dst = 0;
7113464ebd5Sriastradh            *dst |= ((source[i] != 0) << shift);
7123464ebd5Sriastradh            shift++;
7133464ebd5Sriastradh            if (shift == 8) {
7143464ebd5Sriastradh               shift = 0;
7153464ebd5Sriastradh               dst++;
7163464ebd5Sriastradh            }
7173464ebd5Sriastradh         }
7183464ebd5Sriastradh      }
7193464ebd5Sriastradh      else {
7203464ebd5Sriastradh         GLubyte *dst = (GLubyte *) dest;
7213464ebd5Sriastradh         GLint shift = 7;
7223464ebd5Sriastradh         GLuint i;
7233464ebd5Sriastradh         for (i = 0; i < n; i++) {
7243464ebd5Sriastradh            if (shift == 7)
7253464ebd5Sriastradh               *dst = 0;
7263464ebd5Sriastradh            *dst |= ((source[i] != 0) << shift);
7273464ebd5Sriastradh            shift--;
7283464ebd5Sriastradh            if (shift < 0) {
7293464ebd5Sriastradh               shift = 7;
7303464ebd5Sriastradh               dst++;
7313464ebd5Sriastradh            }
7323464ebd5Sriastradh         }
7333464ebd5Sriastradh      }
7343464ebd5Sriastradh      break;
7353464ebd5Sriastradh   default:
73601e04c3fSmrg      unreachable("bad type in _mesa_pack_index_span");
7373464ebd5Sriastradh   }
7383464ebd5Sriastradh
7393464ebd5Sriastradh   free(stencil);
7403464ebd5Sriastradh}
7413464ebd5Sriastradh
7423464ebd5Sriastradh#define DEPTH_VALUES(GLTYPE, GLTYPE2FLOAT)                              \
7433464ebd5Sriastradh    do {                                                                \
7443464ebd5Sriastradh        GLuint i;                                                       \
7453464ebd5Sriastradh        const GLTYPE *src = (const GLTYPE *)source;                     \
7463464ebd5Sriastradh        for (i = 0; i < n; i++) {                                       \
7473464ebd5Sriastradh            GLTYPE value = src[i];                                      \
7483464ebd5Sriastradh            if (srcPacking->SwapBytes) {                                \
7493464ebd5Sriastradh                if (sizeof(GLTYPE) == 2) {                              \
7503464ebd5Sriastradh                    SWAP2BYTE(value);                                   \
7513464ebd5Sriastradh                } else if (sizeof(GLTYPE) == 4) {                       \
7523464ebd5Sriastradh                    SWAP4BYTE(value);                                   \
7533464ebd5Sriastradh                }                                                       \
7543464ebd5Sriastradh            }                                                           \
7553464ebd5Sriastradh            depthValues[i] = GLTYPE2FLOAT(value);                       \
7563464ebd5Sriastradh        }                                                               \
7573464ebd5Sriastradh    } while (0)
7583464ebd5Sriastradh
7593464ebd5Sriastradh
7603464ebd5Sriastradh/**
7613464ebd5Sriastradh * Unpack a row of depth/z values from memory, returning GLushort, GLuint
7623464ebd5Sriastradh * or GLfloat values.
7633464ebd5Sriastradh * The glPixelTransfer (scale/bias) params will be applied.
7643464ebd5Sriastradh *
7653464ebd5Sriastradh * \param dstType  one of GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_FLOAT
7663464ebd5Sriastradh * \param depthMax  max value for returned GLushort or GLuint values
7673464ebd5Sriastradh *                  (ignored for GLfloat).
7683464ebd5Sriastradh */
7693464ebd5Sriastradhvoid
7703464ebd5Sriastradh_mesa_unpack_depth_span( struct gl_context *ctx, GLuint n,
7713464ebd5Sriastradh                         GLenum dstType, GLvoid *dest, GLuint depthMax,
7723464ebd5Sriastradh                         GLenum srcType, const GLvoid *source,
7733464ebd5Sriastradh                         const struct gl_pixelstore_attrib *srcPacking )
7743464ebd5Sriastradh{
7753464ebd5Sriastradh   GLfloat *depthTemp = NULL, *depthValues;
7763464ebd5Sriastradh   GLboolean needClamp = GL_FALSE;
7773464ebd5Sriastradh
7783464ebd5Sriastradh   /* Look for special cases first.
7793464ebd5Sriastradh    * Not only are these faster, they're less prone to numeric conversion
7803464ebd5Sriastradh    * problems.  Otherwise, converting from an int type to a float then
7813464ebd5Sriastradh    * back to an int type can introduce errors that will show up as
7823464ebd5Sriastradh    * artifacts in things like depth peeling which uses glCopyTexImage.
7833464ebd5Sriastradh    */
78401e04c3fSmrg   if (ctx->Pixel.DepthScale == 1.0F && ctx->Pixel.DepthBias == 0.0F) {
7853464ebd5Sriastradh      if (srcType == GL_UNSIGNED_INT && dstType == GL_UNSIGNED_SHORT) {
7863464ebd5Sriastradh         const GLuint *src = (const GLuint *) source;
7873464ebd5Sriastradh         GLushort *dst = (GLushort *) dest;
7883464ebd5Sriastradh         GLuint i;
7893464ebd5Sriastradh         for (i = 0; i < n; i++) {
7903464ebd5Sriastradh            dst[i] = src[i] >> 16;
7913464ebd5Sriastradh         }
7923464ebd5Sriastradh         return;
7933464ebd5Sriastradh      }
7943464ebd5Sriastradh      if (srcType == GL_UNSIGNED_SHORT
7953464ebd5Sriastradh          && dstType == GL_UNSIGNED_INT
7963464ebd5Sriastradh          && depthMax == 0xffffffff) {
7973464ebd5Sriastradh         const GLushort *src = (const GLushort *) source;
7983464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
7993464ebd5Sriastradh         GLuint i;
8003464ebd5Sriastradh         for (i = 0; i < n; i++) {
8013464ebd5Sriastradh            dst[i] = src[i] | (src[i] << 16);
8023464ebd5Sriastradh         }
8033464ebd5Sriastradh         return;
8043464ebd5Sriastradh      }
8053464ebd5Sriastradh      if (srcType == GL_UNSIGNED_INT_24_8
8063464ebd5Sriastradh          && dstType == GL_UNSIGNED_INT
8073464ebd5Sriastradh          && depthMax == 0xffffff) {
8083464ebd5Sriastradh         const GLuint *src = (const GLuint *) source;
8093464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
8103464ebd5Sriastradh         GLuint i;
8113464ebd5Sriastradh         for (i = 0; i < n; i++) {
8123464ebd5Sriastradh            dst[i] = src[i] >> 8;
8133464ebd5Sriastradh         }
8143464ebd5Sriastradh         return;
8153464ebd5Sriastradh      }
8163464ebd5Sriastradh      /* XXX may want to add additional cases here someday */
8173464ebd5Sriastradh   }
8183464ebd5Sriastradh
8193464ebd5Sriastradh   /* general case path follows */
8203464ebd5Sriastradh
8213464ebd5Sriastradh   if (dstType == GL_FLOAT) {
8223464ebd5Sriastradh      depthValues = (GLfloat *) dest;
8233464ebd5Sriastradh   }
8243464ebd5Sriastradh   else {
825af69d88dSmrg      depthTemp = malloc(n * sizeof(GLfloat));
8263464ebd5Sriastradh      if (!depthTemp) {
8273464ebd5Sriastradh         _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
8283464ebd5Sriastradh         return;
8293464ebd5Sriastradh      }
8303464ebd5Sriastradh
8313464ebd5Sriastradh      depthValues = depthTemp;
8323464ebd5Sriastradh   }
8333464ebd5Sriastradh
8343464ebd5Sriastradh   /* Convert incoming values to GLfloat.  Some conversions will require
8353464ebd5Sriastradh    * clamping, below.
8363464ebd5Sriastradh    */
8373464ebd5Sriastradh   switch (srcType) {
8383464ebd5Sriastradh      case GL_BYTE:
839af69d88dSmrg         DEPTH_VALUES(GLbyte, BYTE_TO_FLOATZ);
8403464ebd5Sriastradh         needClamp = GL_TRUE;
8413464ebd5Sriastradh         break;
8423464ebd5Sriastradh      case GL_UNSIGNED_BYTE:
8433464ebd5Sriastradh         DEPTH_VALUES(GLubyte, UBYTE_TO_FLOAT);
8443464ebd5Sriastradh         break;
8453464ebd5Sriastradh      case GL_SHORT:
846af69d88dSmrg         DEPTH_VALUES(GLshort, SHORT_TO_FLOATZ);
8473464ebd5Sriastradh         needClamp = GL_TRUE;
8483464ebd5Sriastradh         break;
8493464ebd5Sriastradh      case GL_UNSIGNED_SHORT:
8503464ebd5Sriastradh         DEPTH_VALUES(GLushort, USHORT_TO_FLOAT);
8513464ebd5Sriastradh         break;
8523464ebd5Sriastradh      case GL_INT:
8533464ebd5Sriastradh         DEPTH_VALUES(GLint, INT_TO_FLOAT);
8543464ebd5Sriastradh         needClamp = GL_TRUE;
8553464ebd5Sriastradh         break;
8563464ebd5Sriastradh      case GL_UNSIGNED_INT:
8573464ebd5Sriastradh         DEPTH_VALUES(GLuint, UINT_TO_FLOAT);
8583464ebd5Sriastradh         break;
8593464ebd5Sriastradh      case GL_UNSIGNED_INT_24_8_EXT: /* GL_EXT_packed_depth_stencil */
8603464ebd5Sriastradh         if (dstType == GL_UNSIGNED_INT_24_8_EXT &&
8613464ebd5Sriastradh             depthMax == 0xffffff &&
86201e04c3fSmrg             ctx->Pixel.DepthScale == 1.0F &&
86301e04c3fSmrg             ctx->Pixel.DepthBias == 0.0F) {
8643464ebd5Sriastradh            const GLuint *src = (const GLuint *) source;
8653464ebd5Sriastradh            GLuint *zValues = (GLuint *) dest;
8663464ebd5Sriastradh            GLuint i;
8673464ebd5Sriastradh            for (i = 0; i < n; i++) {
8683464ebd5Sriastradh                GLuint value = src[i];
8693464ebd5Sriastradh                if (srcPacking->SwapBytes) {
8703464ebd5Sriastradh                    SWAP4BYTE(value);
8713464ebd5Sriastradh                }
8723464ebd5Sriastradh                zValues[i] = value & 0xffffff00;
8733464ebd5Sriastradh            }
8743464ebd5Sriastradh            free(depthTemp);
8753464ebd5Sriastradh            return;
8763464ebd5Sriastradh         }
8773464ebd5Sriastradh         else {
8783464ebd5Sriastradh            const GLuint *src = (const GLuint *) source;
8793464ebd5Sriastradh            const GLfloat scale = 1.0f / 0xffffff;
8803464ebd5Sriastradh            GLuint i;
8813464ebd5Sriastradh            for (i = 0; i < n; i++) {
8823464ebd5Sriastradh                GLuint value = src[i];
8833464ebd5Sriastradh                if (srcPacking->SwapBytes) {
8843464ebd5Sriastradh                    SWAP4BYTE(value);
8853464ebd5Sriastradh                }
8863464ebd5Sriastradh                depthValues[i] = (value >> 8) * scale;
8873464ebd5Sriastradh            }
8883464ebd5Sriastradh         }
8893464ebd5Sriastradh         break;
890af69d88dSmrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
891af69d88dSmrg         {
892af69d88dSmrg            GLuint i;
893af69d88dSmrg            const GLfloat *src = (const GLfloat *)source;
894af69d88dSmrg            for (i = 0; i < n; i++) {
895af69d88dSmrg               GLfloat value = src[i * 2];
896af69d88dSmrg               if (srcPacking->SwapBytes) {
897af69d88dSmrg                  SWAP4BYTE(value);
898af69d88dSmrg               }
899af69d88dSmrg               depthValues[i] = value;
900af69d88dSmrg            }
901af69d88dSmrg            needClamp = GL_TRUE;
902af69d88dSmrg         }
903af69d88dSmrg         break;
9043464ebd5Sriastradh      case GL_FLOAT:
9053464ebd5Sriastradh         DEPTH_VALUES(GLfloat, 1*);
9063464ebd5Sriastradh         needClamp = GL_TRUE;
9073464ebd5Sriastradh         break;
9083464ebd5Sriastradh      case GL_HALF_FLOAT_ARB:
90901e04c3fSmrg      case GL_HALF_FLOAT_OES:
9103464ebd5Sriastradh         {
9113464ebd5Sriastradh            GLuint i;
9123464ebd5Sriastradh            const GLhalfARB *src = (const GLhalfARB *) source;
9133464ebd5Sriastradh            for (i = 0; i < n; i++) {
9143464ebd5Sriastradh               GLhalfARB value = src[i];
9153464ebd5Sriastradh               if (srcPacking->SwapBytes) {
9163464ebd5Sriastradh                  SWAP2BYTE(value);
9173464ebd5Sriastradh               }
9183464ebd5Sriastradh               depthValues[i] = _mesa_half_to_float(value);
9193464ebd5Sriastradh            }
9203464ebd5Sriastradh            needClamp = GL_TRUE;
9213464ebd5Sriastradh         }
9223464ebd5Sriastradh         break;
9233464ebd5Sriastradh      default:
9243464ebd5Sriastradh         _mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()");
9253464ebd5Sriastradh         free(depthTemp);
9263464ebd5Sriastradh         return;
9273464ebd5Sriastradh   }
9283464ebd5Sriastradh
9293464ebd5Sriastradh   /* apply depth scale and bias */
9303464ebd5Sriastradh   {
9313464ebd5Sriastradh      const GLfloat scale = ctx->Pixel.DepthScale;
9323464ebd5Sriastradh      const GLfloat bias = ctx->Pixel.DepthBias;
93301e04c3fSmrg      if (scale != 1.0F || bias != 0.0F) {
9343464ebd5Sriastradh         GLuint i;
9353464ebd5Sriastradh         for (i = 0; i < n; i++) {
9363464ebd5Sriastradh            depthValues[i] = depthValues[i] * scale + bias;
9373464ebd5Sriastradh         }
9383464ebd5Sriastradh         needClamp = GL_TRUE;
9393464ebd5Sriastradh      }
9403464ebd5Sriastradh   }
9413464ebd5Sriastradh
9423464ebd5Sriastradh   /* clamp to [0, 1] */
9433464ebd5Sriastradh   if (needClamp) {
9443464ebd5Sriastradh      GLuint i;
9453464ebd5Sriastradh      for (i = 0; i < n; i++) {
94601e04c3fSmrg         depthValues[i] = CLAMP(depthValues[i], 0.0F, 1.0F);
9473464ebd5Sriastradh      }
9483464ebd5Sriastradh   }
9493464ebd5Sriastradh
9503464ebd5Sriastradh   /*
9513464ebd5Sriastradh    * Convert values to dstType
9523464ebd5Sriastradh    */
9533464ebd5Sriastradh   if (dstType == GL_UNSIGNED_INT) {
9543464ebd5Sriastradh      GLuint *zValues = (GLuint *) dest;
9553464ebd5Sriastradh      GLuint i;
9563464ebd5Sriastradh      if (depthMax <= 0xffffff) {
9573464ebd5Sriastradh         /* no overflow worries */
9583464ebd5Sriastradh         for (i = 0; i < n; i++) {
9593464ebd5Sriastradh            zValues[i] = (GLuint) (depthValues[i] * (GLfloat) depthMax);
9603464ebd5Sriastradh         }
9613464ebd5Sriastradh      }
9623464ebd5Sriastradh      else {
9633464ebd5Sriastradh         /* need to use double precision to prevent overflow problems */
9643464ebd5Sriastradh         for (i = 0; i < n; i++) {
965af69d88dSmrg            GLdouble z = depthValues[i] * (GLdouble) depthMax;
9663464ebd5Sriastradh            if (z >= (GLdouble) 0xffffffff)
9673464ebd5Sriastradh               zValues[i] = 0xffffffff;
9683464ebd5Sriastradh            else
9693464ebd5Sriastradh               zValues[i] = (GLuint) z;
9703464ebd5Sriastradh         }
9713464ebd5Sriastradh      }
9723464ebd5Sriastradh   }
9733464ebd5Sriastradh   else if (dstType == GL_UNSIGNED_SHORT) {
9743464ebd5Sriastradh      GLushort *zValues = (GLushort *) dest;
9753464ebd5Sriastradh      GLuint i;
97601e04c3fSmrg      assert(depthMax <= 0xffff);
9773464ebd5Sriastradh      for (i = 0; i < n; i++) {
9783464ebd5Sriastradh         zValues[i] = (GLushort) (depthValues[i] * (GLfloat) depthMax);
9793464ebd5Sriastradh      }
9803464ebd5Sriastradh   }
981af69d88dSmrg   else if (dstType == GL_FLOAT) {
982af69d88dSmrg      /* Nothing to do. depthValues is pointing to dest. */
983af69d88dSmrg   }
984af69d88dSmrg   else if (dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) {
985af69d88dSmrg      GLfloat *zValues = (GLfloat*) dest;
986af69d88dSmrg      GLuint i;
987af69d88dSmrg      for (i = 0; i < n; i++) {
988af69d88dSmrg         zValues[i*2] = depthValues[i];
989af69d88dSmrg      }
990af69d88dSmrg   }
9913464ebd5Sriastradh   else {
99201e04c3fSmrg      assert(0);
9933464ebd5Sriastradh   }
9943464ebd5Sriastradh
9953464ebd5Sriastradh   free(depthTemp);
9963464ebd5Sriastradh}
9973464ebd5Sriastradh
9983464ebd5Sriastradh
9993464ebd5Sriastradh/*
10003464ebd5Sriastradh * Pack an array of depth values.  The values are floats in [0,1].
10013464ebd5Sriastradh */
10023464ebd5Sriastradhvoid
10033464ebd5Sriastradh_mesa_pack_depth_span( struct gl_context *ctx, GLuint n, GLvoid *dest,
10043464ebd5Sriastradh                       GLenum dstType, const GLfloat *depthSpan,
10053464ebd5Sriastradh                       const struct gl_pixelstore_attrib *dstPacking )
10063464ebd5Sriastradh{
1007af69d88dSmrg   GLfloat *depthCopy = malloc(n * sizeof(GLfloat));
10083464ebd5Sriastradh   if (!depthCopy) {
10093464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel packing");
10103464ebd5Sriastradh      return;
10113464ebd5Sriastradh   }
10123464ebd5Sriastradh
101301e04c3fSmrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) {
10143464ebd5Sriastradh      memcpy(depthCopy, depthSpan, n * sizeof(GLfloat));
10153464ebd5Sriastradh      _mesa_scale_and_bias_depth(ctx, n, depthCopy);
10163464ebd5Sriastradh      depthSpan = depthCopy;
10173464ebd5Sriastradh   }
10183464ebd5Sriastradh
10193464ebd5Sriastradh   switch (dstType) {
10203464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
10213464ebd5Sriastradh      {
10223464ebd5Sriastradh         GLubyte *dst = (GLubyte *) dest;
10233464ebd5Sriastradh         GLuint i;
10243464ebd5Sriastradh         for (i = 0; i < n; i++) {
10253464ebd5Sriastradh            dst[i] = FLOAT_TO_UBYTE( depthSpan[i] );
10263464ebd5Sriastradh         }
10273464ebd5Sriastradh      }
10283464ebd5Sriastradh      break;
10293464ebd5Sriastradh   case GL_BYTE:
10303464ebd5Sriastradh      {
10313464ebd5Sriastradh         GLbyte *dst = (GLbyte *) dest;
10323464ebd5Sriastradh         GLuint i;
10333464ebd5Sriastradh         for (i = 0; i < n; i++) {
10343464ebd5Sriastradh            dst[i] = FLOAT_TO_BYTE( depthSpan[i] );
10353464ebd5Sriastradh         }
10363464ebd5Sriastradh      }
10373464ebd5Sriastradh      break;
10383464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
10393464ebd5Sriastradh      {
10403464ebd5Sriastradh         GLushort *dst = (GLushort *) dest;
10413464ebd5Sriastradh         GLuint i;
10423464ebd5Sriastradh         for (i = 0; i < n; i++) {
10433464ebd5Sriastradh            CLAMPED_FLOAT_TO_USHORT(dst[i], depthSpan[i]);
10443464ebd5Sriastradh         }
10453464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10463464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
10473464ebd5Sriastradh         }
10483464ebd5Sriastradh      }
10493464ebd5Sriastradh      break;
10503464ebd5Sriastradh   case GL_SHORT:
10513464ebd5Sriastradh      {
10523464ebd5Sriastradh         GLshort *dst = (GLshort *) dest;
10533464ebd5Sriastradh         GLuint i;
10543464ebd5Sriastradh         for (i = 0; i < n; i++) {
10553464ebd5Sriastradh            dst[i] = FLOAT_TO_SHORT( depthSpan[i] );
10563464ebd5Sriastradh         }
10573464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10583464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
10593464ebd5Sriastradh         }
10603464ebd5Sriastradh      }
10613464ebd5Sriastradh      break;
106201e04c3fSmrg   case GL_UNSIGNED_INT_24_8:
106301e04c3fSmrg      {
106401e04c3fSmrg         const GLdouble scale = (GLdouble) 0xffffff;
106501e04c3fSmrg         GLuint *dst = (GLuint *) dest;
106601e04c3fSmrg         GLuint i;
106701e04c3fSmrg         for (i = 0; i < n; i++) {
106801e04c3fSmrg            GLuint z = (GLuint) (depthSpan[i] * scale);
106901e04c3fSmrg            assert(z <= 0xffffff);
107001e04c3fSmrg            dst[i] = (z << 8);
107101e04c3fSmrg         }
107201e04c3fSmrg         if (dstPacking->SwapBytes) {
107301e04c3fSmrg            _mesa_swap4( (GLuint *) dst, n );
107401e04c3fSmrg         }
107501e04c3fSmrg         break;
107601e04c3fSmrg      }
10773464ebd5Sriastradh   case GL_UNSIGNED_INT:
10783464ebd5Sriastradh      {
10793464ebd5Sriastradh         GLuint *dst = (GLuint *) dest;
10803464ebd5Sriastradh         GLuint i;
10813464ebd5Sriastradh         for (i = 0; i < n; i++) {
10823464ebd5Sriastradh            dst[i] = FLOAT_TO_UINT( depthSpan[i] );
10833464ebd5Sriastradh         }
10843464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10853464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
10863464ebd5Sriastradh         }
10873464ebd5Sriastradh      }
10883464ebd5Sriastradh      break;
10893464ebd5Sriastradh   case GL_INT:
10903464ebd5Sriastradh      {
10913464ebd5Sriastradh         GLint *dst = (GLint *) dest;
10923464ebd5Sriastradh         GLuint i;
10933464ebd5Sriastradh         for (i = 0; i < n; i++) {
10943464ebd5Sriastradh            dst[i] = FLOAT_TO_INT( depthSpan[i] );
10953464ebd5Sriastradh         }
10963464ebd5Sriastradh         if (dstPacking->SwapBytes) {
10973464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
10983464ebd5Sriastradh         }
10993464ebd5Sriastradh      }
11003464ebd5Sriastradh      break;
11013464ebd5Sriastradh   case GL_FLOAT:
11023464ebd5Sriastradh      {
11033464ebd5Sriastradh         GLfloat *dst = (GLfloat *) dest;
11043464ebd5Sriastradh         GLuint i;
11053464ebd5Sriastradh         for (i = 0; i < n; i++) {
11063464ebd5Sriastradh            dst[i] = depthSpan[i];
11073464ebd5Sriastradh         }
11083464ebd5Sriastradh         if (dstPacking->SwapBytes) {
11093464ebd5Sriastradh            _mesa_swap4( (GLuint *) dst, n );
11103464ebd5Sriastradh         }
11113464ebd5Sriastradh      }
11123464ebd5Sriastradh      break;
11133464ebd5Sriastradh   case GL_HALF_FLOAT_ARB:
111401e04c3fSmrg   case GL_HALF_FLOAT_OES:
11153464ebd5Sriastradh      {
11163464ebd5Sriastradh         GLhalfARB *dst = (GLhalfARB *) dest;
11173464ebd5Sriastradh         GLuint i;
11183464ebd5Sriastradh         for (i = 0; i < n; i++) {
11193464ebd5Sriastradh            dst[i] = _mesa_float_to_half(depthSpan[i]);
11203464ebd5Sriastradh         }
11213464ebd5Sriastradh         if (dstPacking->SwapBytes) {
11223464ebd5Sriastradh            _mesa_swap2( (GLushort *) dst, n );
11233464ebd5Sriastradh         }
11243464ebd5Sriastradh      }
11253464ebd5Sriastradh      break;
11263464ebd5Sriastradh   default:
112701e04c3fSmrg      unreachable("bad type in _mesa_pack_depth_span()");
11283464ebd5Sriastradh   }
11293464ebd5Sriastradh
11303464ebd5Sriastradh   free(depthCopy);
11313464ebd5Sriastradh}
11323464ebd5Sriastradh
11333464ebd5Sriastradh
11343464ebd5Sriastradh
11353464ebd5Sriastradh/**
1136af69d88dSmrg * Pack depth and stencil values as GL_DEPTH_STENCIL (GL_UNSIGNED_INT_24_8 etc)
11373464ebd5Sriastradh */
11383464ebd5Sriastradhvoid
1139af69d88dSmrg_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n,
1140af69d88dSmrg                              GLenum dstType, GLuint *dest,
11413464ebd5Sriastradh                              const GLfloat *depthVals,
1142af69d88dSmrg                              const GLubyte *stencilVals,
11433464ebd5Sriastradh                              const struct gl_pixelstore_attrib *dstPacking)
11443464ebd5Sriastradh{
1145af69d88dSmrg   GLfloat *depthCopy = malloc(n * sizeof(GLfloat));
1146af69d88dSmrg   GLubyte *stencilCopy = malloc(n * sizeof(GLubyte));
11473464ebd5Sriastradh   GLuint i;
11483464ebd5Sriastradh
11493464ebd5Sriastradh   if (!depthCopy || !stencilCopy) {
11503464ebd5Sriastradh      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel packing");
11513464ebd5Sriastradh      free(depthCopy);
11523464ebd5Sriastradh      free(stencilCopy);
11533464ebd5Sriastradh      return;
11543464ebd5Sriastradh   }
11553464ebd5Sriastradh
115601e04c3fSmrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) {
11573464ebd5Sriastradh      memcpy(depthCopy, depthVals, n * sizeof(GLfloat));
11583464ebd5Sriastradh      _mesa_scale_and_bias_depth(ctx, n, depthCopy);
11593464ebd5Sriastradh      depthVals = depthCopy;
11603464ebd5Sriastradh   }
11613464ebd5Sriastradh
11623464ebd5Sriastradh   if (ctx->Pixel.IndexShift ||
11633464ebd5Sriastradh       ctx->Pixel.IndexOffset ||
11643464ebd5Sriastradh       ctx->Pixel.MapStencilFlag) {
1165af69d88dSmrg      memcpy(stencilCopy, stencilVals, n * sizeof(GLubyte));
11663464ebd5Sriastradh      _mesa_apply_stencil_transfer_ops(ctx, n, stencilCopy);
11673464ebd5Sriastradh      stencilVals = stencilCopy;
11683464ebd5Sriastradh   }
11693464ebd5Sriastradh
1170af69d88dSmrg   switch (dstType) {
1171af69d88dSmrg   case GL_UNSIGNED_INT_24_8:
1172af69d88dSmrg      for (i = 0; i < n; i++) {
1173af69d88dSmrg         GLuint z = (GLuint) (depthVals[i] * 0xffffff);
1174af69d88dSmrg         dest[i] = (z << 8) | (stencilVals[i] & 0xff);
1175af69d88dSmrg      }
1176af69d88dSmrg      break;
1177af69d88dSmrg   case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
1178af69d88dSmrg      for (i = 0; i < n; i++) {
1179af69d88dSmrg         ((GLfloat*)dest)[i*2] = depthVals[i];
1180af69d88dSmrg         dest[i*2+1] = stencilVals[i] & 0xff;
1181af69d88dSmrg      }
1182af69d88dSmrg      break;
11833464ebd5Sriastradh   }
11843464ebd5Sriastradh
11853464ebd5Sriastradh   if (dstPacking->SwapBytes) {
11863464ebd5Sriastradh      _mesa_swap4(dest, n);
11873464ebd5Sriastradh   }
11883464ebd5Sriastradh
11893464ebd5Sriastradh   free(depthCopy);
11903464ebd5Sriastradh   free(stencilCopy);
11913464ebd5Sriastradh}
11923464ebd5Sriastradh
11933464ebd5Sriastradh
11943464ebd5Sriastradh
11953464ebd5Sriastradh/**
11963464ebd5Sriastradh * Unpack image data.  Apply byte swapping, byte flipping (bitmap).
11973464ebd5Sriastradh * Return all image data in a contiguous block.  This is used when we
11983464ebd5Sriastradh * compile glDrawPixels, glTexImage, etc into a display list.  We
11993464ebd5Sriastradh * need a copy of the data in a standard format.
12003464ebd5Sriastradh */
12013464ebd5Sriastradhvoid *
12023464ebd5Sriastradh_mesa_unpack_image( GLuint dimensions,
12033464ebd5Sriastradh                    GLsizei width, GLsizei height, GLsizei depth,
12043464ebd5Sriastradh                    GLenum format, GLenum type, const GLvoid *pixels,
12053464ebd5Sriastradh                    const struct gl_pixelstore_attrib *unpack )
12063464ebd5Sriastradh{
12073464ebd5Sriastradh   GLint bytesPerRow, compsPerRow;
12083464ebd5Sriastradh   GLboolean flipBytes, swap2, swap4;
12093464ebd5Sriastradh
12103464ebd5Sriastradh   if (!pixels)
12113464ebd5Sriastradh      return NULL;  /* not necessarily an error */
12123464ebd5Sriastradh
12133464ebd5Sriastradh   if (width <= 0 || height <= 0 || depth <= 0)
12143464ebd5Sriastradh      return NULL;  /* generate error later */
12153464ebd5Sriastradh
12163464ebd5Sriastradh   if (type == GL_BITMAP) {
12173464ebd5Sriastradh      bytesPerRow = (width + 7) >> 3;
12183464ebd5Sriastradh      flipBytes = unpack->LsbFirst;
12193464ebd5Sriastradh      swap2 = swap4 = GL_FALSE;
12203464ebd5Sriastradh      compsPerRow = 0;
12213464ebd5Sriastradh   }
12223464ebd5Sriastradh   else {
12233464ebd5Sriastradh      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
12243464ebd5Sriastradh      GLint components = _mesa_components_in_format(format);
12253464ebd5Sriastradh      GLint bytesPerComp;
12263464ebd5Sriastradh
12273464ebd5Sriastradh      if (_mesa_type_is_packed(type))
12283464ebd5Sriastradh          components = 1;
12293464ebd5Sriastradh
12303464ebd5Sriastradh      if (bytesPerPixel <= 0 || components <= 0)
12313464ebd5Sriastradh         return NULL;   /* bad format or type.  generate error later */
12323464ebd5Sriastradh      bytesPerRow = bytesPerPixel * width;
12333464ebd5Sriastradh      bytesPerComp = bytesPerPixel / components;
12343464ebd5Sriastradh      flipBytes = GL_FALSE;
12353464ebd5Sriastradh      swap2 = (bytesPerComp == 2) && unpack->SwapBytes;
12363464ebd5Sriastradh      swap4 = (bytesPerComp == 4) && unpack->SwapBytes;
12373464ebd5Sriastradh      compsPerRow = components * width;
12383464ebd5Sriastradh      assert(compsPerRow >= width);
12393464ebd5Sriastradh   }
12403464ebd5Sriastradh
12413464ebd5Sriastradh   {
12423464ebd5Sriastradh      GLubyte *destBuffer
1243af69d88dSmrg         = malloc(bytesPerRow * height * depth);
12443464ebd5Sriastradh      GLubyte *dst;
12453464ebd5Sriastradh      GLint img, row;
12463464ebd5Sriastradh      if (!destBuffer)
12473464ebd5Sriastradh         return NULL;   /* generate GL_OUT_OF_MEMORY later */
12483464ebd5Sriastradh
12493464ebd5Sriastradh      dst = destBuffer;
12503464ebd5Sriastradh      for (img = 0; img < depth; img++) {
12513464ebd5Sriastradh         for (row = 0; row < height; row++) {
12523464ebd5Sriastradh            const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels,
12533464ebd5Sriastradh                               width, height, format, type, img, row, 0);
12543464ebd5Sriastradh
12553464ebd5Sriastradh            if ((type == GL_BITMAP) && (unpack->SkipPixels & 0x7)) {
12563464ebd5Sriastradh               GLint i;
12573464ebd5Sriastradh               flipBytes = GL_FALSE;
12583464ebd5Sriastradh               if (unpack->LsbFirst) {
12593464ebd5Sriastradh                  GLubyte srcMask = 1 << (unpack->SkipPixels & 0x7);
12603464ebd5Sriastradh                  GLubyte dstMask = 128;
12613464ebd5Sriastradh                  const GLubyte *s = src;
12623464ebd5Sriastradh                  GLubyte *d = dst;
12633464ebd5Sriastradh                  *d = 0;
12643464ebd5Sriastradh                  for (i = 0; i < width; i++) {
12653464ebd5Sriastradh                     if (*s & srcMask) {
12663464ebd5Sriastradh                        *d |= dstMask;
12677ec681f3Smrg                     }
12683464ebd5Sriastradh                     if (srcMask == 128) {
12693464ebd5Sriastradh                        srcMask = 1;
12703464ebd5Sriastradh                        s++;
12713464ebd5Sriastradh                     }
12723464ebd5Sriastradh                     else {
12733464ebd5Sriastradh                        srcMask = srcMask << 1;
12743464ebd5Sriastradh                     }
12753464ebd5Sriastradh                     if (dstMask == 1) {
12763464ebd5Sriastradh                        dstMask = 128;
12773464ebd5Sriastradh                        d++;
12783464ebd5Sriastradh                        *d = 0;
12793464ebd5Sriastradh                     }
12803464ebd5Sriastradh                     else {
12813464ebd5Sriastradh                        dstMask = dstMask >> 1;
12823464ebd5Sriastradh                     }
12833464ebd5Sriastradh                  }
12843464ebd5Sriastradh               }
12853464ebd5Sriastradh               else {
12863464ebd5Sriastradh                  GLubyte srcMask = 128 >> (unpack->SkipPixels & 0x7);
12873464ebd5Sriastradh                  GLubyte dstMask = 128;
12883464ebd5Sriastradh                  const GLubyte *s = src;
12893464ebd5Sriastradh                  GLubyte *d = dst;
12903464ebd5Sriastradh                  *d = 0;
12913464ebd5Sriastradh                  for (i = 0; i < width; i++) {
12923464ebd5Sriastradh                     if (*s & srcMask) {
12933464ebd5Sriastradh                        *d |= dstMask;
12943464ebd5Sriastradh                     }
12953464ebd5Sriastradh                     if (srcMask == 1) {
12963464ebd5Sriastradh                        srcMask = 128;
12973464ebd5Sriastradh                        s++;
12983464ebd5Sriastradh                     }
12993464ebd5Sriastradh                     else {
13003464ebd5Sriastradh                        srcMask = srcMask >> 1;
13013464ebd5Sriastradh                     }
13023464ebd5Sriastradh                     if (dstMask == 1) {
13033464ebd5Sriastradh                        dstMask = 128;
13043464ebd5Sriastradh                        d++;
13053464ebd5Sriastradh                        *d = 0;
13063464ebd5Sriastradh                     }
13073464ebd5Sriastradh                     else {
13083464ebd5Sriastradh                        dstMask = dstMask >> 1;
13097ec681f3Smrg                     }
13103464ebd5Sriastradh                  }
13113464ebd5Sriastradh               }
13123464ebd5Sriastradh            }
13133464ebd5Sriastradh            else {
13143464ebd5Sriastradh               memcpy(dst, src, bytesPerRow);
13153464ebd5Sriastradh            }
13163464ebd5Sriastradh
13173464ebd5Sriastradh            /* byte flipping/swapping */
13183464ebd5Sriastradh            if (flipBytes) {
13193464ebd5Sriastradh               flip_bytes((GLubyte *) dst, bytesPerRow);
13203464ebd5Sriastradh            }
13213464ebd5Sriastradh            else if (swap2) {
13223464ebd5Sriastradh               _mesa_swap2((GLushort*) dst, compsPerRow);
13233464ebd5Sriastradh            }
13243464ebd5Sriastradh            else if (swap4) {
13253464ebd5Sriastradh               _mesa_swap4((GLuint*) dst, compsPerRow);
13263464ebd5Sriastradh            }
13273464ebd5Sriastradh            dst += bytesPerRow;
13283464ebd5Sriastradh         }
13293464ebd5Sriastradh      }
13303464ebd5Sriastradh      return destBuffer;
13313464ebd5Sriastradh   }
13323464ebd5Sriastradh}
13333464ebd5Sriastradh
1334af69d88dSmrgvoid
133501e04c3fSmrg_mesa_pack_luminance_from_rgba_float(GLuint n, GLfloat rgba[][4],
133601e04c3fSmrg                                     GLvoid *dstAddr, GLenum dst_format,
133701e04c3fSmrg                                     GLbitfield transferOps)
1338af69d88dSmrg{
133901e04c3fSmrg   int i;
134001e04c3fSmrg   GLfloat *dst = (GLfloat *) dstAddr;
1341af69d88dSmrg
134201e04c3fSmrg   switch (dst_format) {
1343af69d88dSmrg   case GL_LUMINANCE:
134401e04c3fSmrg      if (transferOps & IMAGE_CLAMP_BIT) {
134501e04c3fSmrg         for (i = 0; i < n; i++) {
134601e04c3fSmrg            GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
134701e04c3fSmrg            dst[i] = CLAMP(sum, 0.0F, 1.0F);
134801e04c3fSmrg         }
134901e04c3fSmrg      } else {
135001e04c3fSmrg         for (i = 0; i < n; i++) {
135101e04c3fSmrg            dst[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
135201e04c3fSmrg         }
1353af69d88dSmrg      }
135401e04c3fSmrg      return;
1355af69d88dSmrg   case GL_LUMINANCE_ALPHA:
135601e04c3fSmrg      if (transferOps & IMAGE_CLAMP_BIT) {
135701e04c3fSmrg         for (i = 0; i < n; i++) {
135801e04c3fSmrg            GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
135901e04c3fSmrg            dst[2*i] = CLAMP(sum, 0.0F, 1.0F);
136001e04c3fSmrg            dst[2*i+1] = rgba[i][ACOMP];
136101e04c3fSmrg         }
136201e04c3fSmrg      } else {
136301e04c3fSmrg         for (i = 0; i < n; i++) {
136401e04c3fSmrg            dst[2*i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
136501e04c3fSmrg            dst[2*i+1] = rgba[i][ACOMP];
136601e04c3fSmrg         }
1367af69d88dSmrg      }
136801e04c3fSmrg      return;
1369af69d88dSmrg   default:
137001e04c3fSmrg      assert(!"Unsupported format");
137101e04c3fSmrg   }
137201e04c3fSmrg}
137301e04c3fSmrg
137401e04c3fSmrgstatic int32_t
137501e04c3fSmrgclamp_sint64_to_sint32(int64_t src)
137601e04c3fSmrg{
137701e04c3fSmrg   return CLAMP(src, INT32_MIN, INT32_MAX);
137801e04c3fSmrg}
137901e04c3fSmrg
138001e04c3fSmrgstatic int32_t
138101e04c3fSmrgclamp_sint64_to_uint32(int64_t src)
138201e04c3fSmrg{
138301e04c3fSmrg   return CLAMP(src, 0, UINT32_MAX);
138401e04c3fSmrg}
138501e04c3fSmrg
138601e04c3fSmrgstatic int32_t
138701e04c3fSmrgclamp_uint64_to_uint32(uint64_t src)
138801e04c3fSmrg{
138901e04c3fSmrg   return MIN2(src, UINT32_MAX);
139001e04c3fSmrg}
139101e04c3fSmrg
139201e04c3fSmrgstatic int32_t
139301e04c3fSmrgclamp_uint64_to_sint32(uint64_t src)
139401e04c3fSmrg{
139501e04c3fSmrg   return MIN2(src, INT32_MAX);
139601e04c3fSmrg}
139701e04c3fSmrg
139801e04c3fSmrgstatic int32_t
139901e04c3fSmrgconvert_integer_luminance64(int64_t src64, int bits,
140001e04c3fSmrg                            bool dst_is_signed, bool src_is_signed)
140101e04c3fSmrg{
140201e04c3fSmrg   int32_t src32;
140301e04c3fSmrg
140401e04c3fSmrg   /* Clamp Luminance value from 64-bit to 32-bit. Consider if we need
140501e04c3fSmrg    * any signed<->unsigned conversion too.
140601e04c3fSmrg    */
140701e04c3fSmrg   if (src_is_signed && dst_is_signed)
140801e04c3fSmrg      src32 = clamp_sint64_to_sint32(src64);
140901e04c3fSmrg   else if (src_is_signed && !dst_is_signed)
141001e04c3fSmrg      src32 = clamp_sint64_to_uint32(src64);
141101e04c3fSmrg   else if (!src_is_signed && dst_is_signed)
141201e04c3fSmrg      src32 = clamp_uint64_to_sint32(src64);
141301e04c3fSmrg   else
141401e04c3fSmrg      src32 = clamp_uint64_to_uint32(src64);
141501e04c3fSmrg
141601e04c3fSmrg   /* If the dst type is < 32-bit, we need an extra clamp */
141701e04c3fSmrg   if (bits == 32) {
141801e04c3fSmrg      return src32;
141901e04c3fSmrg   } else {
142001e04c3fSmrg      if (dst_is_signed)
142101e04c3fSmrg         return _mesa_signed_to_signed(src32, bits);
142201e04c3fSmrg      else
142301e04c3fSmrg         return _mesa_unsigned_to_unsigned(src32, bits);
1424af69d88dSmrg   }
1425af69d88dSmrg}
1426af69d88dSmrg
142701e04c3fSmrgstatic int32_t
142801e04c3fSmrgconvert_integer(int32_t src, int bits, bool dst_is_signed, bool src_is_signed)
142901e04c3fSmrg{
143001e04c3fSmrg   if (src_is_signed && dst_is_signed)
143101e04c3fSmrg      return _mesa_signed_to_signed(src, bits);
143201e04c3fSmrg   else if (src_is_signed && !dst_is_signed)
143301e04c3fSmrg      return _mesa_signed_to_unsigned(src, bits);
143401e04c3fSmrg   else if (!src_is_signed && dst_is_signed)
143501e04c3fSmrg      return _mesa_unsigned_to_signed(src, bits);
143601e04c3fSmrg   else
143701e04c3fSmrg      return _mesa_unsigned_to_unsigned(src, bits);
143801e04c3fSmrg}
1439af69d88dSmrg
1440af69d88dSmrgvoid
144101e04c3fSmrg_mesa_pack_luminance_from_rgba_integer(GLuint n,
144201e04c3fSmrg                                       GLuint rgba[][4], bool rgba_is_signed,
144301e04c3fSmrg                                       GLvoid *dstAddr,
144401e04c3fSmrg                                       GLenum dst_format,
144501e04c3fSmrg                                       GLenum dst_type)
1446af69d88dSmrg{
144701e04c3fSmrg   int i;
144801e04c3fSmrg   int64_t lum64;
144901e04c3fSmrg   int32_t lum32, alpha;
145001e04c3fSmrg   bool dst_is_signed;
145101e04c3fSmrg   int dst_bits;
145201e04c3fSmrg
145301e04c3fSmrg   assert(dst_format == GL_LUMINANCE_INTEGER_EXT ||
145401e04c3fSmrg          dst_format == GL_LUMINANCE_ALPHA_INTEGER_EXT);
145501e04c3fSmrg
145601e04c3fSmrg   /* We first compute luminance values as a 64-bit addition of the
145701e04c3fSmrg    * 32-bit R,G,B components, then we clamp the result to the dst type size.
145801e04c3fSmrg    *
145901e04c3fSmrg    * Notice that this operation involves casting the 32-bit R,G,B components
146001e04c3fSmrg    * to 64-bit before the addition. Since rgba is defined as a GLuint array
146101e04c3fSmrg    * we need to be careful when rgba packs signed data and make sure
146201e04c3fSmrg    * that we cast to a 32-bit signed integer values before casting them to
146301e04c3fSmrg    * 64-bit signed integers.
146401e04c3fSmrg    */
146501e04c3fSmrg   dst_is_signed = (dst_type == GL_BYTE || dst_type == GL_SHORT ||
146601e04c3fSmrg                    dst_type == GL_INT);
1467af69d88dSmrg
146801e04c3fSmrg   dst_bits = _mesa_sizeof_type(dst_type) * 8;
146901e04c3fSmrg   assert(dst_bits > 0);
147001e04c3fSmrg
147101e04c3fSmrg   switch (dst_format) {
147201e04c3fSmrg   case GL_LUMINANCE_INTEGER_EXT:
1473af69d88dSmrg      for (i = 0; i < n; i++) {
147401e04c3fSmrg         if (!rgba_is_signed) {
147501e04c3fSmrg            lum64 = (uint64_t) rgba[i][RCOMP] +
147601e04c3fSmrg                    (uint64_t) rgba[i][GCOMP] +
147701e04c3fSmrg                    (uint64_t) rgba[i][BCOMP];
147801e04c3fSmrg         } else {
147901e04c3fSmrg            lum64 = (int64_t) ((int32_t) rgba[i][RCOMP]) +
148001e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][GCOMP]) +
148101e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][BCOMP]);
148201e04c3fSmrg         }
148301e04c3fSmrg         lum32 = convert_integer_luminance64(lum64, dst_bits,
148401e04c3fSmrg                                             dst_is_signed, rgba_is_signed);
148501e04c3fSmrg         switch (dst_type) {
148601e04c3fSmrg         case GL_BYTE:
148701e04c3fSmrg         case GL_UNSIGNED_BYTE: {
148801e04c3fSmrg            GLbyte *dst = (GLbyte *) dstAddr;
148901e04c3fSmrg            dst[i] = lum32;
149001e04c3fSmrg            break;
149101e04c3fSmrg         }
149201e04c3fSmrg         case GL_SHORT:
149301e04c3fSmrg         case GL_UNSIGNED_SHORT: {
149401e04c3fSmrg            GLshort *dst = (GLshort *) dstAddr;
149501e04c3fSmrg            dst[i] = lum32;
149601e04c3fSmrg            break;
149701e04c3fSmrg         }
149801e04c3fSmrg         case GL_INT:
149901e04c3fSmrg         case GL_UNSIGNED_INT: {
150001e04c3fSmrg            GLint *dst = (GLint *) dstAddr;
150101e04c3fSmrg            dst[i] = lum32;
150201e04c3fSmrg            break;
150301e04c3fSmrg         }
150401e04c3fSmrg         }
1505af69d88dSmrg      }
150601e04c3fSmrg      return;
150701e04c3fSmrg   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
1508af69d88dSmrg      for (i = 0; i < n; i++) {
150901e04c3fSmrg         if (!rgba_is_signed) {
151001e04c3fSmrg            lum64 = (uint64_t) rgba[i][RCOMP] +
151101e04c3fSmrg                    (uint64_t) rgba[i][GCOMP] +
151201e04c3fSmrg                    (uint64_t) rgba[i][BCOMP];
151301e04c3fSmrg         } else {
151401e04c3fSmrg            lum64 = (int64_t) ((int32_t) rgba[i][RCOMP]) +
151501e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][GCOMP]) +
151601e04c3fSmrg                    (int64_t) ((int32_t) rgba[i][BCOMP]);
151701e04c3fSmrg         }
151801e04c3fSmrg         lum32 = convert_integer_luminance64(lum64, dst_bits,
151901e04c3fSmrg                                             dst_is_signed, rgba_is_signed);
152001e04c3fSmrg         alpha = convert_integer(rgba[i][ACOMP], dst_bits,
152101e04c3fSmrg                                 dst_is_signed, rgba_is_signed);
152201e04c3fSmrg         switch (dst_type) {
152301e04c3fSmrg         case GL_BYTE:
152401e04c3fSmrg         case GL_UNSIGNED_BYTE: {
152501e04c3fSmrg            GLbyte *dst = (GLbyte *) dstAddr;
152601e04c3fSmrg            dst[2*i] = lum32;
152701e04c3fSmrg            dst[2*i+1] = alpha;
152801e04c3fSmrg            break;
152901e04c3fSmrg         }
153001e04c3fSmrg         case GL_SHORT:
153101e04c3fSmrg         case GL_UNSIGNED_SHORT: {
153201e04c3fSmrg            GLshort *dst = (GLshort *) dstAddr;
153301e04c3fSmrg            dst[i] = lum32;
153401e04c3fSmrg            dst[2*i+1] = alpha;
153501e04c3fSmrg            break;
153601e04c3fSmrg         }
153701e04c3fSmrg         case GL_INT:
153801e04c3fSmrg         case GL_UNSIGNED_INT: {
153901e04c3fSmrg            GLint *dst = (GLint *) dstAddr;
154001e04c3fSmrg            dst[i] = lum32;
154101e04c3fSmrg            dst[2*i+1] = alpha;
154201e04c3fSmrg            break;
154301e04c3fSmrg         }
154401e04c3fSmrg         }
1545af69d88dSmrg      }
154601e04c3fSmrg      return;
1547af69d88dSmrg   }
1548af69d88dSmrg}
1549af69d88dSmrg
155001e04c3fSmrgGLfloat *
155101e04c3fSmrg_mesa_unpack_color_index_to_rgba_float(struct gl_context *ctx, GLuint dims,
155201e04c3fSmrg                                       const void *src, GLenum srcFormat, GLenum srcType,
155301e04c3fSmrg                                       int srcWidth, int srcHeight, int srcDepth,
155401e04c3fSmrg                                       const struct gl_pixelstore_attrib *srcPacking,
155501e04c3fSmrg                                       GLbitfield transferOps)
155601e04c3fSmrg{
155701e04c3fSmrg   int count, img;
155801e04c3fSmrg   GLuint *indexes;
155901e04c3fSmrg   GLfloat *rgba, *dstPtr;
156001e04c3fSmrg
156101e04c3fSmrg   count = srcWidth * srcHeight;
156201e04c3fSmrg   indexes = malloc(count * sizeof(GLuint));
156301e04c3fSmrg   if (!indexes) {
156401e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
156501e04c3fSmrg      return NULL;
156601e04c3fSmrg   }
156701e04c3fSmrg
156801e04c3fSmrg   rgba = malloc(4 * count * srcDepth * sizeof(GLfloat));
156901e04c3fSmrg   if (!rgba) {
157001e04c3fSmrg      free(indexes);
157101e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
157201e04c3fSmrg      return NULL;
157301e04c3fSmrg   }
157401e04c3fSmrg
157501e04c3fSmrg   /* Convert indexes to RGBA float */
157601e04c3fSmrg   dstPtr = rgba;
157701e04c3fSmrg   for (img = 0; img < srcDepth; img++) {
157801e04c3fSmrg      const GLubyte *srcPtr =
157901e04c3fSmrg         (const GLubyte *) _mesa_image_address(dims, srcPacking, src,
158001e04c3fSmrg                                               srcWidth, srcHeight,
158101e04c3fSmrg                                               srcFormat, srcType,
158201e04c3fSmrg                                               img, 0, 0);
158301e04c3fSmrg
158401e04c3fSmrg      extract_uint_indexes(count, indexes, srcFormat, srcType, srcPtr, srcPacking);
158501e04c3fSmrg
158601e04c3fSmrg      if (transferOps & IMAGE_SHIFT_OFFSET_BIT)
158701e04c3fSmrg         _mesa_shift_and_offset_ci(ctx, count, indexes);
158801e04c3fSmrg
158901e04c3fSmrg      _mesa_map_ci_to_rgba(ctx, count, indexes, (float (*)[4])dstPtr);
1590af69d88dSmrg
159101e04c3fSmrg      /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting
159201e04c3fSmrg       * with color indexes.
159301e04c3fSmrg       */
159401e04c3fSmrg      transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT);
159501e04c3fSmrg      _mesa_apply_rgba_transfer_ops(ctx, transferOps, count, (float (*)[4])dstPtr);
159601e04c3fSmrg
159701e04c3fSmrg      dstPtr += srcHeight * srcWidth * 4;
159801e04c3fSmrg   }
159901e04c3fSmrg
160001e04c3fSmrg   free(indexes);
160101e04c3fSmrg
160201e04c3fSmrg   return rgba;
160301e04c3fSmrg}
160401e04c3fSmrg
160501e04c3fSmrgGLubyte *
160601e04c3fSmrg_mesa_unpack_color_index_to_rgba_ubyte(struct gl_context *ctx, GLuint dims,
160701e04c3fSmrg                                       const void *src, GLenum srcFormat, GLenum srcType,
160801e04c3fSmrg                                       int srcWidth, int srcHeight, int srcDepth,
160901e04c3fSmrg                                       const struct gl_pixelstore_attrib *srcPacking,
161001e04c3fSmrg                                       GLbitfield transferOps)
161101e04c3fSmrg{
161201e04c3fSmrg   GLfloat *rgba;
161301e04c3fSmrg   GLubyte *dst;
161401e04c3fSmrg   int count, i;
161501e04c3fSmrg
161601e04c3fSmrg   transferOps |= IMAGE_CLAMP_BIT;
161701e04c3fSmrg   rgba = _mesa_unpack_color_index_to_rgba_float(ctx, dims,
161801e04c3fSmrg                                                 src, srcFormat, srcType,
161901e04c3fSmrg                                                 srcWidth, srcHeight, srcDepth,
162001e04c3fSmrg                                                 srcPacking, transferOps);
162101e04c3fSmrg
162201e04c3fSmrg   count = srcWidth * srcHeight * srcDepth;
162301e04c3fSmrg   dst = malloc(count * 4 * sizeof(GLubyte));
162401e04c3fSmrg   for (i = 0; i < count; i++) {
162501e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 0], rgba[i * 4 + 0]);
162601e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 1], rgba[i * 4 + 1]);
162701e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 2], rgba[i * 4 + 2]);
162801e04c3fSmrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 3], rgba[i * 4 + 3]);
162901e04c3fSmrg   }
163001e04c3fSmrg
163101e04c3fSmrg   free(rgba);
163201e04c3fSmrg
163301e04c3fSmrg   return dst;
163401e04c3fSmrg}
16357ec681f3Smrg
16367ec681f3Smrgvoid
16377ec681f3Smrg_mesa_unpack_ubyte_rgba_row(mesa_format format, uint32_t n,
16387ec681f3Smrg                            const void *src, uint8_t dst[][4])
16397ec681f3Smrg{
16407ec681f3Smrg   const struct util_format_unpack_description *unpack =
16417ec681f3Smrg      util_format_unpack_description((enum pipe_format)format);
16427ec681f3Smrg
16437ec681f3Smrg   if (unpack->unpack_rgba_8unorm) {
16447ec681f3Smrg      unpack->unpack_rgba_8unorm((uint8_t *)dst, src, n);
16457ec681f3Smrg   } else {
16467ec681f3Smrg      /* get float values, convert to ubyte */
16477ec681f3Smrg      {
16487ec681f3Smrg         float *tmp = malloc(n * 4 * sizeof(float));
16497ec681f3Smrg         if (tmp) {
16507ec681f3Smrg            uint32_t i;
16517ec681f3Smrg            _mesa_unpack_rgba_row(format, n, src, (float (*)[4]) tmp);
16527ec681f3Smrg            for (i = 0; i < n; i++) {
16537ec681f3Smrg               dst[i][0] = _mesa_float_to_unorm(tmp[i*4+0], 8);
16547ec681f3Smrg               dst[i][1] = _mesa_float_to_unorm(tmp[i*4+1], 8);
16557ec681f3Smrg               dst[i][2] = _mesa_float_to_unorm(tmp[i*4+2], 8);
16567ec681f3Smrg               dst[i][3] = _mesa_float_to_unorm(tmp[i*4+3], 8);
16577ec681f3Smrg            }
16587ec681f3Smrg            free(tmp);
16597ec681f3Smrg         }
16607ec681f3Smrg      }
16617ec681f3Smrg   }
16627ec681f3Smrg}
16637ec681f3Smrg
16647ec681f3Smrg/** Helper struct for MESA_FORMAT_Z32_FLOAT_S8X24_UINT */
16657ec681f3Smrgstruct z32f_x24s8
16667ec681f3Smrg{
16677ec681f3Smrg   float z;
16687ec681f3Smrg   uint32_t x24s8;
16697ec681f3Smrg};
16707ec681f3Smrg
16717ec681f3Smrg
16727ec681f3Smrgstatic void
16737ec681f3Smrgunpack_uint_24_8_depth_stencil_Z24_UNORM_S8_UINT(const uint32_t *src, uint32_t *dst, uint32_t n)
16747ec681f3Smrg{
16757ec681f3Smrg   uint32_t i;
16767ec681f3Smrg
16777ec681f3Smrg   for (i = 0; i < n; i++) {
16787ec681f3Smrg      uint32_t val = src[i];
16797ec681f3Smrg      dst[i] = val >> 24 | val << 8;
16807ec681f3Smrg   }
16817ec681f3Smrg}
16827ec681f3Smrg
16837ec681f3Smrgstatic void
16847ec681f3Smrgunpack_uint_24_8_depth_stencil_Z32_S8X24(const uint32_t *src,
16857ec681f3Smrg                                         uint32_t *dst, uint32_t n)
16867ec681f3Smrg{
16877ec681f3Smrg   uint32_t i;
16887ec681f3Smrg
16897ec681f3Smrg   for (i = 0; i < n; i++) {
16907ec681f3Smrg      /* 8 bytes per pixel (float + uint32) */
16917ec681f3Smrg      float zf = ((float *) src)[i * 2 + 0];
16927ec681f3Smrg      uint32_t z24 = (uint32_t) (zf * (float) 0xffffff);
16937ec681f3Smrg      uint32_t s = src[i * 2 + 1] & 0xff;
16947ec681f3Smrg      dst[i] = (z24 << 8) | s;
16957ec681f3Smrg   }
16967ec681f3Smrg}
16977ec681f3Smrg
16987ec681f3Smrgstatic void
16997ec681f3Smrgunpack_uint_24_8_depth_stencil_S8_UINT_Z24_UNORM(const uint32_t *src, uint32_t *dst, uint32_t n)
17007ec681f3Smrg{
17017ec681f3Smrg   memcpy(dst, src, n * 4);
17027ec681f3Smrg}
17037ec681f3Smrg
17047ec681f3Smrg/**
17057ec681f3Smrg * Unpack depth/stencil returning as GL_UNSIGNED_INT_24_8.
17067ec681f3Smrg * \param format  the source data format
17077ec681f3Smrg */
17087ec681f3Smrgvoid
17097ec681f3Smrg_mesa_unpack_uint_24_8_depth_stencil_row(mesa_format format, uint32_t n,
17107ec681f3Smrg                                         const void *src, uint32_t *dst)
17117ec681f3Smrg{
17127ec681f3Smrg   switch (format) {
17137ec681f3Smrg   case MESA_FORMAT_S8_UINT_Z24_UNORM:
17147ec681f3Smrg      unpack_uint_24_8_depth_stencil_S8_UINT_Z24_UNORM(src, dst, n);
17157ec681f3Smrg      break;
17167ec681f3Smrg   case MESA_FORMAT_Z24_UNORM_S8_UINT:
17177ec681f3Smrg      unpack_uint_24_8_depth_stencil_Z24_UNORM_S8_UINT(src, dst, n);
17187ec681f3Smrg      break;
17197ec681f3Smrg   case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
17207ec681f3Smrg      unpack_uint_24_8_depth_stencil_Z32_S8X24(src, dst, n);
17217ec681f3Smrg      break;
17227ec681f3Smrg   default:
17237ec681f3Smrg      unreachable("bad format %s in _mesa_unpack_uint_24_8_depth_stencil_row");
17247ec681f3Smrg   }
17257ec681f3Smrg}
17267ec681f3Smrg
17277ec681f3Smrgstatic void
17287ec681f3Smrgunpack_float_32_uint_24_8_Z24_UNORM_S8_UINT(const uint32_t *src,
17297ec681f3Smrg                                            uint32_t *dst, uint32_t n)
17307ec681f3Smrg{
17317ec681f3Smrg   uint32_t i;
17327ec681f3Smrg   struct z32f_x24s8 *d = (struct z32f_x24s8 *) dst;
17337ec681f3Smrg   const double scale = 1.0 / (double) 0xffffff;
17347ec681f3Smrg
17357ec681f3Smrg   for (i = 0; i < n; i++) {
17367ec681f3Smrg      const uint32_t z24 = src[i] & 0xffffff;
17377ec681f3Smrg      d[i].z = z24 * scale;
17387ec681f3Smrg      d[i].x24s8 = src[i] >> 24;
17397ec681f3Smrg      assert(d[i].z >= 0.0f);
17407ec681f3Smrg      assert(d[i].z <= 1.0f);
17417ec681f3Smrg   }
17427ec681f3Smrg}
17437ec681f3Smrg
17447ec681f3Smrgstatic void
17457ec681f3Smrgunpack_float_32_uint_24_8_Z32_FLOAT_S8X24_UINT(const uint32_t *src,
17467ec681f3Smrg                                               uint32_t *dst, uint32_t n)
17477ec681f3Smrg{
17487ec681f3Smrg   memcpy(dst, src, n * sizeof(struct z32f_x24s8));
17497ec681f3Smrg}
17507ec681f3Smrg
17517ec681f3Smrgstatic void
17527ec681f3Smrgunpack_float_32_uint_24_8_S8_UINT_Z24_UNORM(const uint32_t *src,
17537ec681f3Smrg                                            uint32_t *dst, uint32_t n)
17547ec681f3Smrg{
17557ec681f3Smrg   uint32_t i;
17567ec681f3Smrg   struct z32f_x24s8 *d = (struct z32f_x24s8 *) dst;
17577ec681f3Smrg   const double scale = 1.0 / (double) 0xffffff;
17587ec681f3Smrg
17597ec681f3Smrg   for (i = 0; i < n; i++) {
17607ec681f3Smrg      const uint32_t z24 = src[i] >> 8;
17617ec681f3Smrg      d[i].z = z24 * scale;
17627ec681f3Smrg      d[i].x24s8 = src[i] & 0xff;
17637ec681f3Smrg      assert(d[i].z >= 0.0f);
17647ec681f3Smrg      assert(d[i].z <= 1.0f);
17657ec681f3Smrg   }
17667ec681f3Smrg}
17677ec681f3Smrg
17687ec681f3Smrg/**
17697ec681f3Smrg * Unpack depth/stencil returning as GL_FLOAT_32_UNSIGNED_INT_24_8_REV.
17707ec681f3Smrg * \param format  the source data format
17717ec681f3Smrg *
17727ec681f3Smrg * In GL_FLOAT_32_UNSIGNED_INT_24_8_REV lower 4 bytes contain float
17737ec681f3Smrg * component and higher 4 bytes contain packed 24-bit and 8-bit
17747ec681f3Smrg * components.
17757ec681f3Smrg *
17767ec681f3Smrg *    31 30 29 28 ... 4 3 2 1 0    31 30 29 ... 9 8 7 6 5 ... 2 1 0
17777ec681f3Smrg *    +-------------------------+  +--------------------------------+
17787ec681f3Smrg *    |    Float Component      |  | Unused         | 8 bit stencil |
17797ec681f3Smrg *    +-------------------------+  +--------------------------------+
17807ec681f3Smrg *          lower 4 bytes                  higher 4 bytes
17817ec681f3Smrg */
17827ec681f3Smrgvoid
17837ec681f3Smrg_mesa_unpack_float_32_uint_24_8_depth_stencil_row(mesa_format format, uint32_t n,
17847ec681f3Smrg                                                  const void *src, uint32_t *dst)
17857ec681f3Smrg{
17867ec681f3Smrg   switch (format) {
17877ec681f3Smrg   case MESA_FORMAT_S8_UINT_Z24_UNORM:
17887ec681f3Smrg      unpack_float_32_uint_24_8_S8_UINT_Z24_UNORM(src, dst, n);
17897ec681f3Smrg      break;
17907ec681f3Smrg   case MESA_FORMAT_Z24_UNORM_S8_UINT:
17917ec681f3Smrg      unpack_float_32_uint_24_8_Z24_UNORM_S8_UINT(src, dst, n);
17927ec681f3Smrg      break;
17937ec681f3Smrg   case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
17947ec681f3Smrg      unpack_float_32_uint_24_8_Z32_FLOAT_S8X24_UINT(src, dst, n);
17957ec681f3Smrg      break;
17967ec681f3Smrg   default:
17977ec681f3Smrg      unreachable("bad format %s in _mesa_unpack_uint_24_8_depth_stencil_row");
17987ec681f3Smrg   }
17997ec681f3Smrg}
1800