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