pack.c revision b8e80941
1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg * Copyright (C) 2009-2010  VMware, Inc.  All Rights Reserved.
6848b8605Smrg *
7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8848b8605Smrg * copy of this software and associated documentation files (the "Software"),
9848b8605Smrg * to deal in the Software without restriction, including without limitation
10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
12848b8605Smrg * Software is furnished to do so, subject to the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice shall be included
15848b8605Smrg * in all copies or substantial portions of the Software.
16848b8605Smrg *
17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20848b8605Smrg * THEA AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21848b8605Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22848b8605Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file pack.c
28848b8605Smrg * Image and pixel span packing and unpacking.
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg
32848b8605Smrg/*
33848b8605Smrg * XXX: MSVC takes forever to compile this module for x86_64 unless we disable
34848b8605Smrg * this global optimization.
35848b8605Smrg *
36848b8605Smrg * See also:
37848b8605Smrg * - http://msdn.microsoft.com/en-us/library/1yk3ydd7.aspx
38848b8605Smrg * - http://msdn.microsoft.com/en-us/library/chh3fb0k.aspx
39848b8605Smrg */
40848b8605Smrg#if defined(_MSC_VER) && defined(_M_X64)
41848b8605Smrg#  pragma optimize( "g", off )
42848b8605Smrg#endif
43848b8605Smrg
44848b8605Smrg
45b8e80941Smrg#include "errors.h"
46848b8605Smrg#include "glheader.h"
47848b8605Smrg#include "enums.h"
48848b8605Smrg#include "image.h"
49848b8605Smrg#include "imports.h"
50848b8605Smrg#include "macros.h"
51848b8605Smrg#include "mtypes.h"
52848b8605Smrg#include "pack.h"
53848b8605Smrg#include "pixeltransfer.h"
54848b8605Smrg#include "imports.h"
55848b8605Smrg#include "glformats.h"
56b8e80941Smrg#include "format_utils.h"
57b8e80941Smrg#include "format_pack.h"
58848b8605Smrg
59848b8605Smrg
60848b8605Smrg/**
61848b8605Smrg * Flip the 8 bits in each byte of the given array.
62848b8605Smrg *
63848b8605Smrg * \param p array.
64848b8605Smrg * \param n number of bytes.
65848b8605Smrg *
66848b8605Smrg * \todo try this trick to flip bytes someday:
67848b8605Smrg * \code
68848b8605Smrg *  v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555);
69848b8605Smrg *  v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333);
70848b8605Smrg *  v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f);
71848b8605Smrg * \endcode
72848b8605Smrg */
73848b8605Smrgstatic void
74848b8605Smrgflip_bytes( GLubyte *p, GLuint n )
75848b8605Smrg{
76848b8605Smrg   GLuint i, a, b;
77848b8605Smrg   for (i = 0; i < n; i++) {
78848b8605Smrg      b = (GLuint) p[i];        /* words are often faster than bytes */
79848b8605Smrg      a = ((b & 0x01) << 7) |
80848b8605Smrg	  ((b & 0x02) << 5) |
81848b8605Smrg	  ((b & 0x04) << 3) |
82848b8605Smrg	  ((b & 0x08) << 1) |
83848b8605Smrg	  ((b & 0x10) >> 1) |
84848b8605Smrg	  ((b & 0x20) >> 3) |
85848b8605Smrg	  ((b & 0x40) >> 5) |
86848b8605Smrg	  ((b & 0x80) >> 7);
87848b8605Smrg      p[i] = (GLubyte) a;
88848b8605Smrg   }
89848b8605Smrg}
90848b8605Smrg
91848b8605Smrg
92848b8605Smrg
93848b8605Smrg/*
94848b8605Smrg * Unpack a 32x32 pixel polygon stipple from user memory using the
95848b8605Smrg * current pixel unpack settings.
96848b8605Smrg */
97848b8605Smrgvoid
98848b8605Smrg_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32],
99848b8605Smrg                              const struct gl_pixelstore_attrib *unpacking )
100848b8605Smrg{
101b8e80941Smrg   GLubyte *ptrn = (GLubyte *) _mesa_unpack_image(2, 32, 32, 1, GL_COLOR_INDEX,
102b8e80941Smrg                                                  GL_BITMAP, pattern, unpacking);
103848b8605Smrg   if (ptrn) {
104848b8605Smrg      /* Convert pattern from GLubytes to GLuints and handle big/little
105848b8605Smrg       * endian differences
106848b8605Smrg       */
107848b8605Smrg      GLubyte *p = ptrn;
108848b8605Smrg      GLint i;
109848b8605Smrg      for (i = 0; i < 32; i++) {
110848b8605Smrg         dest[i] = (p[0] << 24)
111848b8605Smrg                 | (p[1] << 16)
112848b8605Smrg                 | (p[2] <<  8)
113848b8605Smrg                 | (p[3]      );
114848b8605Smrg         p += 4;
115848b8605Smrg      }
116848b8605Smrg      free(ptrn);
117848b8605Smrg   }
118848b8605Smrg}
119848b8605Smrg
120848b8605Smrg
121848b8605Smrg/*
122848b8605Smrg * Pack polygon stipple into user memory given current pixel packing
123848b8605Smrg * settings.
124848b8605Smrg */
125848b8605Smrgvoid
126848b8605Smrg_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest,
127848b8605Smrg                            const struct gl_pixelstore_attrib *packing )
128848b8605Smrg{
129848b8605Smrg   /* Convert pattern from GLuints to GLubytes to handle big/little
130848b8605Smrg    * endian differences.
131848b8605Smrg    */
132848b8605Smrg   GLubyte ptrn[32*4];
133848b8605Smrg   GLint i;
134848b8605Smrg   for (i = 0; i < 32; i++) {
135848b8605Smrg      ptrn[i * 4 + 0] = (GLubyte) ((pattern[i] >> 24) & 0xff);
136848b8605Smrg      ptrn[i * 4 + 1] = (GLubyte) ((pattern[i] >> 16) & 0xff);
137848b8605Smrg      ptrn[i * 4 + 2] = (GLubyte) ((pattern[i] >> 8 ) & 0xff);
138848b8605Smrg      ptrn[i * 4 + 3] = (GLubyte) ((pattern[i]      ) & 0xff);
139848b8605Smrg   }
140848b8605Smrg
141848b8605Smrg   _mesa_pack_bitmap(32, 32, ptrn, dest, packing);
142848b8605Smrg}
143848b8605Smrg
144848b8605Smrg
145848b8605Smrg/*
146848b8605Smrg * Pack bitmap data.
147848b8605Smrg */
148848b8605Smrgvoid
149848b8605Smrg_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
150848b8605Smrg                   GLubyte *dest, const struct gl_pixelstore_attrib *packing )
151848b8605Smrg{
152848b8605Smrg   GLint row, width_in_bytes;
153848b8605Smrg   const GLubyte *src;
154848b8605Smrg
155848b8605Smrg   if (!source)
156848b8605Smrg      return;
157848b8605Smrg
158b8e80941Smrg   width_in_bytes = DIV_ROUND_UP( width, 8 );
159848b8605Smrg   src = source;
160848b8605Smrg   for (row = 0; row < height; row++) {
161848b8605Smrg      GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest,
162848b8605Smrg                       width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
163848b8605Smrg      if (!dst)
164848b8605Smrg         return;
165848b8605Smrg
166848b8605Smrg      if ((packing->SkipPixels & 7) == 0) {
167848b8605Smrg         memcpy( dst, src, width_in_bytes );
168848b8605Smrg         if (packing->LsbFirst) {
169848b8605Smrg            flip_bytes( dst, width_in_bytes );
170848b8605Smrg         }
171848b8605Smrg      }
172848b8605Smrg      else {
173848b8605Smrg         /* handling SkipPixels is a bit tricky (no pun intended!) */
174848b8605Smrg         GLint i;
175848b8605Smrg         if (packing->LsbFirst) {
176848b8605Smrg            GLubyte srcMask = 128;
177848b8605Smrg            GLubyte dstMask = 1 << (packing->SkipPixels & 0x7);
178848b8605Smrg            const GLubyte *s = src;
179848b8605Smrg            GLubyte *d = dst;
180848b8605Smrg            *d = 0;
181848b8605Smrg            for (i = 0; i < width; i++) {
182848b8605Smrg               if (*s & srcMask) {
183848b8605Smrg                  *d |= dstMask;
184848b8605Smrg               }
185848b8605Smrg               if (srcMask == 1) {
186848b8605Smrg                  srcMask = 128;
187848b8605Smrg                  s++;
188848b8605Smrg               }
189848b8605Smrg               else {
190848b8605Smrg                  srcMask = srcMask >> 1;
191848b8605Smrg               }
192848b8605Smrg               if (dstMask == 128) {
193848b8605Smrg                  dstMask = 1;
194848b8605Smrg                  d++;
195848b8605Smrg                  *d = 0;
196848b8605Smrg               }
197848b8605Smrg               else {
198848b8605Smrg                  dstMask = dstMask << 1;
199848b8605Smrg               }
200848b8605Smrg            }
201848b8605Smrg         }
202848b8605Smrg         else {
203848b8605Smrg            GLubyte srcMask = 128;
204848b8605Smrg            GLubyte dstMask = 128 >> (packing->SkipPixels & 0x7);
205848b8605Smrg            const GLubyte *s = src;
206848b8605Smrg            GLubyte *d = dst;
207848b8605Smrg            *d = 0;
208848b8605Smrg            for (i = 0; i < width; i++) {
209848b8605Smrg               if (*s & srcMask) {
210848b8605Smrg                  *d |= dstMask;
211848b8605Smrg               }
212848b8605Smrg               if (srcMask == 1) {
213848b8605Smrg                  srcMask = 128;
214848b8605Smrg                  s++;
215848b8605Smrg               }
216848b8605Smrg               else {
217848b8605Smrg                  srcMask = srcMask >> 1;
218848b8605Smrg               }
219848b8605Smrg               if (dstMask == 1) {
220848b8605Smrg                  dstMask = 128;
221848b8605Smrg                  d++;
222848b8605Smrg                  *d = 0;
223848b8605Smrg               }
224848b8605Smrg               else {
225848b8605Smrg                  dstMask = dstMask >> 1;
226848b8605Smrg               }
227848b8605Smrg            }
228848b8605Smrg         }
229848b8605Smrg      }
230848b8605Smrg      src += width_in_bytes;
231848b8605Smrg   }
232848b8605Smrg}
233848b8605Smrg
234848b8605Smrg
235b8e80941Smrg#define SWAP2BYTE(VALUE)			\
236b8e80941Smrg   {						\
237b8e80941Smrg      GLubyte *bytes = (GLubyte *) &(VALUE);	\
238b8e80941Smrg      GLubyte tmp = bytes[0];			\
239b8e80941Smrg      bytes[0] = bytes[1];			\
240b8e80941Smrg      bytes[1] = tmp;				\
241848b8605Smrg   }
242848b8605Smrg
243b8e80941Smrg#define SWAP4BYTE(VALUE)			\
244b8e80941Smrg   {						\
245b8e80941Smrg      GLubyte *bytes = (GLubyte *) &(VALUE);	\
246b8e80941Smrg      GLubyte tmp = bytes[0];			\
247b8e80941Smrg      bytes[0] = bytes[3];			\
248b8e80941Smrg      bytes[3] = tmp;				\
249b8e80941Smrg      tmp = bytes[1];				\
250b8e80941Smrg      bytes[1] = bytes[2];			\
251b8e80941Smrg      bytes[2] = tmp;				\
252848b8605Smrg   }
253848b8605Smrg
254848b8605Smrg
255848b8605Smrgstatic void
256b8e80941Smrgextract_uint_indexes(GLuint n, GLuint indexes[],
257b8e80941Smrg                     GLenum srcFormat, GLenum srcType, const GLvoid *src,
258b8e80941Smrg                     const struct gl_pixelstore_attrib *unpack )
259848b8605Smrg{
260b8e80941Smrg   assert(srcFormat == GL_COLOR_INDEX || srcFormat == GL_STENCIL_INDEX);
261848b8605Smrg
262b8e80941Smrg   assert(srcType == GL_BITMAP ||
263b8e80941Smrg          srcType == GL_UNSIGNED_BYTE ||
264b8e80941Smrg          srcType == GL_BYTE ||
265b8e80941Smrg          srcType == GL_UNSIGNED_SHORT ||
266b8e80941Smrg          srcType == GL_SHORT ||
267b8e80941Smrg          srcType == GL_UNSIGNED_INT ||
268b8e80941Smrg          srcType == GL_INT ||
269b8e80941Smrg          srcType == GL_UNSIGNED_INT_24_8_EXT ||
270b8e80941Smrg          srcType == GL_HALF_FLOAT_ARB ||
271b8e80941Smrg          srcType == GL_HALF_FLOAT_OES ||
272b8e80941Smrg          srcType == GL_FLOAT ||
273b8e80941Smrg          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
274848b8605Smrg
275b8e80941Smrg   switch (srcType) {
276b8e80941Smrg      case GL_BITMAP:
277b8e80941Smrg         {
278b8e80941Smrg            GLubyte *ubsrc = (GLubyte *) src;
279b8e80941Smrg            if (unpack->LsbFirst) {
280b8e80941Smrg               GLubyte mask = 1 << (unpack->SkipPixels & 0x7);
281b8e80941Smrg               GLuint i;
282b8e80941Smrg               for (i = 0; i < n; i++) {
283b8e80941Smrg                  indexes[i] = (*ubsrc & mask) ? 1 : 0;
284b8e80941Smrg                  if (mask == 128) {
285b8e80941Smrg                     mask = 1;
286b8e80941Smrg                     ubsrc++;
287b8e80941Smrg                  }
288b8e80941Smrg                  else {
289b8e80941Smrg                     mask = mask << 1;
290b8e80941Smrg                  }
291b8e80941Smrg               }
292b8e80941Smrg            }
293b8e80941Smrg            else {
294b8e80941Smrg               GLubyte mask = 128 >> (unpack->SkipPixels & 0x7);
295b8e80941Smrg               GLuint i;
296b8e80941Smrg               for (i = 0; i < n; i++) {
297b8e80941Smrg                  indexes[i] = (*ubsrc & mask) ? 1 : 0;
298b8e80941Smrg                  if (mask == 1) {
299b8e80941Smrg                     mask = 128;
300b8e80941Smrg                     ubsrc++;
301b8e80941Smrg                  }
302b8e80941Smrg                  else {
303b8e80941Smrg                     mask = mask >> 1;
304b8e80941Smrg                  }
305b8e80941Smrg               }
306b8e80941Smrg            }
307848b8605Smrg         }
308b8e80941Smrg         break;
309b8e80941Smrg      case GL_UNSIGNED_BYTE:
310b8e80941Smrg         {
311b8e80941Smrg            GLuint i;
312b8e80941Smrg            const GLubyte *s = (const GLubyte *) src;
313b8e80941Smrg            for (i = 0; i < n; i++)
314b8e80941Smrg               indexes[i] = s[i];
315848b8605Smrg         }
316b8e80941Smrg         break;
317b8e80941Smrg      case GL_BYTE:
318b8e80941Smrg         {
319b8e80941Smrg            GLuint i;
320b8e80941Smrg            const GLbyte *s = (const GLbyte *) src;
321b8e80941Smrg            for (i = 0; i < n; i++)
322b8e80941Smrg               indexes[i] = s[i];
323848b8605Smrg         }
324b8e80941Smrg         break;
325b8e80941Smrg      case GL_UNSIGNED_SHORT:
326b8e80941Smrg         {
327b8e80941Smrg            GLuint i;
328b8e80941Smrg            const GLushort *s = (const GLushort *) src;
329b8e80941Smrg            if (unpack->SwapBytes) {
330b8e80941Smrg               for (i = 0; i < n; i++) {
331b8e80941Smrg                  GLushort value = s[i];
332b8e80941Smrg                  SWAP2BYTE(value);
333b8e80941Smrg                  indexes[i] = value;
334b8e80941Smrg               }
335b8e80941Smrg            }
336b8e80941Smrg            else {
337b8e80941Smrg               for (i = 0; i < n; i++)
338b8e80941Smrg                  indexes[i] = s[i];
339b8e80941Smrg            }
340848b8605Smrg         }
341b8e80941Smrg         break;
342b8e80941Smrg      case GL_SHORT:
343b8e80941Smrg         {
344b8e80941Smrg            GLuint i;
345b8e80941Smrg            const GLshort *s = (const GLshort *) src;
346b8e80941Smrg            if (unpack->SwapBytes) {
347b8e80941Smrg               for (i = 0; i < n; i++) {
348b8e80941Smrg                  GLshort value = s[i];
349b8e80941Smrg                  SWAP2BYTE(value);
350b8e80941Smrg                  indexes[i] = value;
351b8e80941Smrg               }
352b8e80941Smrg            }
353b8e80941Smrg            else {
354b8e80941Smrg               for (i = 0; i < n; i++)
355b8e80941Smrg                  indexes[i] = s[i];
356b8e80941Smrg            }
357848b8605Smrg         }
358b8e80941Smrg         break;
359b8e80941Smrg      case GL_UNSIGNED_INT:
360b8e80941Smrg         {
361b8e80941Smrg            GLuint i;
362b8e80941Smrg            const GLuint *s = (const GLuint *) src;
363b8e80941Smrg            if (unpack->SwapBytes) {
364848b8605Smrg               for (i = 0; i < n; i++) {
365b8e80941Smrg                  GLuint value = s[i];
366b8e80941Smrg                  SWAP4BYTE(value);
367b8e80941Smrg                  indexes[i] = value;
368848b8605Smrg               }
369848b8605Smrg            }
370b8e80941Smrg            else {
371b8e80941Smrg               for (i = 0; i < n; i++)
372b8e80941Smrg                  indexes[i] = s[i];
373848b8605Smrg            }
374848b8605Smrg         }
375b8e80941Smrg         break;
376b8e80941Smrg      case GL_INT:
377b8e80941Smrg         {
378b8e80941Smrg            GLuint i;
379b8e80941Smrg            const GLint *s = (const GLint *) src;
380b8e80941Smrg            if (unpack->SwapBytes) {
381b8e80941Smrg               for (i = 0; i < n; i++) {
382b8e80941Smrg                  GLint value = s[i];
383b8e80941Smrg                  SWAP4BYTE(value);
384b8e80941Smrg                  indexes[i] = value;
385b8e80941Smrg               }
386b8e80941Smrg            }
387b8e80941Smrg            else {
388b8e80941Smrg               for (i = 0; i < n; i++)
389b8e80941Smrg                  indexes[i] = s[i];
390b8e80941Smrg            }
391848b8605Smrg         }
392b8e80941Smrg         break;
393b8e80941Smrg      case GL_FLOAT:
394b8e80941Smrg         {
395b8e80941Smrg            GLuint i;
396b8e80941Smrg            const GLfloat *s = (const GLfloat *) src;
397b8e80941Smrg            if (unpack->SwapBytes) {
398b8e80941Smrg               for (i = 0; i < n; i++) {
399b8e80941Smrg                  GLfloat value = s[i];
400b8e80941Smrg                  SWAP4BYTE(value);
401b8e80941Smrg                  indexes[i] = (GLuint) value;
402b8e80941Smrg               }
403b8e80941Smrg            }
404b8e80941Smrg            else {
405b8e80941Smrg               for (i = 0; i < n; i++)
406b8e80941Smrg                  indexes[i] = (GLuint) s[i];
407b8e80941Smrg            }
408848b8605Smrg         }
409b8e80941Smrg         break;
410b8e80941Smrg      case GL_HALF_FLOAT_ARB:
411b8e80941Smrg      case GL_HALF_FLOAT_OES:
412b8e80941Smrg         {
413b8e80941Smrg            GLuint i;
414b8e80941Smrg            const GLhalfARB *s = (const GLhalfARB *) src;
415b8e80941Smrg            if (unpack->SwapBytes) {
416b8e80941Smrg               for (i = 0; i < n; i++) {
417b8e80941Smrg                  GLhalfARB value = s[i];
418b8e80941Smrg                  SWAP2BYTE(value);
419b8e80941Smrg                  indexes[i] = (GLuint) _mesa_half_to_float(value);
420b8e80941Smrg               }
421b8e80941Smrg            }
422b8e80941Smrg            else {
423b8e80941Smrg               for (i = 0; i < n; i++)
424b8e80941Smrg                  indexes[i] = (GLuint) _mesa_half_to_float(s[i]);
425b8e80941Smrg            }
426848b8605Smrg         }
427b8e80941Smrg         break;
428b8e80941Smrg      case GL_UNSIGNED_INT_24_8_EXT:
429b8e80941Smrg         {
430b8e80941Smrg            GLuint i;
431b8e80941Smrg            const GLuint *s = (const GLuint *) src;
432b8e80941Smrg            if (unpack->SwapBytes) {
433b8e80941Smrg               for (i = 0; i < n; i++) {
434b8e80941Smrg                  GLuint value = s[i];
435b8e80941Smrg                  SWAP4BYTE(value);
436b8e80941Smrg                  indexes[i] = value & 0xff;  /* lower 8 bits */
437b8e80941Smrg               }
438b8e80941Smrg            }
439b8e80941Smrg            else {
440b8e80941Smrg               for (i = 0; i < n; i++)
441b8e80941Smrg                  indexes[i] = s[i] & 0xff;  /* lower 8 bits */
442b8e80941Smrg            }
443848b8605Smrg         }
444b8e80941Smrg         break;
445b8e80941Smrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
446b8e80941Smrg         {
447b8e80941Smrg            GLuint i;
448b8e80941Smrg            const GLuint *s = (const GLuint *) src;
449b8e80941Smrg            if (unpack->SwapBytes) {
450b8e80941Smrg               for (i = 0; i < n; i++) {
451b8e80941Smrg                  GLuint value = s[i*2+1];
452b8e80941Smrg                  SWAP4BYTE(value);
453b8e80941Smrg                  indexes[i] = value & 0xff;  /* lower 8 bits */
454b8e80941Smrg               }
455b8e80941Smrg            }
456b8e80941Smrg            else {
457b8e80941Smrg               for (i = 0; i < n; i++)
458b8e80941Smrg                  indexes[i] = s[i*2+1] & 0xff;  /* lower 8 bits */
459b8e80941Smrg            }
460b8e80941Smrg         }
461b8e80941Smrg         break;
462848b8605Smrg
463b8e80941Smrg      default:
464b8e80941Smrg         unreachable("bad srcType in extract_uint_indexes");
465b8e80941Smrg   }
466848b8605Smrg}
467848b8605Smrg
468848b8605Smrg
469848b8605Smrg/*
470848b8605Smrg * Unpack a row of stencil data from a client buffer according to
471848b8605Smrg * the pixel unpacking parameters.
472848b8605Smrg * This is (or will be) used by glDrawPixels
473848b8605Smrg *
474848b8605Smrg * Args:  ctx - the context
475848b8605Smrg *        n - number of pixels
476848b8605Smrg *        dstType - destination data type
477848b8605Smrg *        dest - destination array
478848b8605Smrg *        srcType - source pixel type
479848b8605Smrg *        source - source data pointer
480848b8605Smrg *        srcPacking - pixel unpacking parameters
481848b8605Smrg *        transferOps - apply offset/bias/lookup ops?
482848b8605Smrg */
483848b8605Smrgvoid
484848b8605Smrg_mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n,
485848b8605Smrg                           GLenum dstType, GLvoid *dest,
486848b8605Smrg                           GLenum srcType, const GLvoid *source,
487848b8605Smrg                           const struct gl_pixelstore_attrib *srcPacking,
488848b8605Smrg                           GLbitfield transferOps )
489848b8605Smrg{
490b8e80941Smrg   assert(srcType == GL_BITMAP ||
491848b8605Smrg          srcType == GL_UNSIGNED_BYTE ||
492848b8605Smrg          srcType == GL_BYTE ||
493848b8605Smrg          srcType == GL_UNSIGNED_SHORT ||
494848b8605Smrg          srcType == GL_SHORT ||
495848b8605Smrg          srcType == GL_UNSIGNED_INT ||
496848b8605Smrg          srcType == GL_INT ||
497848b8605Smrg          srcType == GL_UNSIGNED_INT_24_8_EXT ||
498848b8605Smrg          srcType == GL_HALF_FLOAT_ARB ||
499b8e80941Smrg          srcType == GL_HALF_FLOAT_OES ||
500848b8605Smrg          srcType == GL_FLOAT ||
501848b8605Smrg          srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
502848b8605Smrg
503b8e80941Smrg   assert(dstType == GL_UNSIGNED_BYTE ||
504848b8605Smrg          dstType == GL_UNSIGNED_SHORT ||
505848b8605Smrg          dstType == GL_UNSIGNED_INT ||
506848b8605Smrg          dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
507848b8605Smrg
508848b8605Smrg   /* only shift and offset apply to stencil */
509848b8605Smrg   transferOps &= IMAGE_SHIFT_OFFSET_BIT;
510848b8605Smrg
511848b8605Smrg   /*
512848b8605Smrg    * Try simple cases first
513848b8605Smrg    */
514848b8605Smrg   if (transferOps == 0 &&
515848b8605Smrg       !ctx->Pixel.MapStencilFlag &&
516848b8605Smrg       srcType == GL_UNSIGNED_BYTE &&
517848b8605Smrg       dstType == GL_UNSIGNED_BYTE) {
518848b8605Smrg      memcpy(dest, source, n * sizeof(GLubyte));
519848b8605Smrg   }
520848b8605Smrg   else if (transferOps == 0 &&
521848b8605Smrg            !ctx->Pixel.MapStencilFlag &&
522848b8605Smrg            srcType == GL_UNSIGNED_INT &&
523848b8605Smrg            dstType == GL_UNSIGNED_INT &&
524848b8605Smrg            !srcPacking->SwapBytes) {
525848b8605Smrg      memcpy(dest, source, n * sizeof(GLuint));
526848b8605Smrg   }
527848b8605Smrg   else {
528848b8605Smrg      /*
529848b8605Smrg       * general solution
530848b8605Smrg       */
531848b8605Smrg      GLuint *indexes = malloc(n * sizeof(GLuint));
532848b8605Smrg
533848b8605Smrg      if (!indexes) {
534848b8605Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "stencil unpacking");
535848b8605Smrg         return;
536848b8605Smrg      }
537848b8605Smrg
538848b8605Smrg      extract_uint_indexes(n, indexes, GL_STENCIL_INDEX, srcType, source,
539848b8605Smrg                           srcPacking);
540848b8605Smrg
541848b8605Smrg      if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
542848b8605Smrg         /* shift and offset indexes */
543848b8605Smrg         _mesa_shift_and_offset_ci(ctx, n, indexes);
544848b8605Smrg      }
545848b8605Smrg
546848b8605Smrg      if (ctx->Pixel.MapStencilFlag) {
547848b8605Smrg         /* Apply stencil lookup table */
548848b8605Smrg         const GLuint mask = ctx->PixelMaps.StoS.Size - 1;
549848b8605Smrg         GLuint i;
550848b8605Smrg         for (i = 0; i < n; i++) {
551848b8605Smrg            indexes[i] = (GLuint)ctx->PixelMaps.StoS.Map[ indexes[i] & mask ];
552848b8605Smrg         }
553848b8605Smrg      }
554848b8605Smrg
555848b8605Smrg      /* convert to dest type */
556848b8605Smrg      switch (dstType) {
557848b8605Smrg         case GL_UNSIGNED_BYTE:
558848b8605Smrg            {
559848b8605Smrg               GLubyte *dst = (GLubyte *) dest;
560848b8605Smrg               GLuint i;
561848b8605Smrg               for (i = 0; i < n; i++) {
562848b8605Smrg                  dst[i] = (GLubyte) (indexes[i] & 0xff);
563848b8605Smrg               }
564848b8605Smrg            }
565848b8605Smrg            break;
566848b8605Smrg         case GL_UNSIGNED_SHORT:
567848b8605Smrg            {
568848b8605Smrg               GLuint *dst = (GLuint *) dest;
569848b8605Smrg               GLuint i;
570848b8605Smrg               for (i = 0; i < n; i++) {
571848b8605Smrg                  dst[i] = (GLushort) (indexes[i] & 0xffff);
572848b8605Smrg               }
573848b8605Smrg            }
574848b8605Smrg            break;
575848b8605Smrg         case GL_UNSIGNED_INT:
576848b8605Smrg            memcpy(dest, indexes, n * sizeof(GLuint));
577848b8605Smrg            break;
578848b8605Smrg         case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
579848b8605Smrg            {
580848b8605Smrg               GLuint *dst = (GLuint *) dest;
581848b8605Smrg               GLuint i;
582848b8605Smrg               for (i = 0; i < n; i++) {
583848b8605Smrg                  dst[i*2+1] = indexes[i] & 0xff; /* lower 8 bits */
584848b8605Smrg               }
585848b8605Smrg            }
586848b8605Smrg            break;
587848b8605Smrg         default:
588b8e80941Smrg            unreachable("bad dstType in _mesa_unpack_stencil_span");
589848b8605Smrg      }
590848b8605Smrg
591848b8605Smrg      free(indexes);
592848b8605Smrg   }
593848b8605Smrg}
594848b8605Smrg
595848b8605Smrg
596848b8605Smrgvoid
597848b8605Smrg_mesa_pack_stencil_span( struct gl_context *ctx, GLuint n,
598848b8605Smrg                         GLenum dstType, GLvoid *dest, const GLubyte *source,
599848b8605Smrg                         const struct gl_pixelstore_attrib *dstPacking )
600848b8605Smrg{
601848b8605Smrg   GLubyte *stencil = malloc(n * sizeof(GLubyte));
602848b8605Smrg
603848b8605Smrg   if (!stencil) {
604848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "stencil packing");
605848b8605Smrg      return;
606848b8605Smrg   }
607848b8605Smrg
608848b8605Smrg   if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
609848b8605Smrg       ctx->Pixel.MapStencilFlag) {
610848b8605Smrg      /* make a copy of input */
611848b8605Smrg      memcpy(stencil, source, n * sizeof(GLubyte));
612848b8605Smrg      _mesa_apply_stencil_transfer_ops(ctx, n, stencil);
613848b8605Smrg      source = stencil;
614848b8605Smrg   }
615848b8605Smrg
616848b8605Smrg   switch (dstType) {
617848b8605Smrg   case GL_UNSIGNED_BYTE:
618848b8605Smrg      memcpy(dest, source, n);
619848b8605Smrg      break;
620848b8605Smrg   case GL_BYTE:
621848b8605Smrg      {
622848b8605Smrg         GLbyte *dst = (GLbyte *) dest;
623848b8605Smrg         GLuint i;
624848b8605Smrg         for (i=0;i<n;i++) {
625848b8605Smrg            dst[i] = (GLbyte) (source[i] & 0x7f);
626848b8605Smrg         }
627848b8605Smrg      }
628848b8605Smrg      break;
629848b8605Smrg   case GL_UNSIGNED_SHORT:
630848b8605Smrg      {
631848b8605Smrg         GLushort *dst = (GLushort *) dest;
632848b8605Smrg         GLuint i;
633848b8605Smrg         for (i=0;i<n;i++) {
634848b8605Smrg            dst[i] = (GLushort) source[i];
635848b8605Smrg         }
636848b8605Smrg         if (dstPacking->SwapBytes) {
637848b8605Smrg            _mesa_swap2( (GLushort *) dst, n );
638848b8605Smrg         }
639848b8605Smrg      }
640848b8605Smrg      break;
641848b8605Smrg   case GL_SHORT:
642848b8605Smrg      {
643848b8605Smrg         GLshort *dst = (GLshort *) dest;
644848b8605Smrg         GLuint i;
645848b8605Smrg         for (i=0;i<n;i++) {
646848b8605Smrg            dst[i] = (GLshort) source[i];
647848b8605Smrg         }
648848b8605Smrg         if (dstPacking->SwapBytes) {
649848b8605Smrg            _mesa_swap2( (GLushort *) dst, n );
650848b8605Smrg         }
651848b8605Smrg      }
652848b8605Smrg      break;
653848b8605Smrg   case GL_UNSIGNED_INT:
654848b8605Smrg      {
655848b8605Smrg         GLuint *dst = (GLuint *) dest;
656848b8605Smrg         GLuint i;
657848b8605Smrg         for (i=0;i<n;i++) {
658848b8605Smrg            dst[i] = (GLuint) source[i];
659848b8605Smrg         }
660848b8605Smrg         if (dstPacking->SwapBytes) {
661848b8605Smrg            _mesa_swap4( (GLuint *) dst, n );
662848b8605Smrg         }
663848b8605Smrg      }
664848b8605Smrg      break;
665848b8605Smrg   case GL_INT:
666848b8605Smrg      {
667848b8605Smrg         GLint *dst = (GLint *) dest;
668848b8605Smrg         GLuint i;
669848b8605Smrg         for (i=0;i<n;i++) {
670848b8605Smrg            dst[i] = (GLint) source[i];
671848b8605Smrg         }
672848b8605Smrg         if (dstPacking->SwapBytes) {
673848b8605Smrg            _mesa_swap4( (GLuint *) dst, n );
674848b8605Smrg         }
675848b8605Smrg      }
676848b8605Smrg      break;
677848b8605Smrg   case GL_FLOAT:
678848b8605Smrg      {
679848b8605Smrg         GLfloat *dst = (GLfloat *) dest;
680848b8605Smrg         GLuint i;
681848b8605Smrg         for (i=0;i<n;i++) {
682848b8605Smrg            dst[i] = (GLfloat) source[i];
683848b8605Smrg         }
684848b8605Smrg         if (dstPacking->SwapBytes) {
685848b8605Smrg            _mesa_swap4( (GLuint *) dst, n );
686848b8605Smrg         }
687848b8605Smrg      }
688848b8605Smrg      break;
689848b8605Smrg   case GL_HALF_FLOAT_ARB:
690b8e80941Smrg   case GL_HALF_FLOAT_OES:
691848b8605Smrg      {
692848b8605Smrg         GLhalfARB *dst = (GLhalfARB *) dest;
693848b8605Smrg         GLuint i;
694848b8605Smrg         for (i=0;i<n;i++) {
695848b8605Smrg            dst[i] = _mesa_float_to_half( (float) source[i] );
696848b8605Smrg         }
697848b8605Smrg         if (dstPacking->SwapBytes) {
698848b8605Smrg            _mesa_swap2( (GLushort *) dst, n );
699848b8605Smrg         }
700848b8605Smrg      }
701848b8605Smrg      break;
702848b8605Smrg   case GL_BITMAP:
703848b8605Smrg      if (dstPacking->LsbFirst) {
704848b8605Smrg         GLubyte *dst = (GLubyte *) dest;
705848b8605Smrg         GLint shift = 0;
706848b8605Smrg         GLuint i;
707848b8605Smrg         for (i = 0; i < n; i++) {
708848b8605Smrg            if (shift == 0)
709848b8605Smrg               *dst = 0;
710848b8605Smrg            *dst |= ((source[i] != 0) << shift);
711848b8605Smrg            shift++;
712848b8605Smrg            if (shift == 8) {
713848b8605Smrg               shift = 0;
714848b8605Smrg               dst++;
715848b8605Smrg            }
716848b8605Smrg         }
717848b8605Smrg      }
718848b8605Smrg      else {
719848b8605Smrg         GLubyte *dst = (GLubyte *) dest;
720848b8605Smrg         GLint shift = 7;
721848b8605Smrg         GLuint i;
722848b8605Smrg         for (i = 0; i < n; i++) {
723848b8605Smrg            if (shift == 7)
724848b8605Smrg               *dst = 0;
725848b8605Smrg            *dst |= ((source[i] != 0) << shift);
726848b8605Smrg            shift--;
727848b8605Smrg            if (shift < 0) {
728848b8605Smrg               shift = 7;
729848b8605Smrg               dst++;
730848b8605Smrg            }
731848b8605Smrg         }
732848b8605Smrg      }
733848b8605Smrg      break;
734848b8605Smrg   default:
735b8e80941Smrg      unreachable("bad type in _mesa_pack_index_span");
736848b8605Smrg   }
737848b8605Smrg
738848b8605Smrg   free(stencil);
739848b8605Smrg}
740848b8605Smrg
741848b8605Smrg#define DEPTH_VALUES(GLTYPE, GLTYPE2FLOAT)                              \
742848b8605Smrg    do {                                                                \
743848b8605Smrg        GLuint i;                                                       \
744848b8605Smrg        const GLTYPE *src = (const GLTYPE *)source;                     \
745848b8605Smrg        for (i = 0; i < n; i++) {                                       \
746848b8605Smrg            GLTYPE value = src[i];                                      \
747848b8605Smrg            if (srcPacking->SwapBytes) {                                \
748848b8605Smrg                if (sizeof(GLTYPE) == 2) {                              \
749848b8605Smrg                    SWAP2BYTE(value);                                   \
750848b8605Smrg                } else if (sizeof(GLTYPE) == 4) {                       \
751848b8605Smrg                    SWAP4BYTE(value);                                   \
752848b8605Smrg                }                                                       \
753848b8605Smrg            }                                                           \
754848b8605Smrg            depthValues[i] = GLTYPE2FLOAT(value);                       \
755848b8605Smrg        }                                                               \
756848b8605Smrg    } while (0)
757848b8605Smrg
758848b8605Smrg
759848b8605Smrg/**
760848b8605Smrg * Unpack a row of depth/z values from memory, returning GLushort, GLuint
761848b8605Smrg * or GLfloat values.
762848b8605Smrg * The glPixelTransfer (scale/bias) params will be applied.
763848b8605Smrg *
764848b8605Smrg * \param dstType  one of GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_FLOAT
765848b8605Smrg * \param depthMax  max value for returned GLushort or GLuint values
766848b8605Smrg *                  (ignored for GLfloat).
767848b8605Smrg */
768848b8605Smrgvoid
769848b8605Smrg_mesa_unpack_depth_span( struct gl_context *ctx, GLuint n,
770848b8605Smrg                         GLenum dstType, GLvoid *dest, GLuint depthMax,
771848b8605Smrg                         GLenum srcType, const GLvoid *source,
772848b8605Smrg                         const struct gl_pixelstore_attrib *srcPacking )
773848b8605Smrg{
774848b8605Smrg   GLfloat *depthTemp = NULL, *depthValues;
775848b8605Smrg   GLboolean needClamp = GL_FALSE;
776848b8605Smrg
777848b8605Smrg   /* Look for special cases first.
778848b8605Smrg    * Not only are these faster, they're less prone to numeric conversion
779848b8605Smrg    * problems.  Otherwise, converting from an int type to a float then
780848b8605Smrg    * back to an int type can introduce errors that will show up as
781848b8605Smrg    * artifacts in things like depth peeling which uses glCopyTexImage.
782848b8605Smrg    */
783b8e80941Smrg   if (ctx->Pixel.DepthScale == 1.0F && ctx->Pixel.DepthBias == 0.0F) {
784848b8605Smrg      if (srcType == GL_UNSIGNED_INT && dstType == GL_UNSIGNED_SHORT) {
785848b8605Smrg         const GLuint *src = (const GLuint *) source;
786848b8605Smrg         GLushort *dst = (GLushort *) dest;
787848b8605Smrg         GLuint i;
788848b8605Smrg         for (i = 0; i < n; i++) {
789848b8605Smrg            dst[i] = src[i] >> 16;
790848b8605Smrg         }
791848b8605Smrg         return;
792848b8605Smrg      }
793848b8605Smrg      if (srcType == GL_UNSIGNED_SHORT
794848b8605Smrg          && dstType == GL_UNSIGNED_INT
795848b8605Smrg          && depthMax == 0xffffffff) {
796848b8605Smrg         const GLushort *src = (const GLushort *) source;
797848b8605Smrg         GLuint *dst = (GLuint *) dest;
798848b8605Smrg         GLuint i;
799848b8605Smrg         for (i = 0; i < n; i++) {
800848b8605Smrg            dst[i] = src[i] | (src[i] << 16);
801848b8605Smrg         }
802848b8605Smrg         return;
803848b8605Smrg      }
804848b8605Smrg      if (srcType == GL_UNSIGNED_INT_24_8
805848b8605Smrg          && dstType == GL_UNSIGNED_INT
806848b8605Smrg          && depthMax == 0xffffff) {
807848b8605Smrg         const GLuint *src = (const GLuint *) source;
808848b8605Smrg         GLuint *dst = (GLuint *) dest;
809848b8605Smrg         GLuint i;
810848b8605Smrg         for (i = 0; i < n; i++) {
811848b8605Smrg            dst[i] = src[i] >> 8;
812848b8605Smrg         }
813848b8605Smrg         return;
814848b8605Smrg      }
815848b8605Smrg      /* XXX may want to add additional cases here someday */
816848b8605Smrg   }
817848b8605Smrg
818848b8605Smrg   /* general case path follows */
819848b8605Smrg
820848b8605Smrg   if (dstType == GL_FLOAT) {
821848b8605Smrg      depthValues = (GLfloat *) dest;
822848b8605Smrg   }
823848b8605Smrg   else {
824848b8605Smrg      depthTemp = malloc(n * sizeof(GLfloat));
825848b8605Smrg      if (!depthTemp) {
826848b8605Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
827848b8605Smrg         return;
828848b8605Smrg      }
829848b8605Smrg
830848b8605Smrg      depthValues = depthTemp;
831848b8605Smrg   }
832848b8605Smrg
833848b8605Smrg   /* Convert incoming values to GLfloat.  Some conversions will require
834848b8605Smrg    * clamping, below.
835848b8605Smrg    */
836848b8605Smrg   switch (srcType) {
837848b8605Smrg      case GL_BYTE:
838848b8605Smrg         DEPTH_VALUES(GLbyte, BYTE_TO_FLOATZ);
839848b8605Smrg         needClamp = GL_TRUE;
840848b8605Smrg         break;
841848b8605Smrg      case GL_UNSIGNED_BYTE:
842848b8605Smrg         DEPTH_VALUES(GLubyte, UBYTE_TO_FLOAT);
843848b8605Smrg         break;
844848b8605Smrg      case GL_SHORT:
845848b8605Smrg         DEPTH_VALUES(GLshort, SHORT_TO_FLOATZ);
846848b8605Smrg         needClamp = GL_TRUE;
847848b8605Smrg         break;
848848b8605Smrg      case GL_UNSIGNED_SHORT:
849848b8605Smrg         DEPTH_VALUES(GLushort, USHORT_TO_FLOAT);
850848b8605Smrg         break;
851848b8605Smrg      case GL_INT:
852848b8605Smrg         DEPTH_VALUES(GLint, INT_TO_FLOAT);
853848b8605Smrg         needClamp = GL_TRUE;
854848b8605Smrg         break;
855848b8605Smrg      case GL_UNSIGNED_INT:
856848b8605Smrg         DEPTH_VALUES(GLuint, UINT_TO_FLOAT);
857848b8605Smrg         break;
858848b8605Smrg      case GL_UNSIGNED_INT_24_8_EXT: /* GL_EXT_packed_depth_stencil */
859848b8605Smrg         if (dstType == GL_UNSIGNED_INT_24_8_EXT &&
860848b8605Smrg             depthMax == 0xffffff &&
861b8e80941Smrg             ctx->Pixel.DepthScale == 1.0F &&
862b8e80941Smrg             ctx->Pixel.DepthBias == 0.0F) {
863848b8605Smrg            const GLuint *src = (const GLuint *) source;
864848b8605Smrg            GLuint *zValues = (GLuint *) dest;
865848b8605Smrg            GLuint i;
866848b8605Smrg            for (i = 0; i < n; i++) {
867848b8605Smrg                GLuint value = src[i];
868848b8605Smrg                if (srcPacking->SwapBytes) {
869848b8605Smrg                    SWAP4BYTE(value);
870848b8605Smrg                }
871848b8605Smrg                zValues[i] = value & 0xffffff00;
872848b8605Smrg            }
873848b8605Smrg            free(depthTemp);
874848b8605Smrg            return;
875848b8605Smrg         }
876848b8605Smrg         else {
877848b8605Smrg            const GLuint *src = (const GLuint *) source;
878848b8605Smrg            const GLfloat scale = 1.0f / 0xffffff;
879848b8605Smrg            GLuint i;
880848b8605Smrg            for (i = 0; i < n; i++) {
881848b8605Smrg                GLuint value = src[i];
882848b8605Smrg                if (srcPacking->SwapBytes) {
883848b8605Smrg                    SWAP4BYTE(value);
884848b8605Smrg                }
885848b8605Smrg                depthValues[i] = (value >> 8) * scale;
886848b8605Smrg            }
887848b8605Smrg         }
888848b8605Smrg         break;
889848b8605Smrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
890848b8605Smrg         {
891848b8605Smrg            GLuint i;
892848b8605Smrg            const GLfloat *src = (const GLfloat *)source;
893848b8605Smrg            for (i = 0; i < n; i++) {
894848b8605Smrg               GLfloat value = src[i * 2];
895848b8605Smrg               if (srcPacking->SwapBytes) {
896848b8605Smrg                  SWAP4BYTE(value);
897848b8605Smrg               }
898848b8605Smrg               depthValues[i] = value;
899848b8605Smrg            }
900848b8605Smrg            needClamp = GL_TRUE;
901848b8605Smrg         }
902848b8605Smrg         break;
903848b8605Smrg      case GL_FLOAT:
904848b8605Smrg         DEPTH_VALUES(GLfloat, 1*);
905848b8605Smrg         needClamp = GL_TRUE;
906848b8605Smrg         break;
907848b8605Smrg      case GL_HALF_FLOAT_ARB:
908b8e80941Smrg      case GL_HALF_FLOAT_OES:
909848b8605Smrg         {
910848b8605Smrg            GLuint i;
911848b8605Smrg            const GLhalfARB *src = (const GLhalfARB *) source;
912848b8605Smrg            for (i = 0; i < n; i++) {
913848b8605Smrg               GLhalfARB value = src[i];
914848b8605Smrg               if (srcPacking->SwapBytes) {
915848b8605Smrg                  SWAP2BYTE(value);
916848b8605Smrg               }
917848b8605Smrg               depthValues[i] = _mesa_half_to_float(value);
918848b8605Smrg            }
919848b8605Smrg            needClamp = GL_TRUE;
920848b8605Smrg         }
921848b8605Smrg         break;
922848b8605Smrg      default:
923848b8605Smrg         _mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()");
924848b8605Smrg         free(depthTemp);
925848b8605Smrg         return;
926848b8605Smrg   }
927848b8605Smrg
928848b8605Smrg   /* apply depth scale and bias */
929848b8605Smrg   {
930848b8605Smrg      const GLfloat scale = ctx->Pixel.DepthScale;
931848b8605Smrg      const GLfloat bias = ctx->Pixel.DepthBias;
932b8e80941Smrg      if (scale != 1.0F || bias != 0.0F) {
933848b8605Smrg         GLuint i;
934848b8605Smrg         for (i = 0; i < n; i++) {
935848b8605Smrg            depthValues[i] = depthValues[i] * scale + bias;
936848b8605Smrg         }
937848b8605Smrg         needClamp = GL_TRUE;
938848b8605Smrg      }
939848b8605Smrg   }
940848b8605Smrg
941848b8605Smrg   /* clamp to [0, 1] */
942848b8605Smrg   if (needClamp) {
943848b8605Smrg      GLuint i;
944848b8605Smrg      for (i = 0; i < n; i++) {
945b8e80941Smrg         depthValues[i] = CLAMP(depthValues[i], 0.0F, 1.0F);
946848b8605Smrg      }
947848b8605Smrg   }
948848b8605Smrg
949848b8605Smrg   /*
950848b8605Smrg    * Convert values to dstType
951848b8605Smrg    */
952848b8605Smrg   if (dstType == GL_UNSIGNED_INT) {
953848b8605Smrg      GLuint *zValues = (GLuint *) dest;
954848b8605Smrg      GLuint i;
955848b8605Smrg      if (depthMax <= 0xffffff) {
956848b8605Smrg         /* no overflow worries */
957848b8605Smrg         for (i = 0; i < n; i++) {
958848b8605Smrg            zValues[i] = (GLuint) (depthValues[i] * (GLfloat) depthMax);
959848b8605Smrg         }
960848b8605Smrg      }
961848b8605Smrg      else {
962848b8605Smrg         /* need to use double precision to prevent overflow problems */
963848b8605Smrg         for (i = 0; i < n; i++) {
964848b8605Smrg            GLdouble z = depthValues[i] * (GLdouble) depthMax;
965848b8605Smrg            if (z >= (GLdouble) 0xffffffff)
966848b8605Smrg               zValues[i] = 0xffffffff;
967848b8605Smrg            else
968848b8605Smrg               zValues[i] = (GLuint) z;
969848b8605Smrg         }
970848b8605Smrg      }
971848b8605Smrg   }
972848b8605Smrg   else if (dstType == GL_UNSIGNED_SHORT) {
973848b8605Smrg      GLushort *zValues = (GLushort *) dest;
974848b8605Smrg      GLuint i;
975b8e80941Smrg      assert(depthMax <= 0xffff);
976848b8605Smrg      for (i = 0; i < n; i++) {
977848b8605Smrg         zValues[i] = (GLushort) (depthValues[i] * (GLfloat) depthMax);
978848b8605Smrg      }
979848b8605Smrg   }
980848b8605Smrg   else if (dstType == GL_FLOAT) {
981848b8605Smrg      /* Nothing to do. depthValues is pointing to dest. */
982848b8605Smrg   }
983848b8605Smrg   else if (dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) {
984848b8605Smrg      GLfloat *zValues = (GLfloat*) dest;
985848b8605Smrg      GLuint i;
986848b8605Smrg      for (i = 0; i < n; i++) {
987848b8605Smrg         zValues[i*2] = depthValues[i];
988848b8605Smrg      }
989848b8605Smrg   }
990848b8605Smrg   else {
991b8e80941Smrg      assert(0);
992848b8605Smrg   }
993848b8605Smrg
994848b8605Smrg   free(depthTemp);
995848b8605Smrg}
996848b8605Smrg
997848b8605Smrg
998848b8605Smrg/*
999848b8605Smrg * Pack an array of depth values.  The values are floats in [0,1].
1000848b8605Smrg */
1001848b8605Smrgvoid
1002848b8605Smrg_mesa_pack_depth_span( struct gl_context *ctx, GLuint n, GLvoid *dest,
1003848b8605Smrg                       GLenum dstType, const GLfloat *depthSpan,
1004848b8605Smrg                       const struct gl_pixelstore_attrib *dstPacking )
1005848b8605Smrg{
1006848b8605Smrg   GLfloat *depthCopy = malloc(n * sizeof(GLfloat));
1007848b8605Smrg   if (!depthCopy) {
1008848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel packing");
1009848b8605Smrg      return;
1010848b8605Smrg   }
1011848b8605Smrg
1012b8e80941Smrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) {
1013848b8605Smrg      memcpy(depthCopy, depthSpan, n * sizeof(GLfloat));
1014848b8605Smrg      _mesa_scale_and_bias_depth(ctx, n, depthCopy);
1015848b8605Smrg      depthSpan = depthCopy;
1016848b8605Smrg   }
1017848b8605Smrg
1018848b8605Smrg   switch (dstType) {
1019848b8605Smrg   case GL_UNSIGNED_BYTE:
1020848b8605Smrg      {
1021848b8605Smrg         GLubyte *dst = (GLubyte *) dest;
1022848b8605Smrg         GLuint i;
1023848b8605Smrg         for (i = 0; i < n; i++) {
1024848b8605Smrg            dst[i] = FLOAT_TO_UBYTE( depthSpan[i] );
1025848b8605Smrg         }
1026848b8605Smrg      }
1027848b8605Smrg      break;
1028848b8605Smrg   case GL_BYTE:
1029848b8605Smrg      {
1030848b8605Smrg         GLbyte *dst = (GLbyte *) dest;
1031848b8605Smrg         GLuint i;
1032848b8605Smrg         for (i = 0; i < n; i++) {
1033848b8605Smrg            dst[i] = FLOAT_TO_BYTE( depthSpan[i] );
1034848b8605Smrg         }
1035848b8605Smrg      }
1036848b8605Smrg      break;
1037848b8605Smrg   case GL_UNSIGNED_SHORT:
1038848b8605Smrg      {
1039848b8605Smrg         GLushort *dst = (GLushort *) dest;
1040848b8605Smrg         GLuint i;
1041848b8605Smrg         for (i = 0; i < n; i++) {
1042848b8605Smrg            CLAMPED_FLOAT_TO_USHORT(dst[i], depthSpan[i]);
1043848b8605Smrg         }
1044848b8605Smrg         if (dstPacking->SwapBytes) {
1045848b8605Smrg            _mesa_swap2( (GLushort *) dst, n );
1046848b8605Smrg         }
1047848b8605Smrg      }
1048848b8605Smrg      break;
1049848b8605Smrg   case GL_SHORT:
1050848b8605Smrg      {
1051848b8605Smrg         GLshort *dst = (GLshort *) dest;
1052848b8605Smrg         GLuint i;
1053848b8605Smrg         for (i = 0; i < n; i++) {
1054848b8605Smrg            dst[i] = FLOAT_TO_SHORT( depthSpan[i] );
1055848b8605Smrg         }
1056848b8605Smrg         if (dstPacking->SwapBytes) {
1057848b8605Smrg            _mesa_swap2( (GLushort *) dst, n );
1058848b8605Smrg         }
1059848b8605Smrg      }
1060848b8605Smrg      break;
1061b8e80941Smrg   case GL_UNSIGNED_INT_24_8:
1062b8e80941Smrg      {
1063b8e80941Smrg         const GLdouble scale = (GLdouble) 0xffffff;
1064b8e80941Smrg         GLuint *dst = (GLuint *) dest;
1065b8e80941Smrg         GLuint i;
1066b8e80941Smrg         for (i = 0; i < n; i++) {
1067b8e80941Smrg            GLuint z = (GLuint) (depthSpan[i] * scale);
1068b8e80941Smrg            assert(z <= 0xffffff);
1069b8e80941Smrg            dst[i] = (z << 8);
1070b8e80941Smrg         }
1071b8e80941Smrg         if (dstPacking->SwapBytes) {
1072b8e80941Smrg            _mesa_swap4( (GLuint *) dst, n );
1073b8e80941Smrg         }
1074b8e80941Smrg         break;
1075b8e80941Smrg      }
1076848b8605Smrg   case GL_UNSIGNED_INT:
1077848b8605Smrg      {
1078848b8605Smrg         GLuint *dst = (GLuint *) dest;
1079848b8605Smrg         GLuint i;
1080848b8605Smrg         for (i = 0; i < n; i++) {
1081848b8605Smrg            dst[i] = FLOAT_TO_UINT( depthSpan[i] );
1082848b8605Smrg         }
1083848b8605Smrg         if (dstPacking->SwapBytes) {
1084848b8605Smrg            _mesa_swap4( (GLuint *) dst, n );
1085848b8605Smrg         }
1086848b8605Smrg      }
1087848b8605Smrg      break;
1088848b8605Smrg   case GL_INT:
1089848b8605Smrg      {
1090848b8605Smrg         GLint *dst = (GLint *) dest;
1091848b8605Smrg         GLuint i;
1092848b8605Smrg         for (i = 0; i < n; i++) {
1093848b8605Smrg            dst[i] = FLOAT_TO_INT( depthSpan[i] );
1094848b8605Smrg         }
1095848b8605Smrg         if (dstPacking->SwapBytes) {
1096848b8605Smrg            _mesa_swap4( (GLuint *) dst, n );
1097848b8605Smrg         }
1098848b8605Smrg      }
1099848b8605Smrg      break;
1100848b8605Smrg   case GL_FLOAT:
1101848b8605Smrg      {
1102848b8605Smrg         GLfloat *dst = (GLfloat *) dest;
1103848b8605Smrg         GLuint i;
1104848b8605Smrg         for (i = 0; i < n; i++) {
1105848b8605Smrg            dst[i] = depthSpan[i];
1106848b8605Smrg         }
1107848b8605Smrg         if (dstPacking->SwapBytes) {
1108848b8605Smrg            _mesa_swap4( (GLuint *) dst, n );
1109848b8605Smrg         }
1110848b8605Smrg      }
1111848b8605Smrg      break;
1112848b8605Smrg   case GL_HALF_FLOAT_ARB:
1113b8e80941Smrg   case GL_HALF_FLOAT_OES:
1114848b8605Smrg      {
1115848b8605Smrg         GLhalfARB *dst = (GLhalfARB *) dest;
1116848b8605Smrg         GLuint i;
1117848b8605Smrg         for (i = 0; i < n; i++) {
1118848b8605Smrg            dst[i] = _mesa_float_to_half(depthSpan[i]);
1119848b8605Smrg         }
1120848b8605Smrg         if (dstPacking->SwapBytes) {
1121848b8605Smrg            _mesa_swap2( (GLushort *) dst, n );
1122848b8605Smrg         }
1123848b8605Smrg      }
1124848b8605Smrg      break;
1125848b8605Smrg   default:
1126b8e80941Smrg      unreachable("bad type in _mesa_pack_depth_span()");
1127848b8605Smrg   }
1128848b8605Smrg
1129848b8605Smrg   free(depthCopy);
1130848b8605Smrg}
1131848b8605Smrg
1132848b8605Smrg
1133848b8605Smrg
1134848b8605Smrg/**
1135848b8605Smrg * Pack depth and stencil values as GL_DEPTH_STENCIL (GL_UNSIGNED_INT_24_8 etc)
1136848b8605Smrg */
1137848b8605Smrgvoid
1138848b8605Smrg_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n,
1139848b8605Smrg                              GLenum dstType, GLuint *dest,
1140848b8605Smrg                              const GLfloat *depthVals,
1141848b8605Smrg                              const GLubyte *stencilVals,
1142848b8605Smrg                              const struct gl_pixelstore_attrib *dstPacking)
1143848b8605Smrg{
1144848b8605Smrg   GLfloat *depthCopy = malloc(n * sizeof(GLfloat));
1145848b8605Smrg   GLubyte *stencilCopy = malloc(n * sizeof(GLubyte));
1146848b8605Smrg   GLuint i;
1147848b8605Smrg
1148848b8605Smrg   if (!depthCopy || !stencilCopy) {
1149848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel packing");
1150848b8605Smrg      free(depthCopy);
1151848b8605Smrg      free(stencilCopy);
1152848b8605Smrg      return;
1153848b8605Smrg   }
1154848b8605Smrg
1155b8e80941Smrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F) {
1156848b8605Smrg      memcpy(depthCopy, depthVals, n * sizeof(GLfloat));
1157848b8605Smrg      _mesa_scale_and_bias_depth(ctx, n, depthCopy);
1158848b8605Smrg      depthVals = depthCopy;
1159848b8605Smrg   }
1160848b8605Smrg
1161848b8605Smrg   if (ctx->Pixel.IndexShift ||
1162848b8605Smrg       ctx->Pixel.IndexOffset ||
1163848b8605Smrg       ctx->Pixel.MapStencilFlag) {
1164848b8605Smrg      memcpy(stencilCopy, stencilVals, n * sizeof(GLubyte));
1165848b8605Smrg      _mesa_apply_stencil_transfer_ops(ctx, n, stencilCopy);
1166848b8605Smrg      stencilVals = stencilCopy;
1167848b8605Smrg   }
1168848b8605Smrg
1169848b8605Smrg   switch (dstType) {
1170848b8605Smrg   case GL_UNSIGNED_INT_24_8:
1171848b8605Smrg      for (i = 0; i < n; i++) {
1172848b8605Smrg         GLuint z = (GLuint) (depthVals[i] * 0xffffff);
1173848b8605Smrg         dest[i] = (z << 8) | (stencilVals[i] & 0xff);
1174848b8605Smrg      }
1175848b8605Smrg      break;
1176848b8605Smrg   case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
1177848b8605Smrg      for (i = 0; i < n; i++) {
1178848b8605Smrg         ((GLfloat*)dest)[i*2] = depthVals[i];
1179848b8605Smrg         dest[i*2+1] = stencilVals[i] & 0xff;
1180848b8605Smrg      }
1181848b8605Smrg      break;
1182848b8605Smrg   }
1183848b8605Smrg
1184848b8605Smrg   if (dstPacking->SwapBytes) {
1185848b8605Smrg      _mesa_swap4(dest, n);
1186848b8605Smrg   }
1187848b8605Smrg
1188848b8605Smrg   free(depthCopy);
1189848b8605Smrg   free(stencilCopy);
1190848b8605Smrg}
1191848b8605Smrg
1192848b8605Smrg
1193848b8605Smrg
1194848b8605Smrg/**
1195848b8605Smrg * Unpack image data.  Apply byte swapping, byte flipping (bitmap).
1196848b8605Smrg * Return all image data in a contiguous block.  This is used when we
1197848b8605Smrg * compile glDrawPixels, glTexImage, etc into a display list.  We
1198848b8605Smrg * need a copy of the data in a standard format.
1199848b8605Smrg */
1200848b8605Smrgvoid *
1201848b8605Smrg_mesa_unpack_image( GLuint dimensions,
1202848b8605Smrg                    GLsizei width, GLsizei height, GLsizei depth,
1203848b8605Smrg                    GLenum format, GLenum type, const GLvoid *pixels,
1204848b8605Smrg                    const struct gl_pixelstore_attrib *unpack )
1205848b8605Smrg{
1206848b8605Smrg   GLint bytesPerRow, compsPerRow;
1207848b8605Smrg   GLboolean flipBytes, swap2, swap4;
1208848b8605Smrg
1209848b8605Smrg   if (!pixels)
1210848b8605Smrg      return NULL;  /* not necessarily an error */
1211848b8605Smrg
1212848b8605Smrg   if (width <= 0 || height <= 0 || depth <= 0)
1213848b8605Smrg      return NULL;  /* generate error later */
1214848b8605Smrg
1215848b8605Smrg   if (type == GL_BITMAP) {
1216848b8605Smrg      bytesPerRow = (width + 7) >> 3;
1217848b8605Smrg      flipBytes = unpack->LsbFirst;
1218848b8605Smrg      swap2 = swap4 = GL_FALSE;
1219848b8605Smrg      compsPerRow = 0;
1220848b8605Smrg   }
1221848b8605Smrg   else {
1222848b8605Smrg      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
1223848b8605Smrg      GLint components = _mesa_components_in_format(format);
1224848b8605Smrg      GLint bytesPerComp;
1225848b8605Smrg
1226848b8605Smrg      if (_mesa_type_is_packed(type))
1227848b8605Smrg          components = 1;
1228848b8605Smrg
1229848b8605Smrg      if (bytesPerPixel <= 0 || components <= 0)
1230848b8605Smrg         return NULL;   /* bad format or type.  generate error later */
1231848b8605Smrg      bytesPerRow = bytesPerPixel * width;
1232848b8605Smrg      bytesPerComp = bytesPerPixel / components;
1233848b8605Smrg      flipBytes = GL_FALSE;
1234848b8605Smrg      swap2 = (bytesPerComp == 2) && unpack->SwapBytes;
1235848b8605Smrg      swap4 = (bytesPerComp == 4) && unpack->SwapBytes;
1236848b8605Smrg      compsPerRow = components * width;
1237848b8605Smrg      assert(compsPerRow >= width);
1238848b8605Smrg   }
1239848b8605Smrg
1240848b8605Smrg   {
1241848b8605Smrg      GLubyte *destBuffer
1242848b8605Smrg         = malloc(bytesPerRow * height * depth);
1243848b8605Smrg      GLubyte *dst;
1244848b8605Smrg      GLint img, row;
1245848b8605Smrg      if (!destBuffer)
1246848b8605Smrg         return NULL;   /* generate GL_OUT_OF_MEMORY later */
1247848b8605Smrg
1248848b8605Smrg      dst = destBuffer;
1249848b8605Smrg      for (img = 0; img < depth; img++) {
1250848b8605Smrg         for (row = 0; row < height; row++) {
1251848b8605Smrg            const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels,
1252848b8605Smrg                               width, height, format, type, img, row, 0);
1253848b8605Smrg
1254848b8605Smrg            if ((type == GL_BITMAP) && (unpack->SkipPixels & 0x7)) {
1255848b8605Smrg               GLint i;
1256848b8605Smrg               flipBytes = GL_FALSE;
1257848b8605Smrg               if (unpack->LsbFirst) {
1258848b8605Smrg                  GLubyte srcMask = 1 << (unpack->SkipPixels & 0x7);
1259848b8605Smrg                  GLubyte dstMask = 128;
1260848b8605Smrg                  const GLubyte *s = src;
1261848b8605Smrg                  GLubyte *d = dst;
1262848b8605Smrg                  *d = 0;
1263848b8605Smrg                  for (i = 0; i < width; i++) {
1264848b8605Smrg                     if (*s & srcMask) {
1265848b8605Smrg                        *d |= dstMask;
1266848b8605Smrg                     }
1267848b8605Smrg                     if (srcMask == 128) {
1268848b8605Smrg                        srcMask = 1;
1269848b8605Smrg                        s++;
1270848b8605Smrg                     }
1271848b8605Smrg                     else {
1272848b8605Smrg                        srcMask = srcMask << 1;
1273848b8605Smrg                     }
1274848b8605Smrg                     if (dstMask == 1) {
1275848b8605Smrg                        dstMask = 128;
1276848b8605Smrg                        d++;
1277848b8605Smrg                        *d = 0;
1278848b8605Smrg                     }
1279848b8605Smrg                     else {
1280848b8605Smrg                        dstMask = dstMask >> 1;
1281848b8605Smrg                     }
1282848b8605Smrg                  }
1283848b8605Smrg               }
1284848b8605Smrg               else {
1285848b8605Smrg                  GLubyte srcMask = 128 >> (unpack->SkipPixels & 0x7);
1286848b8605Smrg                  GLubyte dstMask = 128;
1287848b8605Smrg                  const GLubyte *s = src;
1288848b8605Smrg                  GLubyte *d = dst;
1289848b8605Smrg                  *d = 0;
1290848b8605Smrg                  for (i = 0; i < width; i++) {
1291848b8605Smrg                     if (*s & srcMask) {
1292848b8605Smrg                        *d |= dstMask;
1293848b8605Smrg                     }
1294848b8605Smrg                     if (srcMask == 1) {
1295848b8605Smrg                        srcMask = 128;
1296848b8605Smrg                        s++;
1297848b8605Smrg                     }
1298848b8605Smrg                     else {
1299848b8605Smrg                        srcMask = srcMask >> 1;
1300848b8605Smrg                     }
1301848b8605Smrg                     if (dstMask == 1) {
1302848b8605Smrg                        dstMask = 128;
1303848b8605Smrg                        d++;
1304848b8605Smrg                        *d = 0;
1305848b8605Smrg                     }
1306848b8605Smrg                     else {
1307848b8605Smrg                        dstMask = dstMask >> 1;
1308848b8605Smrg                     }
1309848b8605Smrg                  }
1310848b8605Smrg               }
1311848b8605Smrg            }
1312848b8605Smrg            else {
1313848b8605Smrg               memcpy(dst, src, bytesPerRow);
1314848b8605Smrg            }
1315848b8605Smrg
1316848b8605Smrg            /* byte flipping/swapping */
1317848b8605Smrg            if (flipBytes) {
1318848b8605Smrg               flip_bytes((GLubyte *) dst, bytesPerRow);
1319848b8605Smrg            }
1320848b8605Smrg            else if (swap2) {
1321848b8605Smrg               _mesa_swap2((GLushort*) dst, compsPerRow);
1322848b8605Smrg            }
1323848b8605Smrg            else if (swap4) {
1324848b8605Smrg               _mesa_swap4((GLuint*) dst, compsPerRow);
1325848b8605Smrg            }
1326848b8605Smrg            dst += bytesPerRow;
1327848b8605Smrg         }
1328848b8605Smrg      }
1329848b8605Smrg      return destBuffer;
1330848b8605Smrg   }
1331848b8605Smrg}
1332848b8605Smrg
1333848b8605Smrgvoid
1334b8e80941Smrg_mesa_pack_luminance_from_rgba_float(GLuint n, GLfloat rgba[][4],
1335b8e80941Smrg                                     GLvoid *dstAddr, GLenum dst_format,
1336b8e80941Smrg                                     GLbitfield transferOps)
1337848b8605Smrg{
1338b8e80941Smrg   int i;
1339b8e80941Smrg   GLfloat *dst = (GLfloat *) dstAddr;
1340848b8605Smrg
1341b8e80941Smrg   switch (dst_format) {
1342848b8605Smrg   case GL_LUMINANCE:
1343b8e80941Smrg      if (transferOps & IMAGE_CLAMP_BIT) {
1344b8e80941Smrg         for (i = 0; i < n; i++) {
1345b8e80941Smrg            GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
1346b8e80941Smrg            dst[i] = CLAMP(sum, 0.0F, 1.0F);
1347b8e80941Smrg         }
1348b8e80941Smrg      } else {
1349b8e80941Smrg         for (i = 0; i < n; i++) {
1350b8e80941Smrg            dst[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
1351b8e80941Smrg         }
1352848b8605Smrg      }
1353b8e80941Smrg      return;
1354848b8605Smrg   case GL_LUMINANCE_ALPHA:
1355b8e80941Smrg      if (transferOps & IMAGE_CLAMP_BIT) {
1356b8e80941Smrg         for (i = 0; i < n; i++) {
1357b8e80941Smrg            GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
1358b8e80941Smrg            dst[2*i] = CLAMP(sum, 0.0F, 1.0F);
1359b8e80941Smrg            dst[2*i+1] = rgba[i][ACOMP];
1360b8e80941Smrg         }
1361b8e80941Smrg      } else {
1362b8e80941Smrg         for (i = 0; i < n; i++) {
1363b8e80941Smrg            dst[2*i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
1364b8e80941Smrg            dst[2*i+1] = rgba[i][ACOMP];
1365b8e80941Smrg         }
1366848b8605Smrg      }
1367b8e80941Smrg      return;
1368848b8605Smrg   default:
1369b8e80941Smrg      assert(!"Unsupported format");
1370b8e80941Smrg   }
1371b8e80941Smrg}
1372b8e80941Smrg
1373b8e80941Smrgstatic int32_t
1374b8e80941Smrgclamp_sint64_to_sint32(int64_t src)
1375b8e80941Smrg{
1376b8e80941Smrg   return CLAMP(src, INT32_MIN, INT32_MAX);
1377b8e80941Smrg}
1378b8e80941Smrg
1379b8e80941Smrgstatic int32_t
1380b8e80941Smrgclamp_sint64_to_uint32(int64_t src)
1381b8e80941Smrg{
1382b8e80941Smrg   return CLAMP(src, 0, UINT32_MAX);
1383b8e80941Smrg}
1384b8e80941Smrg
1385b8e80941Smrgstatic int32_t
1386b8e80941Smrgclamp_uint64_to_uint32(uint64_t src)
1387b8e80941Smrg{
1388b8e80941Smrg   return MIN2(src, UINT32_MAX);
1389b8e80941Smrg}
1390b8e80941Smrg
1391b8e80941Smrgstatic int32_t
1392b8e80941Smrgclamp_uint64_to_sint32(uint64_t src)
1393b8e80941Smrg{
1394b8e80941Smrg   return MIN2(src, INT32_MAX);
1395b8e80941Smrg}
1396b8e80941Smrg
1397b8e80941Smrgstatic int32_t
1398b8e80941Smrgconvert_integer_luminance64(int64_t src64, int bits,
1399b8e80941Smrg                            bool dst_is_signed, bool src_is_signed)
1400b8e80941Smrg{
1401b8e80941Smrg   int32_t src32;
1402b8e80941Smrg
1403b8e80941Smrg   /* Clamp Luminance value from 64-bit to 32-bit. Consider if we need
1404b8e80941Smrg    * any signed<->unsigned conversion too.
1405b8e80941Smrg    */
1406b8e80941Smrg   if (src_is_signed && dst_is_signed)
1407b8e80941Smrg      src32 = clamp_sint64_to_sint32(src64);
1408b8e80941Smrg   else if (src_is_signed && !dst_is_signed)
1409b8e80941Smrg      src32 = clamp_sint64_to_uint32(src64);
1410b8e80941Smrg   else if (!src_is_signed && dst_is_signed)
1411b8e80941Smrg      src32 = clamp_uint64_to_sint32(src64);
1412b8e80941Smrg   else
1413b8e80941Smrg      src32 = clamp_uint64_to_uint32(src64);
1414b8e80941Smrg
1415b8e80941Smrg   /* If the dst type is < 32-bit, we need an extra clamp */
1416b8e80941Smrg   if (bits == 32) {
1417b8e80941Smrg      return src32;
1418b8e80941Smrg   } else {
1419b8e80941Smrg      if (dst_is_signed)
1420b8e80941Smrg         return _mesa_signed_to_signed(src32, bits);
1421b8e80941Smrg      else
1422b8e80941Smrg         return _mesa_unsigned_to_unsigned(src32, bits);
1423848b8605Smrg   }
1424848b8605Smrg}
1425848b8605Smrg
1426b8e80941Smrgstatic int32_t
1427b8e80941Smrgconvert_integer(int32_t src, int bits, bool dst_is_signed, bool src_is_signed)
1428b8e80941Smrg{
1429b8e80941Smrg   if (src_is_signed && dst_is_signed)
1430b8e80941Smrg      return _mesa_signed_to_signed(src, bits);
1431b8e80941Smrg   else if (src_is_signed && !dst_is_signed)
1432b8e80941Smrg      return _mesa_signed_to_unsigned(src, bits);
1433b8e80941Smrg   else if (!src_is_signed && dst_is_signed)
1434b8e80941Smrg      return _mesa_unsigned_to_signed(src, bits);
1435b8e80941Smrg   else
1436b8e80941Smrg      return _mesa_unsigned_to_unsigned(src, bits);
1437b8e80941Smrg}
1438848b8605Smrg
1439848b8605Smrgvoid
1440b8e80941Smrg_mesa_pack_luminance_from_rgba_integer(GLuint n,
1441b8e80941Smrg                                       GLuint rgba[][4], bool rgba_is_signed,
1442b8e80941Smrg                                       GLvoid *dstAddr,
1443b8e80941Smrg                                       GLenum dst_format,
1444b8e80941Smrg                                       GLenum dst_type)
1445848b8605Smrg{
1446b8e80941Smrg   int i;
1447b8e80941Smrg   int64_t lum64;
1448b8e80941Smrg   int32_t lum32, alpha;
1449b8e80941Smrg   bool dst_is_signed;
1450b8e80941Smrg   int dst_bits;
1451b8e80941Smrg
1452b8e80941Smrg   assert(dst_format == GL_LUMINANCE_INTEGER_EXT ||
1453b8e80941Smrg          dst_format == GL_LUMINANCE_ALPHA_INTEGER_EXT);
1454b8e80941Smrg
1455b8e80941Smrg   /* We first compute luminance values as a 64-bit addition of the
1456b8e80941Smrg    * 32-bit R,G,B components, then we clamp the result to the dst type size.
1457b8e80941Smrg    *
1458b8e80941Smrg    * Notice that this operation involves casting the 32-bit R,G,B components
1459b8e80941Smrg    * to 64-bit before the addition. Since rgba is defined as a GLuint array
1460b8e80941Smrg    * we need to be careful when rgba packs signed data and make sure
1461b8e80941Smrg    * that we cast to a 32-bit signed integer values before casting them to
1462b8e80941Smrg    * 64-bit signed integers.
1463b8e80941Smrg    */
1464b8e80941Smrg   dst_is_signed = (dst_type == GL_BYTE || dst_type == GL_SHORT ||
1465b8e80941Smrg                    dst_type == GL_INT);
1466848b8605Smrg
1467b8e80941Smrg   dst_bits = _mesa_sizeof_type(dst_type) * 8;
1468b8e80941Smrg   assert(dst_bits > 0);
1469b8e80941Smrg
1470b8e80941Smrg   switch (dst_format) {
1471b8e80941Smrg   case GL_LUMINANCE_INTEGER_EXT:
1472848b8605Smrg      for (i = 0; i < n; i++) {
1473b8e80941Smrg         if (!rgba_is_signed) {
1474b8e80941Smrg            lum64 = (uint64_t) rgba[i][RCOMP] +
1475b8e80941Smrg                    (uint64_t) rgba[i][GCOMP] +
1476b8e80941Smrg                    (uint64_t) rgba[i][BCOMP];
1477b8e80941Smrg         } else {
1478b8e80941Smrg            lum64 = (int64_t) ((int32_t) rgba[i][RCOMP]) +
1479b8e80941Smrg                    (int64_t) ((int32_t) rgba[i][GCOMP]) +
1480b8e80941Smrg                    (int64_t) ((int32_t) rgba[i][BCOMP]);
1481b8e80941Smrg         }
1482b8e80941Smrg         lum32 = convert_integer_luminance64(lum64, dst_bits,
1483b8e80941Smrg                                             dst_is_signed, rgba_is_signed);
1484b8e80941Smrg         switch (dst_type) {
1485b8e80941Smrg         case GL_BYTE:
1486b8e80941Smrg         case GL_UNSIGNED_BYTE: {
1487b8e80941Smrg            GLbyte *dst = (GLbyte *) dstAddr;
1488b8e80941Smrg            dst[i] = lum32;
1489b8e80941Smrg            break;
1490b8e80941Smrg         }
1491b8e80941Smrg         case GL_SHORT:
1492b8e80941Smrg         case GL_UNSIGNED_SHORT: {
1493b8e80941Smrg            GLshort *dst = (GLshort *) dstAddr;
1494b8e80941Smrg            dst[i] = lum32;
1495b8e80941Smrg            break;
1496b8e80941Smrg         }
1497b8e80941Smrg         case GL_INT:
1498b8e80941Smrg         case GL_UNSIGNED_INT: {
1499b8e80941Smrg            GLint *dst = (GLint *) dstAddr;
1500b8e80941Smrg            dst[i] = lum32;
1501b8e80941Smrg            break;
1502b8e80941Smrg         }
1503b8e80941Smrg         }
1504848b8605Smrg      }
1505b8e80941Smrg      return;
1506b8e80941Smrg   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
1507848b8605Smrg      for (i = 0; i < n; i++) {
1508b8e80941Smrg         if (!rgba_is_signed) {
1509b8e80941Smrg            lum64 = (uint64_t) rgba[i][RCOMP] +
1510b8e80941Smrg                    (uint64_t) rgba[i][GCOMP] +
1511b8e80941Smrg                    (uint64_t) rgba[i][BCOMP];
1512b8e80941Smrg         } else {
1513b8e80941Smrg            lum64 = (int64_t) ((int32_t) rgba[i][RCOMP]) +
1514b8e80941Smrg                    (int64_t) ((int32_t) rgba[i][GCOMP]) +
1515b8e80941Smrg                    (int64_t) ((int32_t) rgba[i][BCOMP]);
1516b8e80941Smrg         }
1517b8e80941Smrg         lum32 = convert_integer_luminance64(lum64, dst_bits,
1518b8e80941Smrg                                             dst_is_signed, rgba_is_signed);
1519b8e80941Smrg         alpha = convert_integer(rgba[i][ACOMP], dst_bits,
1520b8e80941Smrg                                 dst_is_signed, rgba_is_signed);
1521b8e80941Smrg         switch (dst_type) {
1522b8e80941Smrg         case GL_BYTE:
1523b8e80941Smrg         case GL_UNSIGNED_BYTE: {
1524b8e80941Smrg            GLbyte *dst = (GLbyte *) dstAddr;
1525b8e80941Smrg            dst[2*i] = lum32;
1526b8e80941Smrg            dst[2*i+1] = alpha;
1527b8e80941Smrg            break;
1528b8e80941Smrg         }
1529b8e80941Smrg         case GL_SHORT:
1530b8e80941Smrg         case GL_UNSIGNED_SHORT: {
1531b8e80941Smrg            GLshort *dst = (GLshort *) dstAddr;
1532b8e80941Smrg            dst[i] = lum32;
1533b8e80941Smrg            dst[2*i+1] = alpha;
1534b8e80941Smrg            break;
1535b8e80941Smrg         }
1536b8e80941Smrg         case GL_INT:
1537b8e80941Smrg         case GL_UNSIGNED_INT: {
1538b8e80941Smrg            GLint *dst = (GLint *) dstAddr;
1539b8e80941Smrg            dst[i] = lum32;
1540b8e80941Smrg            dst[2*i+1] = alpha;
1541b8e80941Smrg            break;
1542b8e80941Smrg         }
1543b8e80941Smrg         }
1544848b8605Smrg      }
1545b8e80941Smrg      return;
1546848b8605Smrg   }
1547848b8605Smrg}
1548848b8605Smrg
1549b8e80941SmrgGLfloat *
1550b8e80941Smrg_mesa_unpack_color_index_to_rgba_float(struct gl_context *ctx, GLuint dims,
1551b8e80941Smrg                                       const void *src, GLenum srcFormat, GLenum srcType,
1552b8e80941Smrg                                       int srcWidth, int srcHeight, int srcDepth,
1553b8e80941Smrg                                       const struct gl_pixelstore_attrib *srcPacking,
1554b8e80941Smrg                                       GLbitfield transferOps)
1555b8e80941Smrg{
1556b8e80941Smrg   int count, img;
1557b8e80941Smrg   GLuint *indexes;
1558b8e80941Smrg   GLfloat *rgba, *dstPtr;
1559b8e80941Smrg
1560b8e80941Smrg   count = srcWidth * srcHeight;
1561b8e80941Smrg   indexes = malloc(count * sizeof(GLuint));
1562b8e80941Smrg   if (!indexes) {
1563b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
1564b8e80941Smrg      return NULL;
1565b8e80941Smrg   }
1566b8e80941Smrg
1567b8e80941Smrg   rgba = malloc(4 * count * srcDepth * sizeof(GLfloat));
1568b8e80941Smrg   if (!rgba) {
1569b8e80941Smrg      free(indexes);
1570b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "pixel unpacking");
1571b8e80941Smrg      return NULL;
1572b8e80941Smrg   }
1573b8e80941Smrg
1574b8e80941Smrg   /* Convert indexes to RGBA float */
1575b8e80941Smrg   dstPtr = rgba;
1576b8e80941Smrg   for (img = 0; img < srcDepth; img++) {
1577b8e80941Smrg      const GLubyte *srcPtr =
1578b8e80941Smrg         (const GLubyte *) _mesa_image_address(dims, srcPacking, src,
1579b8e80941Smrg                                               srcWidth, srcHeight,
1580b8e80941Smrg                                               srcFormat, srcType,
1581b8e80941Smrg                                               img, 0, 0);
1582b8e80941Smrg
1583b8e80941Smrg      extract_uint_indexes(count, indexes, srcFormat, srcType, srcPtr, srcPacking);
1584b8e80941Smrg
1585b8e80941Smrg      if (transferOps & IMAGE_SHIFT_OFFSET_BIT)
1586b8e80941Smrg         _mesa_shift_and_offset_ci(ctx, count, indexes);
1587b8e80941Smrg
1588b8e80941Smrg      _mesa_map_ci_to_rgba(ctx, count, indexes, (float (*)[4])dstPtr);
1589848b8605Smrg
1590b8e80941Smrg      /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting
1591b8e80941Smrg       * with color indexes.
1592b8e80941Smrg       */
1593b8e80941Smrg      transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT);
1594b8e80941Smrg      _mesa_apply_rgba_transfer_ops(ctx, transferOps, count, (float (*)[4])dstPtr);
1595b8e80941Smrg
1596b8e80941Smrg      dstPtr += srcHeight * srcWidth * 4;
1597b8e80941Smrg   }
1598b8e80941Smrg
1599b8e80941Smrg   free(indexes);
1600b8e80941Smrg
1601b8e80941Smrg   return rgba;
1602b8e80941Smrg}
1603b8e80941Smrg
1604b8e80941SmrgGLubyte *
1605b8e80941Smrg_mesa_unpack_color_index_to_rgba_ubyte(struct gl_context *ctx, GLuint dims,
1606b8e80941Smrg                                       const void *src, GLenum srcFormat, GLenum srcType,
1607b8e80941Smrg                                       int srcWidth, int srcHeight, int srcDepth,
1608b8e80941Smrg                                       const struct gl_pixelstore_attrib *srcPacking,
1609b8e80941Smrg                                       GLbitfield transferOps)
1610b8e80941Smrg{
1611b8e80941Smrg   GLfloat *rgba;
1612b8e80941Smrg   GLubyte *dst;
1613b8e80941Smrg   int count, i;
1614b8e80941Smrg
1615b8e80941Smrg   transferOps |= IMAGE_CLAMP_BIT;
1616b8e80941Smrg   rgba = _mesa_unpack_color_index_to_rgba_float(ctx, dims,
1617b8e80941Smrg                                                 src, srcFormat, srcType,
1618b8e80941Smrg                                                 srcWidth, srcHeight, srcDepth,
1619b8e80941Smrg                                                 srcPacking, transferOps);
1620b8e80941Smrg
1621b8e80941Smrg   count = srcWidth * srcHeight * srcDepth;
1622b8e80941Smrg   dst = malloc(count * 4 * sizeof(GLubyte));
1623b8e80941Smrg   for (i = 0; i < count; i++) {
1624b8e80941Smrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 0], rgba[i * 4 + 0]);
1625b8e80941Smrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 1], rgba[i * 4 + 1]);
1626b8e80941Smrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 2], rgba[i * 4 + 2]);
1627b8e80941Smrg      CLAMPED_FLOAT_TO_UBYTE(dst[i * 4 + 3], rgba[i * 4 + 3]);
1628b8e80941Smrg   }
1629b8e80941Smrg
1630b8e80941Smrg   free(rgba);
1631b8e80941Smrg
1632b8e80941Smrg   return dst;
1633b8e80941Smrg}
1634