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