image.c revision 3464ebd5
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
3c7037ccdSmrg * Version:  7.5
47117f1b4Smrg *
5c1f859d4Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6c7037ccdSmrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
77117f1b4Smrg *
87117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
97117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
107117f1b4Smrg * to deal in the Software without restriction, including without limitation
117117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
127117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
137117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
147117f1b4Smrg *
157117f1b4Smrg * The above copyright notice and this permission notice shall be included
167117f1b4Smrg * in all copies or substantial portions of the Software.
177117f1b4Smrg *
187117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
197117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
217117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
227117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
237117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
247117f1b4Smrg */
257117f1b4Smrg
267117f1b4Smrg
277117f1b4Smrg/**
287117f1b4Smrg * \file image.c
297117f1b4Smrg * Image handling.
307117f1b4Smrg */
317117f1b4Smrg
327117f1b4Smrg
337117f1b4Smrg#include "glheader.h"
347117f1b4Smrg#include "colormac.h"
357117f1b4Smrg#include "image.h"
367117f1b4Smrg#include "imports.h"
377117f1b4Smrg#include "macros.h"
383464ebd5Sriastradh#include "mfeatures.h"
393464ebd5Sriastradh#include "mtypes.h"
407117f1b4Smrg
417117f1b4Smrg
427117f1b4Smrg/**
437117f1b4Smrg * NOTE:
447117f1b4Smrg * Normally, BYTE_TO_FLOAT(0) returns 0.00392  That causes problems when
457117f1b4Smrg * we later convert the float to a packed integer value (such as for
467117f1b4Smrg * GL_RGB5_A1) because we'll wind up with a non-zero value.
477117f1b4Smrg *
487117f1b4Smrg * We redefine the macros here so zero is handled correctly.
497117f1b4Smrg */
507117f1b4Smrg#undef BYTE_TO_FLOAT
517117f1b4Smrg#define BYTE_TO_FLOAT(B)    ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F)))
527117f1b4Smrg
537117f1b4Smrg#undef SHORT_TO_FLOAT
547117f1b4Smrg#define SHORT_TO_FLOAT(S)   ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)))
557117f1b4Smrg
567117f1b4Smrg
577117f1b4Smrg
587117f1b4Smrg/** Compute ceiling of integer quotient of A divided by B. */
597117f1b4Smrg#define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
607117f1b4Smrg
617117f1b4Smrg
627117f1b4Smrg/**
637117f1b4Smrg * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise.
647117f1b4Smrg */
65c1f859d4SmrgGLboolean
667117f1b4Smrg_mesa_type_is_packed(GLenum type)
677117f1b4Smrg{
687117f1b4Smrg   switch (type) {
697117f1b4Smrg   case GL_UNSIGNED_BYTE_3_3_2:
707117f1b4Smrg   case GL_UNSIGNED_BYTE_2_3_3_REV:
713464ebd5Sriastradh   case MESA_UNSIGNED_BYTE_4_4:
727117f1b4Smrg   case GL_UNSIGNED_SHORT_5_6_5:
737117f1b4Smrg   case GL_UNSIGNED_SHORT_5_6_5_REV:
747117f1b4Smrg   case GL_UNSIGNED_SHORT_4_4_4_4:
757117f1b4Smrg   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
767117f1b4Smrg   case GL_UNSIGNED_SHORT_5_5_5_1:
777117f1b4Smrg   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
787117f1b4Smrg   case GL_UNSIGNED_INT_8_8_8_8:
797117f1b4Smrg   case GL_UNSIGNED_INT_8_8_8_8_REV:
807117f1b4Smrg   case GL_UNSIGNED_INT_10_10_10_2:
817117f1b4Smrg   case GL_UNSIGNED_INT_2_10_10_10_REV:
827117f1b4Smrg   case GL_UNSIGNED_SHORT_8_8_MESA:
837117f1b4Smrg   case GL_UNSIGNED_SHORT_8_8_REV_MESA:
847117f1b4Smrg   case GL_UNSIGNED_INT_24_8_EXT:
853464ebd5Sriastradh   case GL_UNSIGNED_INT_5_9_9_9_REV:
863464ebd5Sriastradh   case GL_UNSIGNED_INT_10F_11F_11F_REV:
877117f1b4Smrg      return GL_TRUE;
887117f1b4Smrg   }
897117f1b4Smrg
907117f1b4Smrg   return GL_FALSE;
917117f1b4Smrg}
927117f1b4Smrg
937117f1b4Smrg
947117f1b4Smrg
957117f1b4Smrg/**
967117f1b4Smrg * Flip the order of the 2 bytes in each word in the given array.
977117f1b4Smrg *
987117f1b4Smrg * \param p array.
997117f1b4Smrg * \param n number of words.
1007117f1b4Smrg */
1017117f1b4Smrgvoid
1027117f1b4Smrg_mesa_swap2( GLushort *p, GLuint n )
1037117f1b4Smrg{
1047117f1b4Smrg   GLuint i;
1057117f1b4Smrg   for (i = 0; i < n; i++) {
1067117f1b4Smrg      p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
1077117f1b4Smrg   }
1087117f1b4Smrg}
1097117f1b4Smrg
1107117f1b4Smrg
1117117f1b4Smrg
1127117f1b4Smrg/*
1137117f1b4Smrg * Flip the order of the 4 bytes in each word in the given array.
1147117f1b4Smrg */
1157117f1b4Smrgvoid
1167117f1b4Smrg_mesa_swap4( GLuint *p, GLuint n )
1177117f1b4Smrg{
1187117f1b4Smrg   GLuint i, a, b;
1197117f1b4Smrg   for (i = 0; i < n; i++) {
1207117f1b4Smrg      b = p[i];
1217117f1b4Smrg      a =  (b >> 24)
1227117f1b4Smrg	| ((b >> 8) & 0xff00)
1237117f1b4Smrg	| ((b << 8) & 0xff0000)
1247117f1b4Smrg	| ((b << 24) & 0xff000000);
1257117f1b4Smrg      p[i] = a;
1267117f1b4Smrg   }
1277117f1b4Smrg}
1287117f1b4Smrg
1297117f1b4Smrg
1307117f1b4Smrg/**
1317117f1b4Smrg * Get the size of a GL data type.
1327117f1b4Smrg *
1337117f1b4Smrg * \param type GL data type.
1347117f1b4Smrg *
1357117f1b4Smrg * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1
1367117f1b4Smrg * if an invalid type enum.
1377117f1b4Smrg */
1387117f1b4SmrgGLint
1397117f1b4Smrg_mesa_sizeof_type( GLenum type )
1407117f1b4Smrg{
1417117f1b4Smrg   switch (type) {
1427117f1b4Smrg      case GL_BITMAP:
1437117f1b4Smrg	 return 0;
1447117f1b4Smrg      case GL_UNSIGNED_BYTE:
1457117f1b4Smrg         return sizeof(GLubyte);
1467117f1b4Smrg      case GL_BYTE:
1477117f1b4Smrg	 return sizeof(GLbyte);
1487117f1b4Smrg      case GL_UNSIGNED_SHORT:
1497117f1b4Smrg	 return sizeof(GLushort);
1507117f1b4Smrg      case GL_SHORT:
1517117f1b4Smrg	 return sizeof(GLshort);
1527117f1b4Smrg      case GL_UNSIGNED_INT:
1537117f1b4Smrg	 return sizeof(GLuint);
1547117f1b4Smrg      case GL_INT:
1557117f1b4Smrg	 return sizeof(GLint);
1567117f1b4Smrg      case GL_FLOAT:
1577117f1b4Smrg	 return sizeof(GLfloat);
1584a49301eSmrg      case GL_DOUBLE:
1594a49301eSmrg	 return sizeof(GLdouble);
1607117f1b4Smrg      case GL_HALF_FLOAT_ARB:
1617117f1b4Smrg	 return sizeof(GLhalfARB);
1623464ebd5Sriastradh      case GL_FIXED:
1633464ebd5Sriastradh	 return sizeof(GLfixed);
1647117f1b4Smrg      default:
1657117f1b4Smrg         return -1;
1667117f1b4Smrg   }
1677117f1b4Smrg}
1687117f1b4Smrg
1697117f1b4Smrg
1707117f1b4Smrg/**
1717117f1b4Smrg * Same as _mesa_sizeof_type() but also accepting the packed pixel
1727117f1b4Smrg * format data types.
1737117f1b4Smrg */
1747117f1b4SmrgGLint
1757117f1b4Smrg_mesa_sizeof_packed_type( GLenum type )
1767117f1b4Smrg{
1777117f1b4Smrg   switch (type) {
1787117f1b4Smrg      case GL_BITMAP:
1797117f1b4Smrg	 return 0;
1807117f1b4Smrg      case GL_UNSIGNED_BYTE:
1817117f1b4Smrg         return sizeof(GLubyte);
1827117f1b4Smrg      case GL_BYTE:
1837117f1b4Smrg	 return sizeof(GLbyte);
1847117f1b4Smrg      case GL_UNSIGNED_SHORT:
1857117f1b4Smrg	 return sizeof(GLushort);
1867117f1b4Smrg      case GL_SHORT:
1877117f1b4Smrg	 return sizeof(GLshort);
1887117f1b4Smrg      case GL_UNSIGNED_INT:
1897117f1b4Smrg	 return sizeof(GLuint);
1907117f1b4Smrg      case GL_INT:
1917117f1b4Smrg	 return sizeof(GLint);
1927117f1b4Smrg      case GL_HALF_FLOAT_ARB:
1937117f1b4Smrg	 return sizeof(GLhalfARB);
1947117f1b4Smrg      case GL_FLOAT:
1957117f1b4Smrg	 return sizeof(GLfloat);
1967117f1b4Smrg      case GL_UNSIGNED_BYTE_3_3_2:
1977117f1b4Smrg         return sizeof(GLubyte);
1987117f1b4Smrg      case GL_UNSIGNED_BYTE_2_3_3_REV:
1997117f1b4Smrg         return sizeof(GLubyte);
2003464ebd5Sriastradh      case MESA_UNSIGNED_BYTE_4_4:
2013464ebd5Sriastradh         return sizeof(GLubyte);
2027117f1b4Smrg      case GL_UNSIGNED_SHORT_5_6_5:
2037117f1b4Smrg         return sizeof(GLushort);
2047117f1b4Smrg      case GL_UNSIGNED_SHORT_5_6_5_REV:
2057117f1b4Smrg         return sizeof(GLushort);
2067117f1b4Smrg      case GL_UNSIGNED_SHORT_4_4_4_4:
2077117f1b4Smrg         return sizeof(GLushort);
2087117f1b4Smrg      case GL_UNSIGNED_SHORT_4_4_4_4_REV:
2097117f1b4Smrg         return sizeof(GLushort);
2107117f1b4Smrg      case GL_UNSIGNED_SHORT_5_5_5_1:
2117117f1b4Smrg         return sizeof(GLushort);
2127117f1b4Smrg      case GL_UNSIGNED_SHORT_1_5_5_5_REV:
2137117f1b4Smrg         return sizeof(GLushort);
2147117f1b4Smrg      case GL_UNSIGNED_INT_8_8_8_8:
2157117f1b4Smrg         return sizeof(GLuint);
2167117f1b4Smrg      case GL_UNSIGNED_INT_8_8_8_8_REV:
2177117f1b4Smrg         return sizeof(GLuint);
2187117f1b4Smrg      case GL_UNSIGNED_INT_10_10_10_2:
2197117f1b4Smrg         return sizeof(GLuint);
2207117f1b4Smrg      case GL_UNSIGNED_INT_2_10_10_10_REV:
2217117f1b4Smrg         return sizeof(GLuint);
2227117f1b4Smrg      case GL_UNSIGNED_SHORT_8_8_MESA:
2237117f1b4Smrg      case GL_UNSIGNED_SHORT_8_8_REV_MESA:
2247117f1b4Smrg         return sizeof(GLushort);
2257117f1b4Smrg      case GL_UNSIGNED_INT_24_8_EXT:
2267117f1b4Smrg         return sizeof(GLuint);
2273464ebd5Sriastradh      case GL_UNSIGNED_INT_5_9_9_9_REV:
2283464ebd5Sriastradh         return sizeof(GLuint);
2293464ebd5Sriastradh      case GL_UNSIGNED_INT_10F_11F_11F_REV:
2303464ebd5Sriastradh         return sizeof(GLuint);
2317117f1b4Smrg      default:
2327117f1b4Smrg         return -1;
2337117f1b4Smrg   }
2347117f1b4Smrg}
2357117f1b4Smrg
2367117f1b4Smrg
2377117f1b4Smrg/**
2387117f1b4Smrg * Get the number of components in a pixel format.
2397117f1b4Smrg *
2407117f1b4Smrg * \param format pixel format.
2417117f1b4Smrg *
2427117f1b4Smrg * \return the number of components in the given format, or -1 if a bad format.
2437117f1b4Smrg */
2447117f1b4SmrgGLint
2457117f1b4Smrg_mesa_components_in_format( GLenum format )
2467117f1b4Smrg{
2477117f1b4Smrg   switch (format) {
2487117f1b4Smrg      case GL_COLOR_INDEX:
2497117f1b4Smrg      case GL_COLOR_INDEX1_EXT:
2507117f1b4Smrg      case GL_COLOR_INDEX2_EXT:
2517117f1b4Smrg      case GL_COLOR_INDEX4_EXT:
2527117f1b4Smrg      case GL_COLOR_INDEX8_EXT:
2537117f1b4Smrg      case GL_COLOR_INDEX12_EXT:
2547117f1b4Smrg      case GL_COLOR_INDEX16_EXT:
2557117f1b4Smrg      case GL_STENCIL_INDEX:
2567117f1b4Smrg      case GL_DEPTH_COMPONENT:
2577117f1b4Smrg      case GL_RED:
2583464ebd5Sriastradh      case GL_RED_INTEGER_EXT:
2597117f1b4Smrg      case GL_GREEN:
2603464ebd5Sriastradh      case GL_GREEN_INTEGER_EXT:
2617117f1b4Smrg      case GL_BLUE:
2623464ebd5Sriastradh      case GL_BLUE_INTEGER_EXT:
2637117f1b4Smrg      case GL_ALPHA:
2643464ebd5Sriastradh      case GL_ALPHA_INTEGER_EXT:
2657117f1b4Smrg      case GL_LUMINANCE:
2663464ebd5Sriastradh      case GL_LUMINANCE_INTEGER_EXT:
2677117f1b4Smrg      case GL_INTENSITY:
2687117f1b4Smrg         return 1;
2697117f1b4Smrg      case GL_LUMINANCE_ALPHA:
2703464ebd5Sriastradh      case GL_LUMINANCE_ALPHA_INTEGER_EXT:
2713464ebd5Sriastradh      case GL_RG:
2727117f1b4Smrg	 return 2;
2737117f1b4Smrg      case GL_RGB:
2743464ebd5Sriastradh      case GL_RGB_INTEGER_EXT:
2757117f1b4Smrg	 return 3;
2767117f1b4Smrg      case GL_RGBA:
2773464ebd5Sriastradh      case GL_RGBA_INTEGER_EXT:
2787117f1b4Smrg	 return 4;
2797117f1b4Smrg      case GL_BGR:
2807117f1b4Smrg	 return 3;
2817117f1b4Smrg      case GL_BGRA:
2827117f1b4Smrg	 return 4;
2837117f1b4Smrg      case GL_ABGR_EXT:
2847117f1b4Smrg         return 4;
2857117f1b4Smrg      case GL_YCBCR_MESA:
2867117f1b4Smrg         return 2;
2877117f1b4Smrg      case GL_DEPTH_STENCIL_EXT:
2887117f1b4Smrg         return 2;
2894a49301eSmrg      case GL_DUDV_ATI:
2904a49301eSmrg      case GL_DU8DV8_ATI:
2914a49301eSmrg         return 2;
2927117f1b4Smrg      default:
2937117f1b4Smrg         return -1;
2947117f1b4Smrg   }
2957117f1b4Smrg}
2967117f1b4Smrg
2977117f1b4Smrg
2987117f1b4Smrg/**
2997117f1b4Smrg * Get the bytes per pixel of pixel format type pair.
3007117f1b4Smrg *
3017117f1b4Smrg * \param format pixel format.
3027117f1b4Smrg * \param type pixel type.
3037117f1b4Smrg *
3047117f1b4Smrg * \return bytes per pixel, or -1 if a bad format or type was given.
3057117f1b4Smrg */
3067117f1b4SmrgGLint
3077117f1b4Smrg_mesa_bytes_per_pixel( GLenum format, GLenum type )
3087117f1b4Smrg{
3097117f1b4Smrg   GLint comps = _mesa_components_in_format( format );
3107117f1b4Smrg   if (comps < 0)
3117117f1b4Smrg      return -1;
3127117f1b4Smrg
3137117f1b4Smrg   switch (type) {
3147117f1b4Smrg      case GL_BITMAP:
3157117f1b4Smrg         return 0;  /* special case */
3167117f1b4Smrg      case GL_BYTE:
3177117f1b4Smrg      case GL_UNSIGNED_BYTE:
3187117f1b4Smrg         return comps * sizeof(GLubyte);
3197117f1b4Smrg      case GL_SHORT:
3207117f1b4Smrg      case GL_UNSIGNED_SHORT:
3217117f1b4Smrg         return comps * sizeof(GLshort);
3227117f1b4Smrg      case GL_INT:
3237117f1b4Smrg      case GL_UNSIGNED_INT:
3247117f1b4Smrg         return comps * sizeof(GLint);
3257117f1b4Smrg      case GL_FLOAT:
3267117f1b4Smrg         return comps * sizeof(GLfloat);
3277117f1b4Smrg      case GL_HALF_FLOAT_ARB:
3287117f1b4Smrg         return comps * sizeof(GLhalfARB);
3297117f1b4Smrg      case GL_UNSIGNED_BYTE_3_3_2:
3307117f1b4Smrg      case GL_UNSIGNED_BYTE_2_3_3_REV:
3313464ebd5Sriastradh         if (format == GL_RGB || format == GL_BGR ||
3323464ebd5Sriastradh             format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT)
3337117f1b4Smrg            return sizeof(GLubyte);
3347117f1b4Smrg         else
3357117f1b4Smrg            return -1;  /* error */
3367117f1b4Smrg      case GL_UNSIGNED_SHORT_5_6_5:
3377117f1b4Smrg      case GL_UNSIGNED_SHORT_5_6_5_REV:
3383464ebd5Sriastradh         if (format == GL_RGB || format == GL_BGR ||
3393464ebd5Sriastradh             format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT)
3407117f1b4Smrg            return sizeof(GLushort);
3417117f1b4Smrg         else
3427117f1b4Smrg            return -1;  /* error */
3437117f1b4Smrg      case GL_UNSIGNED_SHORT_4_4_4_4:
3447117f1b4Smrg      case GL_UNSIGNED_SHORT_4_4_4_4_REV:
3457117f1b4Smrg      case GL_UNSIGNED_SHORT_5_5_5_1:
3467117f1b4Smrg      case GL_UNSIGNED_SHORT_1_5_5_5_REV:
3473464ebd5Sriastradh         if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT ||
3483464ebd5Sriastradh             format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
3497117f1b4Smrg            return sizeof(GLushort);
3507117f1b4Smrg         else
3517117f1b4Smrg            return -1;
3527117f1b4Smrg      case GL_UNSIGNED_INT_8_8_8_8:
3537117f1b4Smrg      case GL_UNSIGNED_INT_8_8_8_8_REV:
3547117f1b4Smrg      case GL_UNSIGNED_INT_10_10_10_2:
3557117f1b4Smrg      case GL_UNSIGNED_INT_2_10_10_10_REV:
3563464ebd5Sriastradh         if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT ||
3573464ebd5Sriastradh             format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT)
3587117f1b4Smrg            return sizeof(GLuint);
3597117f1b4Smrg         else
3607117f1b4Smrg            return -1;
3617117f1b4Smrg      case GL_UNSIGNED_SHORT_8_8_MESA:
3627117f1b4Smrg      case GL_UNSIGNED_SHORT_8_8_REV_MESA:
3637117f1b4Smrg         if (format == GL_YCBCR_MESA)
3647117f1b4Smrg            return sizeof(GLushort);
3657117f1b4Smrg         else
3667117f1b4Smrg            return -1;
3677117f1b4Smrg      case GL_UNSIGNED_INT_24_8_EXT:
3687117f1b4Smrg         if (format == GL_DEPTH_STENCIL_EXT)
3697117f1b4Smrg            return sizeof(GLuint);
3707117f1b4Smrg         else
3717117f1b4Smrg            return -1;
3723464ebd5Sriastradh      case GL_UNSIGNED_INT_5_9_9_9_REV:
3733464ebd5Sriastradh         if (format == GL_RGB)
3743464ebd5Sriastradh            return sizeof(GLuint);
3753464ebd5Sriastradh         else
3763464ebd5Sriastradh            return -1;
3773464ebd5Sriastradh      case GL_UNSIGNED_INT_10F_11F_11F_REV:
3783464ebd5Sriastradh         if (format == GL_RGB)
3793464ebd5Sriastradh            return sizeof(GLuint);
3803464ebd5Sriastradh         else
3813464ebd5Sriastradh            return -1;
3827117f1b4Smrg      default:
3837117f1b4Smrg         return -1;
3847117f1b4Smrg   }
3857117f1b4Smrg}
3867117f1b4Smrg
3877117f1b4Smrg
3887117f1b4Smrg/**
3897117f1b4Smrg * Test for a legal pixel format and type.
3907117f1b4Smrg *
3917117f1b4Smrg * \param format pixel format.
3927117f1b4Smrg * \param type pixel type.
3937117f1b4Smrg *
3947117f1b4Smrg * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE
3957117f1b4Smrg * otherwise.
3967117f1b4Smrg */
3977117f1b4SmrgGLboolean
3983464ebd5Sriastradh_mesa_is_legal_format_and_type(const struct gl_context *ctx,
3993464ebd5Sriastradh                               GLenum format, GLenum type)
4007117f1b4Smrg{
4017117f1b4Smrg   switch (format) {
4027117f1b4Smrg      case GL_COLOR_INDEX:
4037117f1b4Smrg      case GL_STENCIL_INDEX:
4047117f1b4Smrg         switch (type) {
4057117f1b4Smrg            case GL_BITMAP:
4067117f1b4Smrg            case GL_BYTE:
4077117f1b4Smrg            case GL_UNSIGNED_BYTE:
4087117f1b4Smrg            case GL_SHORT:
4097117f1b4Smrg            case GL_UNSIGNED_SHORT:
4107117f1b4Smrg            case GL_INT:
4117117f1b4Smrg            case GL_UNSIGNED_INT:
4127117f1b4Smrg            case GL_FLOAT:
4137117f1b4Smrg               return GL_TRUE;
4147117f1b4Smrg            case GL_HALF_FLOAT_ARB:
4157117f1b4Smrg               return ctx->Extensions.ARB_half_float_pixel;
4167117f1b4Smrg            default:
4177117f1b4Smrg               return GL_FALSE;
4187117f1b4Smrg         }
4197117f1b4Smrg      case GL_RED:
4207117f1b4Smrg      case GL_GREEN:
4217117f1b4Smrg      case GL_BLUE:
4227117f1b4Smrg      case GL_ALPHA:
4237117f1b4Smrg#if 0 /* not legal!  see table 3.6 of the 1.5 spec */
4247117f1b4Smrg      case GL_INTENSITY:
4257117f1b4Smrg#endif
4267117f1b4Smrg      case GL_LUMINANCE:
4277117f1b4Smrg      case GL_LUMINANCE_ALPHA:
4287117f1b4Smrg      case GL_DEPTH_COMPONENT:
4293464ebd5Sriastradh         switch (type) {
4303464ebd5Sriastradh            case GL_BYTE:
4313464ebd5Sriastradh            case GL_UNSIGNED_BYTE:
4323464ebd5Sriastradh            case GL_SHORT:
4333464ebd5Sriastradh            case GL_UNSIGNED_SHORT:
4343464ebd5Sriastradh            case GL_INT:
4353464ebd5Sriastradh            case GL_UNSIGNED_INT:
4363464ebd5Sriastradh            case GL_FLOAT:
4373464ebd5Sriastradh               return GL_TRUE;
4383464ebd5Sriastradh            case GL_HALF_FLOAT_ARB:
4393464ebd5Sriastradh               return ctx->Extensions.ARB_half_float_pixel;
4403464ebd5Sriastradh            default:
4413464ebd5Sriastradh               return GL_FALSE;
4423464ebd5Sriastradh         }
4433464ebd5Sriastradh      case GL_RG:
4443464ebd5Sriastradh	 if (!ctx->Extensions.ARB_texture_rg)
4453464ebd5Sriastradh	    return GL_FALSE;
4463464ebd5Sriastradh
4477117f1b4Smrg         switch (type) {
4487117f1b4Smrg            case GL_BYTE:
4497117f1b4Smrg            case GL_UNSIGNED_BYTE:
4507117f1b4Smrg            case GL_SHORT:
4517117f1b4Smrg            case GL_UNSIGNED_SHORT:
4527117f1b4Smrg            case GL_INT:
4537117f1b4Smrg            case GL_UNSIGNED_INT:
4547117f1b4Smrg            case GL_FLOAT:
4557117f1b4Smrg               return GL_TRUE;
4567117f1b4Smrg            case GL_HALF_FLOAT_ARB:
4577117f1b4Smrg               return ctx->Extensions.ARB_half_float_pixel;
4587117f1b4Smrg            default:
4597117f1b4Smrg               return GL_FALSE;
4607117f1b4Smrg         }
4617117f1b4Smrg      case GL_RGB:
4627117f1b4Smrg         switch (type) {
4637117f1b4Smrg            case GL_BYTE:
4647117f1b4Smrg            case GL_UNSIGNED_BYTE:
4657117f1b4Smrg            case GL_SHORT:
4667117f1b4Smrg            case GL_UNSIGNED_SHORT:
4677117f1b4Smrg            case GL_INT:
4687117f1b4Smrg            case GL_UNSIGNED_INT:
4697117f1b4Smrg            case GL_FLOAT:
4707117f1b4Smrg            case GL_UNSIGNED_BYTE_3_3_2:
4717117f1b4Smrg            case GL_UNSIGNED_BYTE_2_3_3_REV:
4727117f1b4Smrg            case GL_UNSIGNED_SHORT_5_6_5:
4737117f1b4Smrg            case GL_UNSIGNED_SHORT_5_6_5_REV:
4747117f1b4Smrg               return GL_TRUE;
4757117f1b4Smrg            case GL_HALF_FLOAT_ARB:
4767117f1b4Smrg               return ctx->Extensions.ARB_half_float_pixel;
4773464ebd5Sriastradh            case GL_UNSIGNED_INT_5_9_9_9_REV:
4783464ebd5Sriastradh               return ctx->Extensions.EXT_texture_shared_exponent;
4793464ebd5Sriastradh            case GL_UNSIGNED_INT_10F_11F_11F_REV:
4803464ebd5Sriastradh               return ctx->Extensions.EXT_packed_float;
4817117f1b4Smrg            default:
4827117f1b4Smrg               return GL_FALSE;
4837117f1b4Smrg         }
4847117f1b4Smrg      case GL_BGR:
4857117f1b4Smrg         switch (type) {
4867117f1b4Smrg            /* NOTE: no packed types are supported with BGR.  That's
4877117f1b4Smrg             * intentional, according to the GL spec.
4887117f1b4Smrg             */
4897117f1b4Smrg            case GL_BYTE:
4907117f1b4Smrg            case GL_UNSIGNED_BYTE:
4917117f1b4Smrg            case GL_SHORT:
4927117f1b4Smrg            case GL_UNSIGNED_SHORT:
4937117f1b4Smrg            case GL_INT:
4947117f1b4Smrg            case GL_UNSIGNED_INT:
4957117f1b4Smrg            case GL_FLOAT:
4967117f1b4Smrg               return GL_TRUE;
4977117f1b4Smrg            case GL_HALF_FLOAT_ARB:
4987117f1b4Smrg               return ctx->Extensions.ARB_half_float_pixel;
4997117f1b4Smrg            default:
5007117f1b4Smrg               return GL_FALSE;
5017117f1b4Smrg         }
5027117f1b4Smrg      case GL_RGBA:
5037117f1b4Smrg      case GL_BGRA:
5047117f1b4Smrg      case GL_ABGR_EXT:
5057117f1b4Smrg         switch (type) {
5067117f1b4Smrg            case GL_BYTE:
5077117f1b4Smrg            case GL_UNSIGNED_BYTE:
5087117f1b4Smrg            case GL_SHORT:
5097117f1b4Smrg            case GL_UNSIGNED_SHORT:
5107117f1b4Smrg            case GL_INT:
5117117f1b4Smrg            case GL_UNSIGNED_INT:
5127117f1b4Smrg            case GL_FLOAT:
5137117f1b4Smrg            case GL_UNSIGNED_SHORT_4_4_4_4:
5147117f1b4Smrg            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5157117f1b4Smrg            case GL_UNSIGNED_SHORT_5_5_5_1:
5167117f1b4Smrg            case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5177117f1b4Smrg            case GL_UNSIGNED_INT_8_8_8_8:
5187117f1b4Smrg            case GL_UNSIGNED_INT_8_8_8_8_REV:
5197117f1b4Smrg            case GL_UNSIGNED_INT_10_10_10_2:
5207117f1b4Smrg            case GL_UNSIGNED_INT_2_10_10_10_REV:
5217117f1b4Smrg               return GL_TRUE;
5227117f1b4Smrg            case GL_HALF_FLOAT_ARB:
5237117f1b4Smrg               return ctx->Extensions.ARB_half_float_pixel;
5247117f1b4Smrg            default:
5257117f1b4Smrg               return GL_FALSE;
5267117f1b4Smrg         }
5277117f1b4Smrg      case GL_YCBCR_MESA:
5287117f1b4Smrg         if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
5297117f1b4Smrg             type == GL_UNSIGNED_SHORT_8_8_REV_MESA)
5307117f1b4Smrg            return GL_TRUE;
5317117f1b4Smrg         else
5327117f1b4Smrg            return GL_FALSE;
5337117f1b4Smrg      case GL_DEPTH_STENCIL_EXT:
5347117f1b4Smrg         if (ctx->Extensions.EXT_packed_depth_stencil
5357117f1b4Smrg             && type == GL_UNSIGNED_INT_24_8_EXT)
5367117f1b4Smrg            return GL_TRUE;
5377117f1b4Smrg         else
5387117f1b4Smrg            return GL_FALSE;
5394a49301eSmrg      case GL_DUDV_ATI:
5404a49301eSmrg      case GL_DU8DV8_ATI:
5414a49301eSmrg         switch (type) {
5424a49301eSmrg            case GL_BYTE:
5434a49301eSmrg            case GL_UNSIGNED_BYTE:
5444a49301eSmrg            case GL_SHORT:
5454a49301eSmrg            case GL_UNSIGNED_SHORT:
5464a49301eSmrg            case GL_INT:
5474a49301eSmrg            case GL_UNSIGNED_INT:
5484a49301eSmrg            case GL_FLOAT:
5494a49301eSmrg               return GL_TRUE;
5504a49301eSmrg            default:
5514a49301eSmrg               return GL_FALSE;
5524a49301eSmrg         }
5533464ebd5Sriastradh
5543464ebd5Sriastradh      /* integer-valued formats */
5553464ebd5Sriastradh      case GL_RED_INTEGER_EXT:
5563464ebd5Sriastradh      case GL_GREEN_INTEGER_EXT:
5573464ebd5Sriastradh      case GL_BLUE_INTEGER_EXT:
5583464ebd5Sriastradh      case GL_ALPHA_INTEGER_EXT:
5593464ebd5Sriastradh         switch (type) {
5603464ebd5Sriastradh            case GL_BYTE:
5613464ebd5Sriastradh            case GL_UNSIGNED_BYTE:
5623464ebd5Sriastradh            case GL_SHORT:
5633464ebd5Sriastradh            case GL_UNSIGNED_SHORT:
5643464ebd5Sriastradh            case GL_INT:
5653464ebd5Sriastradh            case GL_UNSIGNED_INT:
5663464ebd5Sriastradh               return ctx->Extensions.EXT_texture_integer;
5673464ebd5Sriastradh            default:
5683464ebd5Sriastradh               return GL_FALSE;
5693464ebd5Sriastradh         }
5703464ebd5Sriastradh
5713464ebd5Sriastradh      case GL_RGB_INTEGER_EXT:
5723464ebd5Sriastradh         switch (type) {
5733464ebd5Sriastradh            case GL_BYTE:
5743464ebd5Sriastradh            case GL_UNSIGNED_BYTE:
5753464ebd5Sriastradh            case GL_SHORT:
5763464ebd5Sriastradh            case GL_UNSIGNED_SHORT:
5773464ebd5Sriastradh            case GL_INT:
5783464ebd5Sriastradh            case GL_UNSIGNED_INT:
5793464ebd5Sriastradh            case GL_UNSIGNED_BYTE_3_3_2:
5803464ebd5Sriastradh            case GL_UNSIGNED_BYTE_2_3_3_REV:
5813464ebd5Sriastradh            case GL_UNSIGNED_SHORT_5_6_5:
5823464ebd5Sriastradh            case GL_UNSIGNED_SHORT_5_6_5_REV:
5833464ebd5Sriastradh               return ctx->Extensions.EXT_texture_integer;
5843464ebd5Sriastradh            default:
5853464ebd5Sriastradh               return GL_FALSE;
5863464ebd5Sriastradh         }
5873464ebd5Sriastradh
5883464ebd5Sriastradh      case GL_BGR_INTEGER_EXT:
5893464ebd5Sriastradh         switch (type) {
5903464ebd5Sriastradh            case GL_BYTE:
5913464ebd5Sriastradh            case GL_UNSIGNED_BYTE:
5923464ebd5Sriastradh            case GL_SHORT:
5933464ebd5Sriastradh            case GL_UNSIGNED_SHORT:
5943464ebd5Sriastradh            case GL_INT:
5953464ebd5Sriastradh            case GL_UNSIGNED_INT:
5963464ebd5Sriastradh            /* NOTE: no packed formats w/ BGR format */
5973464ebd5Sriastradh               return ctx->Extensions.EXT_texture_integer;
5983464ebd5Sriastradh            default:
5993464ebd5Sriastradh               return GL_FALSE;
6003464ebd5Sriastradh         }
6013464ebd5Sriastradh
6023464ebd5Sriastradh      case GL_RGBA_INTEGER_EXT:
6033464ebd5Sriastradh      case GL_BGRA_INTEGER_EXT:
6043464ebd5Sriastradh         switch (type) {
6053464ebd5Sriastradh            case GL_BYTE:
6063464ebd5Sriastradh            case GL_UNSIGNED_BYTE:
6073464ebd5Sriastradh            case GL_SHORT:
6083464ebd5Sriastradh            case GL_UNSIGNED_SHORT:
6093464ebd5Sriastradh            case GL_INT:
6103464ebd5Sriastradh            case GL_UNSIGNED_INT:
6113464ebd5Sriastradh            case GL_UNSIGNED_SHORT_4_4_4_4:
6123464ebd5Sriastradh            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
6133464ebd5Sriastradh            case GL_UNSIGNED_SHORT_5_5_5_1:
6143464ebd5Sriastradh            case GL_UNSIGNED_SHORT_1_5_5_5_REV:
6153464ebd5Sriastradh            case GL_UNSIGNED_INT_8_8_8_8:
6163464ebd5Sriastradh            case GL_UNSIGNED_INT_8_8_8_8_REV:
6173464ebd5Sriastradh            case GL_UNSIGNED_INT_10_10_10_2:
6183464ebd5Sriastradh            case GL_UNSIGNED_INT_2_10_10_10_REV:
6193464ebd5Sriastradh               return ctx->Extensions.EXT_texture_integer;
6203464ebd5Sriastradh            default:
6213464ebd5Sriastradh               return GL_FALSE;
6223464ebd5Sriastradh         }
6233464ebd5Sriastradh
6243464ebd5Sriastradh      case GL_LUMINANCE_INTEGER_EXT:
6253464ebd5Sriastradh      case GL_LUMINANCE_ALPHA_INTEGER_EXT:
6263464ebd5Sriastradh         switch (type) {
6273464ebd5Sriastradh            case GL_BYTE:
6283464ebd5Sriastradh            case GL_UNSIGNED_BYTE:
6293464ebd5Sriastradh            case GL_SHORT:
6303464ebd5Sriastradh            case GL_UNSIGNED_SHORT:
6313464ebd5Sriastradh            case GL_INT:
6323464ebd5Sriastradh            case GL_UNSIGNED_INT:
6333464ebd5Sriastradh               return ctx->Extensions.EXT_texture_integer;
6343464ebd5Sriastradh            default:
6353464ebd5Sriastradh               return GL_FALSE;
6363464ebd5Sriastradh         }
6373464ebd5Sriastradh
6387117f1b4Smrg      default:
6397117f1b4Smrg         ; /* fall-through */
6407117f1b4Smrg   }
6417117f1b4Smrg   return GL_FALSE;
6427117f1b4Smrg}
6437117f1b4Smrg
6447117f1b4Smrg
6454a49301eSmrg/**
6464a49301eSmrg * Test if the given image format is a color/RGBA format (i.e., not color
6474a49301eSmrg * index, depth, stencil, etc).
6484a49301eSmrg * \param format  the image format value (may by an internal texture format)
6494a49301eSmrg * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
6504a49301eSmrg */
6514a49301eSmrgGLboolean
6524a49301eSmrg_mesa_is_color_format(GLenum format)
6534a49301eSmrg{
6544a49301eSmrg   switch (format) {
6554a49301eSmrg      case GL_RED:
6564a49301eSmrg      case GL_GREEN:
6574a49301eSmrg      case GL_BLUE:
6584a49301eSmrg      case GL_ALPHA:
6594a49301eSmrg      case GL_ALPHA4:
6604a49301eSmrg      case GL_ALPHA8:
6614a49301eSmrg      case GL_ALPHA12:
6624a49301eSmrg      case GL_ALPHA16:
6634a49301eSmrg      case 1:
6644a49301eSmrg      case GL_LUMINANCE:
6654a49301eSmrg      case GL_LUMINANCE4:
6664a49301eSmrg      case GL_LUMINANCE8:
6674a49301eSmrg      case GL_LUMINANCE12:
6684a49301eSmrg      case GL_LUMINANCE16:
6694a49301eSmrg      case 2:
6704a49301eSmrg      case GL_LUMINANCE_ALPHA:
6714a49301eSmrg      case GL_LUMINANCE4_ALPHA4:
6724a49301eSmrg      case GL_LUMINANCE6_ALPHA2:
6734a49301eSmrg      case GL_LUMINANCE8_ALPHA8:
6744a49301eSmrg      case GL_LUMINANCE12_ALPHA4:
6754a49301eSmrg      case GL_LUMINANCE12_ALPHA12:
6764a49301eSmrg      case GL_LUMINANCE16_ALPHA16:
6774a49301eSmrg      case GL_INTENSITY:
6784a49301eSmrg      case GL_INTENSITY4:
6794a49301eSmrg      case GL_INTENSITY8:
6804a49301eSmrg      case GL_INTENSITY12:
6814a49301eSmrg      case GL_INTENSITY16:
6823464ebd5Sriastradh      case GL_R8:
6833464ebd5Sriastradh      case GL_R16:
6843464ebd5Sriastradh      case GL_RG:
6853464ebd5Sriastradh      case GL_RG8:
6863464ebd5Sriastradh      case GL_RG16:
6874a49301eSmrg      case 3:
6884a49301eSmrg      case GL_RGB:
6894a49301eSmrg      case GL_BGR:
6904a49301eSmrg      case GL_R3_G3_B2:
6914a49301eSmrg      case GL_RGB4:
6924a49301eSmrg      case GL_RGB5:
6934a49301eSmrg      case GL_RGB8:
6944a49301eSmrg      case GL_RGB10:
6954a49301eSmrg      case GL_RGB12:
6964a49301eSmrg      case GL_RGB16:
6974a49301eSmrg      case 4:
6984a49301eSmrg      case GL_ABGR_EXT:
6994a49301eSmrg      case GL_RGBA:
7004a49301eSmrg      case GL_BGRA:
7014a49301eSmrg      case GL_RGBA2:
7024a49301eSmrg      case GL_RGBA4:
7034a49301eSmrg      case GL_RGB5_A1:
7044a49301eSmrg      case GL_RGBA8:
7054a49301eSmrg      case GL_RGB10_A2:
7064a49301eSmrg      case GL_RGBA12:
7074a49301eSmrg      case GL_RGBA16:
7084a49301eSmrg      /* float texture formats */
7094a49301eSmrg      case GL_ALPHA16F_ARB:
7104a49301eSmrg      case GL_ALPHA32F_ARB:
7114a49301eSmrg      case GL_LUMINANCE16F_ARB:
7124a49301eSmrg      case GL_LUMINANCE32F_ARB:
7134a49301eSmrg      case GL_LUMINANCE_ALPHA16F_ARB:
7144a49301eSmrg      case GL_LUMINANCE_ALPHA32F_ARB:
7154a49301eSmrg      case GL_INTENSITY16F_ARB:
7164a49301eSmrg      case GL_INTENSITY32F_ARB:
7173464ebd5Sriastradh      case GL_R16F:
7183464ebd5Sriastradh      case GL_R32F:
7193464ebd5Sriastradh      case GL_RG16F:
7203464ebd5Sriastradh      case GL_RG32F:
7214a49301eSmrg      case GL_RGB16F_ARB:
7224a49301eSmrg      case GL_RGB32F_ARB:
7234a49301eSmrg      case GL_RGBA16F_ARB:
7244a49301eSmrg      case GL_RGBA32F_ARB:
7254a49301eSmrg      /* compressed formats */
7264a49301eSmrg      case GL_COMPRESSED_ALPHA:
7274a49301eSmrg      case GL_COMPRESSED_LUMINANCE:
7284a49301eSmrg      case GL_COMPRESSED_LUMINANCE_ALPHA:
7294a49301eSmrg      case GL_COMPRESSED_INTENSITY:
7303464ebd5Sriastradh      case GL_COMPRESSED_RED:
7313464ebd5Sriastradh      case GL_COMPRESSED_RG:
7324a49301eSmrg      case GL_COMPRESSED_RGB:
7334a49301eSmrg      case GL_COMPRESSED_RGBA:
7344a49301eSmrg      case GL_RGB_S3TC:
7354a49301eSmrg      case GL_RGB4_S3TC:
7364a49301eSmrg      case GL_RGBA_S3TC:
7374a49301eSmrg      case GL_RGBA4_S3TC:
7384a49301eSmrg      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7394a49301eSmrg      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7404a49301eSmrg      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7414a49301eSmrg      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
7424a49301eSmrg      case GL_COMPRESSED_RGB_FXT1_3DFX:
7434a49301eSmrg      case GL_COMPRESSED_RGBA_FXT1_3DFX:
7444a49301eSmrg#if FEATURE_EXT_texture_sRGB
7454a49301eSmrg      case GL_SRGB_EXT:
7464a49301eSmrg      case GL_SRGB8_EXT:
7474a49301eSmrg      case GL_SRGB_ALPHA_EXT:
7484a49301eSmrg      case GL_SRGB8_ALPHA8_EXT:
7494a49301eSmrg      case GL_SLUMINANCE_ALPHA_EXT:
7504a49301eSmrg      case GL_SLUMINANCE8_ALPHA8_EXT:
7514a49301eSmrg      case GL_SLUMINANCE_EXT:
7524a49301eSmrg      case GL_SLUMINANCE8_EXT:
7534a49301eSmrg      case GL_COMPRESSED_SRGB_EXT:
7544a49301eSmrg      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
7554a49301eSmrg      case GL_COMPRESSED_SRGB_ALPHA_EXT:
7564a49301eSmrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
7574a49301eSmrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
7584a49301eSmrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
7594a49301eSmrg      case GL_COMPRESSED_SLUMINANCE_EXT:
7604a49301eSmrg      case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
7614a49301eSmrg#endif /* FEATURE_EXT_texture_sRGB */
7623464ebd5Sriastradh      case GL_COMPRESSED_RED_RGTC1:
7633464ebd5Sriastradh      case GL_COMPRESSED_SIGNED_RED_RGTC1:
7643464ebd5Sriastradh      case GL_COMPRESSED_RG_RGTC2:
7653464ebd5Sriastradh      case GL_COMPRESSED_SIGNED_RG_RGTC2:
7663464ebd5Sriastradh      case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
7673464ebd5Sriastradh      case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
7683464ebd5Sriastradh      case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
7693464ebd5Sriastradh      case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
7703464ebd5Sriastradh      case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
7713464ebd5Sriastradh      /* generic integer formats */
7723464ebd5Sriastradh      case GL_RED_INTEGER_EXT:
7733464ebd5Sriastradh      case GL_GREEN_INTEGER_EXT:
7743464ebd5Sriastradh      case GL_BLUE_INTEGER_EXT:
7753464ebd5Sriastradh      case GL_ALPHA_INTEGER_EXT:
7763464ebd5Sriastradh      case GL_RGB_INTEGER_EXT:
7773464ebd5Sriastradh      case GL_RGBA_INTEGER_EXT:
7783464ebd5Sriastradh      case GL_BGR_INTEGER_EXT:
7793464ebd5Sriastradh      case GL_BGRA_INTEGER_EXT:
7803464ebd5Sriastradh      case GL_LUMINANCE_INTEGER_EXT:
7813464ebd5Sriastradh      case GL_LUMINANCE_ALPHA_INTEGER_EXT:
7823464ebd5Sriastradh      /* sized integer formats */
7833464ebd5Sriastradh      case GL_RGBA32UI_EXT:
7843464ebd5Sriastradh      case GL_RGB32UI_EXT:
7853464ebd5Sriastradh      case GL_ALPHA32UI_EXT:
7863464ebd5Sriastradh      case GL_INTENSITY32UI_EXT:
7873464ebd5Sriastradh      case GL_LUMINANCE32UI_EXT:
7883464ebd5Sriastradh      case GL_LUMINANCE_ALPHA32UI_EXT:
7893464ebd5Sriastradh      case GL_RGBA16UI_EXT:
7903464ebd5Sriastradh      case GL_RGB16UI_EXT:
7913464ebd5Sriastradh      case GL_ALPHA16UI_EXT:
7923464ebd5Sriastradh      case GL_INTENSITY16UI_EXT:
7933464ebd5Sriastradh      case GL_LUMINANCE16UI_EXT:
7943464ebd5Sriastradh      case GL_LUMINANCE_ALPHA16UI_EXT:
7953464ebd5Sriastradh      case GL_RGBA8UI_EXT:
7963464ebd5Sriastradh      case GL_RGB8UI_EXT:
7973464ebd5Sriastradh      case GL_ALPHA8UI_EXT:
7983464ebd5Sriastradh      case GL_INTENSITY8UI_EXT:
7993464ebd5Sriastradh      case GL_LUMINANCE8UI_EXT:
8003464ebd5Sriastradh      case GL_LUMINANCE_ALPHA8UI_EXT:
8013464ebd5Sriastradh      case GL_RGBA32I_EXT:
8023464ebd5Sriastradh      case GL_RGB32I_EXT:
8033464ebd5Sriastradh      case GL_ALPHA32I_EXT:
8043464ebd5Sriastradh      case GL_INTENSITY32I_EXT:
8053464ebd5Sriastradh      case GL_LUMINANCE32I_EXT:
8063464ebd5Sriastradh      case GL_LUMINANCE_ALPHA32I_EXT:
8073464ebd5Sriastradh      case GL_RGBA16I_EXT:
8083464ebd5Sriastradh      case GL_RGB16I_EXT:
8093464ebd5Sriastradh      case GL_ALPHA16I_EXT:
8103464ebd5Sriastradh      case GL_INTENSITY16I_EXT:
8113464ebd5Sriastradh      case GL_LUMINANCE16I_EXT:
8123464ebd5Sriastradh      case GL_LUMINANCE_ALPHA16I_EXT:
8133464ebd5Sriastradh      case GL_RGBA8I_EXT:
8143464ebd5Sriastradh      case GL_RGB8I_EXT:
8153464ebd5Sriastradh      case GL_ALPHA8I_EXT:
8163464ebd5Sriastradh      case GL_INTENSITY8I_EXT:
8173464ebd5Sriastradh      case GL_LUMINANCE8I_EXT:
8183464ebd5Sriastradh      case GL_LUMINANCE_ALPHA8I_EXT:
8193464ebd5Sriastradh      /* signed, normalized texture formats */
8203464ebd5Sriastradh      case GL_RED_SNORM:
8213464ebd5Sriastradh      case GL_R8_SNORM:
8223464ebd5Sriastradh      case GL_R16_SNORM:
8233464ebd5Sriastradh      case GL_RG_SNORM:
8243464ebd5Sriastradh      case GL_RG8_SNORM:
8253464ebd5Sriastradh      case GL_RG16_SNORM:
8263464ebd5Sriastradh      case GL_RGB_SNORM:
8273464ebd5Sriastradh      case GL_RGB8_SNORM:
8283464ebd5Sriastradh      case GL_RGB16_SNORM:
8294a49301eSmrg      case GL_RGBA_SNORM:
8304a49301eSmrg      case GL_RGBA8_SNORM:
8313464ebd5Sriastradh      case GL_RGBA16_SNORM:
8323464ebd5Sriastradh      case GL_ALPHA_SNORM:
8333464ebd5Sriastradh      case GL_ALPHA8_SNORM:
8343464ebd5Sriastradh      case GL_ALPHA16_SNORM:
8353464ebd5Sriastradh      case GL_LUMINANCE_SNORM:
8363464ebd5Sriastradh      case GL_LUMINANCE8_SNORM:
8373464ebd5Sriastradh      case GL_LUMINANCE16_SNORM:
8383464ebd5Sriastradh      case GL_LUMINANCE_ALPHA_SNORM:
8393464ebd5Sriastradh      case GL_LUMINANCE8_ALPHA8_SNORM:
8403464ebd5Sriastradh      case GL_LUMINANCE16_ALPHA16_SNORM:
8413464ebd5Sriastradh      case GL_INTENSITY_SNORM:
8423464ebd5Sriastradh      case GL_INTENSITY8_SNORM:
8433464ebd5Sriastradh      case GL_INTENSITY16_SNORM:
8443464ebd5Sriastradh      case GL_RGB9_E5:
8453464ebd5Sriastradh      case GL_R11F_G11F_B10F:
8464a49301eSmrg         return GL_TRUE;
8474a49301eSmrg      case GL_YCBCR_MESA:  /* not considered to be RGB */
8484a49301eSmrg         /* fall-through */
8494a49301eSmrg      default:
8504a49301eSmrg         return GL_FALSE;
8514a49301eSmrg   }
8524a49301eSmrg}
8534a49301eSmrg
8544a49301eSmrg
8554a49301eSmrg/**
8564a49301eSmrg * Test if the given image format is a color index format.
8574a49301eSmrg */
8584a49301eSmrgGLboolean
8594a49301eSmrg_mesa_is_index_format(GLenum format)
8604a49301eSmrg{
8614a49301eSmrg   switch (format) {
8624a49301eSmrg      case GL_COLOR_INDEX:
8634a49301eSmrg      case GL_COLOR_INDEX1_EXT:
8644a49301eSmrg      case GL_COLOR_INDEX2_EXT:
8654a49301eSmrg      case GL_COLOR_INDEX4_EXT:
8664a49301eSmrg      case GL_COLOR_INDEX8_EXT:
8674a49301eSmrg      case GL_COLOR_INDEX12_EXT:
8684a49301eSmrg      case GL_COLOR_INDEX16_EXT:
8694a49301eSmrg         return GL_TRUE;
8704a49301eSmrg      default:
8714a49301eSmrg         return GL_FALSE;
8724a49301eSmrg   }
8734a49301eSmrg}
8744a49301eSmrg
8754a49301eSmrg
8764a49301eSmrg/**
8774a49301eSmrg * Test if the given image format is a depth component format.
8784a49301eSmrg */
8794a49301eSmrgGLboolean
8804a49301eSmrg_mesa_is_depth_format(GLenum format)
8814a49301eSmrg{
8824a49301eSmrg   switch (format) {
8834a49301eSmrg      case GL_DEPTH_COMPONENT:
8844a49301eSmrg      case GL_DEPTH_COMPONENT16:
8854a49301eSmrg      case GL_DEPTH_COMPONENT24:
8864a49301eSmrg      case GL_DEPTH_COMPONENT32:
8874a49301eSmrg         return GL_TRUE;
8884a49301eSmrg      default:
8894a49301eSmrg         return GL_FALSE;
8904a49301eSmrg   }
8914a49301eSmrg}
8924a49301eSmrg
8934a49301eSmrg
8944a49301eSmrg/**
8954a49301eSmrg * Test if the given image format is a stencil format.
8964a49301eSmrg */
8974a49301eSmrgGLboolean
8984a49301eSmrg_mesa_is_stencil_format(GLenum format)
8994a49301eSmrg{
9004a49301eSmrg   switch (format) {
9014a49301eSmrg      case GL_STENCIL_INDEX:
9024a49301eSmrg      case GL_DEPTH_STENCIL:
9034a49301eSmrg         return GL_TRUE;
9044a49301eSmrg      default:
9054a49301eSmrg         return GL_FALSE;
9064a49301eSmrg   }
9074a49301eSmrg}
9084a49301eSmrg
9094a49301eSmrg
9104a49301eSmrg/**
9114a49301eSmrg * Test if the given image format is a YCbCr format.
9124a49301eSmrg */
9134a49301eSmrgGLboolean
9144a49301eSmrg_mesa_is_ycbcr_format(GLenum format)
9154a49301eSmrg{
9164a49301eSmrg   switch (format) {
9174a49301eSmrg      case GL_YCBCR_MESA:
9184a49301eSmrg         return GL_TRUE;
9194a49301eSmrg      default:
9204a49301eSmrg         return GL_FALSE;
9214a49301eSmrg   }
9224a49301eSmrg}
9234a49301eSmrg
9244a49301eSmrg
9254a49301eSmrg/**
9264a49301eSmrg * Test if the given image format is a depth+stencil format.
9274a49301eSmrg */
9284a49301eSmrgGLboolean
9294a49301eSmrg_mesa_is_depthstencil_format(GLenum format)
9304a49301eSmrg{
9314a49301eSmrg   switch (format) {
9324a49301eSmrg      case GL_DEPTH24_STENCIL8_EXT:
9334a49301eSmrg      case GL_DEPTH_STENCIL_EXT:
9344a49301eSmrg         return GL_TRUE;
9354a49301eSmrg      default:
9364a49301eSmrg         return GL_FALSE;
9374a49301eSmrg   }
9384a49301eSmrg}
9394a49301eSmrg
9403464ebd5Sriastradh
9413464ebd5Sriastradh/**
9423464ebd5Sriastradh * Test if the given image format is a depth or stencil format.
9433464ebd5Sriastradh */
9443464ebd5SriastradhGLboolean
9453464ebd5Sriastradh_mesa_is_depth_or_stencil_format(GLenum format)
9463464ebd5Sriastradh{
9473464ebd5Sriastradh   switch (format) {
9483464ebd5Sriastradh      case GL_DEPTH_COMPONENT:
9493464ebd5Sriastradh      case GL_DEPTH_COMPONENT16:
9503464ebd5Sriastradh      case GL_DEPTH_COMPONENT24:
9513464ebd5Sriastradh      case GL_DEPTH_COMPONENT32:
9523464ebd5Sriastradh      case GL_STENCIL_INDEX:
9533464ebd5Sriastradh      case GL_STENCIL_INDEX1_EXT:
9543464ebd5Sriastradh      case GL_STENCIL_INDEX4_EXT:
9553464ebd5Sriastradh      case GL_STENCIL_INDEX8_EXT:
9563464ebd5Sriastradh      case GL_STENCIL_INDEX16_EXT:
9573464ebd5Sriastradh      case GL_DEPTH_STENCIL_EXT:
9583464ebd5Sriastradh      case GL_DEPTH24_STENCIL8_EXT:
9593464ebd5Sriastradh         return GL_TRUE;
9603464ebd5Sriastradh      default:
9613464ebd5Sriastradh         return GL_FALSE;
9623464ebd5Sriastradh   }
9633464ebd5Sriastradh}
9643464ebd5Sriastradh
9653464ebd5Sriastradh
9664a49301eSmrg/**
9674a49301eSmrg * Test if the given image format is a dudv format.
9684a49301eSmrg */
9694a49301eSmrgGLboolean
9704a49301eSmrg_mesa_is_dudv_format(GLenum format)
9714a49301eSmrg{
9724a49301eSmrg   switch (format) {
9734a49301eSmrg      case GL_DUDV_ATI:
9744a49301eSmrg      case GL_DU8DV8_ATI:
9754a49301eSmrg         return GL_TRUE;
9764a49301eSmrg      default:
9774a49301eSmrg         return GL_FALSE;
9784a49301eSmrg   }
9794a49301eSmrg}
9804a49301eSmrg
9814a49301eSmrg
9823464ebd5Sriastradh/**
9833464ebd5Sriastradh * Test if the given format is an integer (non-normalized) format.
9843464ebd5Sriastradh */
9853464ebd5SriastradhGLboolean
9863464ebd5Sriastradh_mesa_is_integer_format(GLenum format)
9873464ebd5Sriastradh{
9883464ebd5Sriastradh   switch (format) {
9893464ebd5Sriastradh   /* generic integer formats */
9903464ebd5Sriastradh   case GL_RED_INTEGER_EXT:
9913464ebd5Sriastradh   case GL_GREEN_INTEGER_EXT:
9923464ebd5Sriastradh   case GL_BLUE_INTEGER_EXT:
9933464ebd5Sriastradh   case GL_ALPHA_INTEGER_EXT:
9943464ebd5Sriastradh   case GL_RGB_INTEGER_EXT:
9953464ebd5Sriastradh   case GL_RGBA_INTEGER_EXT:
9963464ebd5Sriastradh   case GL_BGR_INTEGER_EXT:
9973464ebd5Sriastradh   case GL_BGRA_INTEGER_EXT:
9983464ebd5Sriastradh   case GL_LUMINANCE_INTEGER_EXT:
9993464ebd5Sriastradh   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
10003464ebd5Sriastradh   /* specific integer formats */
10013464ebd5Sriastradh   case GL_RGBA32UI_EXT:
10023464ebd5Sriastradh   case GL_RGB32UI_EXT:
10033464ebd5Sriastradh   case GL_ALPHA32UI_EXT:
10043464ebd5Sriastradh   case GL_INTENSITY32UI_EXT:
10053464ebd5Sriastradh   case GL_LUMINANCE32UI_EXT:
10063464ebd5Sriastradh   case GL_LUMINANCE_ALPHA32UI_EXT:
10073464ebd5Sriastradh   case GL_RGBA16UI_EXT:
10083464ebd5Sriastradh   case GL_RGB16UI_EXT:
10093464ebd5Sriastradh   case GL_ALPHA16UI_EXT:
10103464ebd5Sriastradh   case GL_INTENSITY16UI_EXT:
10113464ebd5Sriastradh   case GL_LUMINANCE16UI_EXT:
10123464ebd5Sriastradh   case GL_LUMINANCE_ALPHA16UI_EXT:
10133464ebd5Sriastradh   case GL_RGBA8UI_EXT:
10143464ebd5Sriastradh   case GL_RGB8UI_EXT:
10153464ebd5Sriastradh   case GL_ALPHA8UI_EXT:
10163464ebd5Sriastradh   case GL_INTENSITY8UI_EXT:
10173464ebd5Sriastradh   case GL_LUMINANCE8UI_EXT:
10183464ebd5Sriastradh   case GL_LUMINANCE_ALPHA8UI_EXT:
10193464ebd5Sriastradh   case GL_RGBA32I_EXT:
10203464ebd5Sriastradh   case GL_RGB32I_EXT:
10213464ebd5Sriastradh   case GL_ALPHA32I_EXT:
10223464ebd5Sriastradh   case GL_INTENSITY32I_EXT:
10233464ebd5Sriastradh   case GL_LUMINANCE32I_EXT:
10243464ebd5Sriastradh   case GL_LUMINANCE_ALPHA32I_EXT:
10253464ebd5Sriastradh   case GL_RGBA16I_EXT:
10263464ebd5Sriastradh   case GL_RGB16I_EXT:
10273464ebd5Sriastradh   case GL_ALPHA16I_EXT:
10283464ebd5Sriastradh   case GL_INTENSITY16I_EXT:
10293464ebd5Sriastradh   case GL_LUMINANCE16I_EXT:
10303464ebd5Sriastradh   case GL_LUMINANCE_ALPHA16I_EXT:
10313464ebd5Sriastradh   case GL_RGBA8I_EXT:
10323464ebd5Sriastradh   case GL_RGB8I_EXT:
10333464ebd5Sriastradh   case GL_ALPHA8I_EXT:
10343464ebd5Sriastradh   case GL_INTENSITY8I_EXT:
10353464ebd5Sriastradh   case GL_LUMINANCE8I_EXT:
10363464ebd5Sriastradh   case GL_LUMINANCE_ALPHA8I_EXT:
10373464ebd5Sriastradh      return GL_TRUE;
10383464ebd5Sriastradh   default:
10393464ebd5Sriastradh      return GL_FALSE;
10403464ebd5Sriastradh   }
10413464ebd5Sriastradh}
10423464ebd5Sriastradh
10433464ebd5Sriastradh
10443464ebd5Sriastradh/**
10453464ebd5Sriastradh * Test if an image format is a supported compressed format.
10463464ebd5Sriastradh * \param format the internal format token provided by the user.
10473464ebd5Sriastradh * \return GL_TRUE if compressed, GL_FALSE if uncompressed
10483464ebd5Sriastradh */
10493464ebd5SriastradhGLboolean
10503464ebd5Sriastradh_mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
10513464ebd5Sriastradh{
10523464ebd5Sriastradh   switch (format) {
10533464ebd5Sriastradh   case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
10543464ebd5Sriastradh   case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
10553464ebd5Sriastradh   case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
10563464ebd5Sriastradh   case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
10573464ebd5Sriastradh      return ctx->Extensions.EXT_texture_compression_s3tc;
10583464ebd5Sriastradh   case GL_RGB_S3TC:
10593464ebd5Sriastradh   case GL_RGB4_S3TC:
10603464ebd5Sriastradh   case GL_RGBA_S3TC:
10613464ebd5Sriastradh   case GL_RGBA4_S3TC:
10623464ebd5Sriastradh      return ctx->Extensions.S3_s3tc;
10633464ebd5Sriastradh   case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
10643464ebd5Sriastradh   case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
10653464ebd5Sriastradh   case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
10663464ebd5Sriastradh   case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
10673464ebd5Sriastradh      return ctx->Extensions.EXT_texture_sRGB
10683464ebd5Sriastradh         && ctx->Extensions.EXT_texture_compression_s3tc;
10693464ebd5Sriastradh   case GL_COMPRESSED_RGB_FXT1_3DFX:
10703464ebd5Sriastradh   case GL_COMPRESSED_RGBA_FXT1_3DFX:
10713464ebd5Sriastradh      return ctx->Extensions.TDFX_texture_compression_FXT1;
10723464ebd5Sriastradh   case GL_COMPRESSED_RED_RGTC1:
10733464ebd5Sriastradh   case GL_COMPRESSED_SIGNED_RED_RGTC1:
10743464ebd5Sriastradh   case GL_COMPRESSED_RG_RGTC2:
10753464ebd5Sriastradh   case GL_COMPRESSED_SIGNED_RG_RGTC2:
10763464ebd5Sriastradh      return ctx->Extensions.ARB_texture_compression_rgtc;
10773464ebd5Sriastradh   case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
10783464ebd5Sriastradh   case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
10793464ebd5Sriastradh   case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
10803464ebd5Sriastradh   case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
10813464ebd5Sriastradh      return ctx->Extensions.EXT_texture_compression_latc;
10823464ebd5Sriastradh   case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
10833464ebd5Sriastradh      return ctx->Extensions.ATI_texture_compression_3dc;
10843464ebd5Sriastradh#if FEATURE_ES
10853464ebd5Sriastradh   case GL_PALETTE4_RGB8_OES:
10863464ebd5Sriastradh   case GL_PALETTE4_RGBA8_OES:
10873464ebd5Sriastradh   case GL_PALETTE4_R5_G6_B5_OES:
10883464ebd5Sriastradh   case GL_PALETTE4_RGBA4_OES:
10893464ebd5Sriastradh   case GL_PALETTE4_RGB5_A1_OES:
10903464ebd5Sriastradh   case GL_PALETTE8_RGB8_OES:
10913464ebd5Sriastradh   case GL_PALETTE8_RGBA8_OES:
10923464ebd5Sriastradh   case GL_PALETTE8_R5_G6_B5_OES:
10933464ebd5Sriastradh   case GL_PALETTE8_RGBA4_OES:
10943464ebd5Sriastradh   case GL_PALETTE8_RGB5_A1_OES:
10953464ebd5Sriastradh      return ctx->API == API_OPENGLES;
10963464ebd5Sriastradh#endif
10973464ebd5Sriastradh   default:
10983464ebd5Sriastradh      return GL_FALSE;
10993464ebd5Sriastradh   }
11003464ebd5Sriastradh}
11013464ebd5Sriastradh
11023464ebd5Sriastradh
11037117f1b4Smrg/**
11047117f1b4Smrg * Return the address of a specific pixel in an image (1D, 2D or 3D).
11057117f1b4Smrg *
11067117f1b4Smrg * Pixel unpacking/packing parameters are observed according to \p packing.
11077117f1b4Smrg *
11087117f1b4Smrg * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
11097117f1b4Smrg * \param image  starting address of image data
11107117f1b4Smrg * \param width  the image width
11117117f1b4Smrg * \param height  theimage height
11127117f1b4Smrg * \param format  the pixel format
11137117f1b4Smrg * \param type  the pixel data type
11147117f1b4Smrg * \param packing  the pixelstore attributes
11157117f1b4Smrg * \param img  which image in the volume (0 for 1D or 2D images)
11167117f1b4Smrg * \param row  row of pixel in the image (0 for 1D images)
11177117f1b4Smrg * \param column column of pixel in the image
11187117f1b4Smrg *
11197117f1b4Smrg * \return address of pixel on success, or NULL on error.
11207117f1b4Smrg *
11217117f1b4Smrg * \sa gl_pixelstore_attrib.
11227117f1b4Smrg */
11237117f1b4SmrgGLvoid *
11247117f1b4Smrg_mesa_image_address( GLuint dimensions,
11257117f1b4Smrg                     const struct gl_pixelstore_attrib *packing,
11267117f1b4Smrg                     const GLvoid *image,
11277117f1b4Smrg                     GLsizei width, GLsizei height,
11287117f1b4Smrg                     GLenum format, GLenum type,
11297117f1b4Smrg                     GLint img, GLint row, GLint column )
11307117f1b4Smrg{
11317117f1b4Smrg   GLint alignment;        /* 1, 2 or 4 */
11327117f1b4Smrg   GLint pixels_per_row;
11337117f1b4Smrg   GLint rows_per_image;
11347117f1b4Smrg   GLint skiprows;
11357117f1b4Smrg   GLint skippixels;
11367117f1b4Smrg   GLint skipimages;       /* for 3-D volume images */
11377117f1b4Smrg   GLubyte *pixel_addr;
11387117f1b4Smrg
11397117f1b4Smrg   ASSERT(dimensions >= 1 && dimensions <= 3);
11407117f1b4Smrg
11417117f1b4Smrg   alignment = packing->Alignment;
11427117f1b4Smrg   if (packing->RowLength > 0) {
11437117f1b4Smrg      pixels_per_row = packing->RowLength;
11447117f1b4Smrg   }
11457117f1b4Smrg   else {
11467117f1b4Smrg      pixels_per_row = width;
11477117f1b4Smrg   }
11487117f1b4Smrg   if (packing->ImageHeight > 0) {
11497117f1b4Smrg      rows_per_image = packing->ImageHeight;
11507117f1b4Smrg   }
11517117f1b4Smrg   else {
11527117f1b4Smrg      rows_per_image = height;
11537117f1b4Smrg   }
11547117f1b4Smrg
11557117f1b4Smrg   skippixels = packing->SkipPixels;
11567117f1b4Smrg   /* Note: SKIP_ROWS _is_ used for 1D images */
11577117f1b4Smrg   skiprows = packing->SkipRows;
11587117f1b4Smrg   /* Note: SKIP_IMAGES is only used for 3D images */
11597117f1b4Smrg   skipimages = (dimensions == 3) ? packing->SkipImages : 0;
11607117f1b4Smrg
11617117f1b4Smrg   if (type == GL_BITMAP) {
11627117f1b4Smrg      /* BITMAP data */
11637117f1b4Smrg      GLint comp_per_pixel;   /* components per pixel */
11647117f1b4Smrg      GLint bytes_per_comp;   /* bytes per component */
11657117f1b4Smrg      GLint bytes_per_row;
11667117f1b4Smrg      GLint bytes_per_image;
11677117f1b4Smrg
11687117f1b4Smrg      /* Compute bytes per component */
11697117f1b4Smrg      bytes_per_comp = _mesa_sizeof_packed_type( type );
11707117f1b4Smrg      if (bytes_per_comp < 0) {
11717117f1b4Smrg         return NULL;
11727117f1b4Smrg      }
11737117f1b4Smrg
11747117f1b4Smrg      /* Compute number of components per pixel */
11757117f1b4Smrg      comp_per_pixel = _mesa_components_in_format( format );
11767117f1b4Smrg      if (comp_per_pixel < 0) {
11777117f1b4Smrg         return NULL;
11787117f1b4Smrg      }
11797117f1b4Smrg
11807117f1b4Smrg      bytes_per_row = alignment
11817117f1b4Smrg                    * CEILING( comp_per_pixel*pixels_per_row, 8*alignment );
11827117f1b4Smrg
11837117f1b4Smrg      bytes_per_image = bytes_per_row * rows_per_image;
11847117f1b4Smrg
11857117f1b4Smrg      pixel_addr = (GLubyte *) image
11867117f1b4Smrg                 + (skipimages + img) * bytes_per_image
11877117f1b4Smrg                 + (skiprows + row) * bytes_per_row
11887117f1b4Smrg                 + (skippixels + column) / 8;
11897117f1b4Smrg   }
11907117f1b4Smrg   else {
11917117f1b4Smrg      /* Non-BITMAP data */
11927117f1b4Smrg      GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
11937117f1b4Smrg      GLint topOfImage;
11947117f1b4Smrg
11957117f1b4Smrg      bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
11967117f1b4Smrg
11977117f1b4Smrg      /* The pixel type and format should have been error checked earlier */
11987117f1b4Smrg      assert(bytes_per_pixel > 0);
11997117f1b4Smrg
12007117f1b4Smrg      bytes_per_row = pixels_per_row * bytes_per_pixel;
12017117f1b4Smrg      remainder = bytes_per_row % alignment;
12027117f1b4Smrg      if (remainder > 0)
12037117f1b4Smrg         bytes_per_row += (alignment - remainder);
12047117f1b4Smrg
12057117f1b4Smrg      ASSERT(bytes_per_row % alignment == 0);
12067117f1b4Smrg
12077117f1b4Smrg      bytes_per_image = bytes_per_row * rows_per_image;
12087117f1b4Smrg
12097117f1b4Smrg      if (packing->Invert) {
12107117f1b4Smrg         /* set pixel_addr to the last row */
12117117f1b4Smrg         topOfImage = bytes_per_row * (height - 1);
12127117f1b4Smrg         bytes_per_row = -bytes_per_row;
12137117f1b4Smrg      }
12147117f1b4Smrg      else {
12157117f1b4Smrg         topOfImage = 0;
12167117f1b4Smrg      }
12177117f1b4Smrg
12187117f1b4Smrg      /* compute final pixel address */
12197117f1b4Smrg      pixel_addr = (GLubyte *) image
12207117f1b4Smrg                 + (skipimages + img) * bytes_per_image
12217117f1b4Smrg                 + topOfImage
12227117f1b4Smrg                 + (skiprows + row) * bytes_per_row
12237117f1b4Smrg                 + (skippixels + column) * bytes_per_pixel;
12247117f1b4Smrg   }
12257117f1b4Smrg
12267117f1b4Smrg   return (GLvoid *) pixel_addr;
12277117f1b4Smrg}
12287117f1b4Smrg
12297117f1b4Smrg
12307117f1b4SmrgGLvoid *
12317117f1b4Smrg_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
12327117f1b4Smrg                       const GLvoid *image,
12337117f1b4Smrg                       GLsizei width,
12347117f1b4Smrg                       GLenum format, GLenum type,
12357117f1b4Smrg                       GLint column )
12367117f1b4Smrg{
12377117f1b4Smrg   return _mesa_image_address(1, packing, image, width, 1,
12387117f1b4Smrg                              format, type, 0, 0, column);
12397117f1b4Smrg}
12407117f1b4Smrg
12417117f1b4Smrg
12427117f1b4SmrgGLvoid *
12437117f1b4Smrg_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
12447117f1b4Smrg                       const GLvoid *image,
12457117f1b4Smrg                       GLsizei width, GLsizei height,
12467117f1b4Smrg                       GLenum format, GLenum type,
12477117f1b4Smrg                       GLint row, GLint column )
12487117f1b4Smrg{
12497117f1b4Smrg   return _mesa_image_address(2, packing, image, width, height,
12507117f1b4Smrg                              format, type, 0, row, column);
12517117f1b4Smrg}
12527117f1b4Smrg
12537117f1b4Smrg
12547117f1b4SmrgGLvoid *
12557117f1b4Smrg_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
12567117f1b4Smrg                       const GLvoid *image,
12577117f1b4Smrg                       GLsizei width, GLsizei height,
12587117f1b4Smrg                       GLenum format, GLenum type,
12597117f1b4Smrg                       GLint img, GLint row, GLint column )
12607117f1b4Smrg{
12617117f1b4Smrg   return _mesa_image_address(3, packing, image, width, height,
12627117f1b4Smrg                              format, type, img, row, column);
12637117f1b4Smrg}
12647117f1b4Smrg
12657117f1b4Smrg
12667117f1b4Smrg
12677117f1b4Smrg/**
12687117f1b4Smrg * Compute the stride (in bytes) between image rows.
12697117f1b4Smrg *
12707117f1b4Smrg * \param packing the pixelstore attributes
12717117f1b4Smrg * \param width image width.
12727117f1b4Smrg * \param format pixel format.
12737117f1b4Smrg * \param type pixel data type.
12747117f1b4Smrg *
12757117f1b4Smrg * \return the stride in bytes for the given parameters, or -1 if error
12767117f1b4Smrg */
12777117f1b4SmrgGLint
12787117f1b4Smrg_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
12797117f1b4Smrg                        GLint width, GLenum format, GLenum type )
12807117f1b4Smrg{
12817117f1b4Smrg   GLint bytesPerRow, remainder;
12827117f1b4Smrg
12837117f1b4Smrg   ASSERT(packing);
12847117f1b4Smrg
12857117f1b4Smrg   if (type == GL_BITMAP) {
12867117f1b4Smrg      if (packing->RowLength == 0) {
12877117f1b4Smrg         bytesPerRow = (width + 7) / 8;
12887117f1b4Smrg      }
12897117f1b4Smrg      else {
12907117f1b4Smrg         bytesPerRow = (packing->RowLength + 7) / 8;
12917117f1b4Smrg      }
12927117f1b4Smrg   }
12937117f1b4Smrg   else {
12947117f1b4Smrg      /* Non-BITMAP data */
12957117f1b4Smrg      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
12967117f1b4Smrg      if (bytesPerPixel <= 0)
12977117f1b4Smrg         return -1;  /* error */
12987117f1b4Smrg      if (packing->RowLength == 0) {
12997117f1b4Smrg         bytesPerRow = bytesPerPixel * width;
13007117f1b4Smrg      }
13017117f1b4Smrg      else {
13027117f1b4Smrg         bytesPerRow = bytesPerPixel * packing->RowLength;
13037117f1b4Smrg      }
13047117f1b4Smrg   }
13057117f1b4Smrg
13067117f1b4Smrg   remainder = bytesPerRow % packing->Alignment;
13077117f1b4Smrg   if (remainder > 0) {
13087117f1b4Smrg      bytesPerRow += (packing->Alignment - remainder);
13097117f1b4Smrg   }
13107117f1b4Smrg
13117117f1b4Smrg   if (packing->Invert) {
13127117f1b4Smrg      /* negate the bytes per row (negative row stride) */
13137117f1b4Smrg      bytesPerRow = -bytesPerRow;
13147117f1b4Smrg   }
13157117f1b4Smrg
13167117f1b4Smrg   return bytesPerRow;
13177117f1b4Smrg}
13187117f1b4Smrg
13197117f1b4Smrg
13207117f1b4Smrg/*
13217117f1b4Smrg * Compute the stride between images in a 3D texture (in bytes) for the given
13227117f1b4Smrg * pixel packing parameters and image width, format and type.
13237117f1b4Smrg */
13247117f1b4SmrgGLint
13257117f1b4Smrg_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
13267117f1b4Smrg                          GLint width, GLint height,
13277117f1b4Smrg                          GLenum format, GLenum type )
13287117f1b4Smrg{
1329c7037ccdSmrg   GLint bytesPerRow, bytesPerImage, remainder;
1330c7037ccdSmrg
13317117f1b4Smrg   ASSERT(packing);
13327117f1b4Smrg
1333c7037ccdSmrg   if (type == GL_BITMAP) {
1334c7037ccdSmrg      if (packing->RowLength == 0) {
1335c7037ccdSmrg         bytesPerRow = (width + 7) / 8;
1336c7037ccdSmrg      }
1337c7037ccdSmrg      else {
1338c7037ccdSmrg         bytesPerRow = (packing->RowLength + 7) / 8;
1339c7037ccdSmrg      }
1340c7037ccdSmrg   }
1341c7037ccdSmrg   else {
13427117f1b4Smrg      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
13437117f1b4Smrg
13447117f1b4Smrg      if (bytesPerPixel <= 0)
13457117f1b4Smrg         return -1;  /* error */
13467117f1b4Smrg      if (packing->RowLength == 0) {
13477117f1b4Smrg         bytesPerRow = bytesPerPixel * width;
13487117f1b4Smrg      }
13497117f1b4Smrg      else {
13507117f1b4Smrg         bytesPerRow = bytesPerPixel * packing->RowLength;
13517117f1b4Smrg      }
1352c7037ccdSmrg   }
13537117f1b4Smrg
1354c7037ccdSmrg   remainder = bytesPerRow % packing->Alignment;
1355c7037ccdSmrg   if (remainder > 0)
1356c7037ccdSmrg      bytesPerRow += (packing->Alignment - remainder);
13577117f1b4Smrg
1358c7037ccdSmrg   if (packing->ImageHeight == 0)
1359c7037ccdSmrg      bytesPerImage = bytesPerRow * height;
1360c7037ccdSmrg   else
1361c7037ccdSmrg      bytesPerImage = bytesPerRow * packing->ImageHeight;
1362c7037ccdSmrg
1363c7037ccdSmrg   return bytesPerImage;
13647117f1b4Smrg}
13657117f1b4Smrg
13667117f1b4Smrg
13677117f1b4Smrg
13684a49301eSmrg/**
13694a49301eSmrg * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
13704a49301eSmrg * This is typically used to convert a bitmap into a GLubyte/pixel texture.
13714a49301eSmrg * "On" bits will set texels to \p onValue.
13724a49301eSmrg * "Off" bits will not modify texels.
13734a49301eSmrg * \param width  src bitmap width in pixels
13744a49301eSmrg * \param height  src bitmap height in pixels
13754a49301eSmrg * \param unpack  bitmap unpacking state
13764a49301eSmrg * \param bitmap  the src bitmap data
13774a49301eSmrg * \param destBuffer  start of dest buffer
13784a49301eSmrg * \param destStride  row stride in dest buffer
13794a49301eSmrg * \param onValue  if bit is 1, set destBuffer pixel to this value
13804a49301eSmrg */
13814a49301eSmrgvoid
13824a49301eSmrg_mesa_expand_bitmap(GLsizei width, GLsizei height,
13834a49301eSmrg                    const struct gl_pixelstore_attrib *unpack,
13844a49301eSmrg                    const GLubyte *bitmap,
13854a49301eSmrg                    GLubyte *destBuffer, GLint destStride,
13864a49301eSmrg                    GLubyte onValue)
13874a49301eSmrg{
13884a49301eSmrg   const GLubyte *srcRow = (const GLubyte *)
13894a49301eSmrg      _mesa_image_address2d(unpack, bitmap, width, height,
13904a49301eSmrg                            GL_COLOR_INDEX, GL_BITMAP, 0, 0);
13914a49301eSmrg   const GLint srcStride = _mesa_image_row_stride(unpack, width,
13924a49301eSmrg                                                  GL_COLOR_INDEX, GL_BITMAP);
13934a49301eSmrg   GLint row, col;
13944a49301eSmrg
13954a49301eSmrg#define SET_PIXEL(COL, ROW) \
13964a49301eSmrg   destBuffer[(ROW) * destStride + (COL)] = onValue;
13974a49301eSmrg
13984a49301eSmrg   for (row = 0; row < height; row++) {
13994a49301eSmrg      const GLubyte *src = srcRow;
14004a49301eSmrg
14014a49301eSmrg      if (unpack->LsbFirst) {
14024a49301eSmrg         /* Lsb first */
14034a49301eSmrg         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
14044a49301eSmrg         for (col = 0; col < width; col++) {
14054a49301eSmrg
14064a49301eSmrg            if (*src & mask) {
14074a49301eSmrg               SET_PIXEL(col, row);
14084a49301eSmrg            }
14094a49301eSmrg
14104a49301eSmrg            if (mask == 128U) {
14114a49301eSmrg               src++;
14124a49301eSmrg               mask = 1U;
14134a49301eSmrg            }
14144a49301eSmrg            else {
14154a49301eSmrg               mask = mask << 1;
14164a49301eSmrg            }
14174a49301eSmrg         }
14184a49301eSmrg
14194a49301eSmrg         /* get ready for next row */
14204a49301eSmrg         if (mask != 1)
14214a49301eSmrg            src++;
14224a49301eSmrg      }
14234a49301eSmrg      else {
14244a49301eSmrg         /* Msb first */
14254a49301eSmrg         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
14264a49301eSmrg         for (col = 0; col < width; col++) {
14274a49301eSmrg
14284a49301eSmrg            if (*src & mask) {
14294a49301eSmrg               SET_PIXEL(col, row);
14304a49301eSmrg            }
14314a49301eSmrg
14324a49301eSmrg            if (mask == 1U) {
14334a49301eSmrg               src++;
14344a49301eSmrg               mask = 128U;
14354a49301eSmrg            }
14364a49301eSmrg            else {
14374a49301eSmrg               mask = mask >> 1;
14384a49301eSmrg            }
14394a49301eSmrg         }
14404a49301eSmrg
14414a49301eSmrg         /* get ready for next row */
14424a49301eSmrg         if (mask != 128)
14434a49301eSmrg            src++;
14444a49301eSmrg      }
14454a49301eSmrg
14464a49301eSmrg      srcRow += srcStride;
14474a49301eSmrg   } /* row */
14484a49301eSmrg
14494a49301eSmrg#undef SET_PIXEL
14504a49301eSmrg}
14514a49301eSmrg
14524a49301eSmrg
1453c1f859d4Smrg
1454c1f859d4Smrg
1455c1f859d4Smrg/**
14563464ebd5Sriastradh * Convert an array of RGBA colors from one datatype to another.
14573464ebd5Sriastradh * NOTE: src may equal dst.  In that case, we use a temporary buffer.
1458c1f859d4Smrg */
1459c1f859d4Smrgvoid
14603464ebd5Sriastradh_mesa_convert_colors(GLenum srcType, const GLvoid *src,
14613464ebd5Sriastradh                     GLenum dstType, GLvoid *dst,
14623464ebd5Sriastradh                     GLuint count, const GLubyte mask[])
1463c1f859d4Smrg{
14643464ebd5Sriastradh   GLuint tempBuffer[MAX_WIDTH][4];
14653464ebd5Sriastradh   const GLboolean useTemp = (src == dst);
1466c1f859d4Smrg
14673464ebd5Sriastradh   ASSERT(srcType != dstType);
14687117f1b4Smrg
14697117f1b4Smrg   switch (srcType) {
14707117f1b4Smrg   case GL_UNSIGNED_BYTE:
14717117f1b4Smrg      if (dstType == GL_UNSIGNED_SHORT) {
14727117f1b4Smrg         const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
14737117f1b4Smrg         GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
14747117f1b4Smrg         GLuint i;
14757117f1b4Smrg         for (i = 0; i < count; i++) {
14767117f1b4Smrg            if (!mask || mask[i]) {
14777117f1b4Smrg               dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]);
14787117f1b4Smrg               dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]);
14797117f1b4Smrg               dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]);
14807117f1b4Smrg               dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]);
14817117f1b4Smrg            }
14827117f1b4Smrg         }
14837117f1b4Smrg         if (useTemp)
1484cdc920a0Smrg            memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
14857117f1b4Smrg      }
14867117f1b4Smrg      else {
14877117f1b4Smrg         const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
14887117f1b4Smrg         GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
14897117f1b4Smrg         GLuint i;
14907117f1b4Smrg         ASSERT(dstType == GL_FLOAT);
14917117f1b4Smrg         for (i = 0; i < count; i++) {
14927117f1b4Smrg            if (!mask || mask[i]) {
14937117f1b4Smrg               dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]);
14947117f1b4Smrg               dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]);
14957117f1b4Smrg               dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]);
14967117f1b4Smrg               dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]);
14977117f1b4Smrg            }
14987117f1b4Smrg         }
14997117f1b4Smrg         if (useTemp)
1500cdc920a0Smrg            memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
15017117f1b4Smrg      }
15027117f1b4Smrg      break;
15037117f1b4Smrg   case GL_UNSIGNED_SHORT:
15047117f1b4Smrg      if (dstType == GL_UNSIGNED_BYTE) {
15057117f1b4Smrg         const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
15067117f1b4Smrg         GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
15077117f1b4Smrg         GLuint i;
15087117f1b4Smrg         for (i = 0; i < count; i++) {
15097117f1b4Smrg            if (!mask || mask[i]) {
15107117f1b4Smrg               dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]);
15117117f1b4Smrg               dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]);
15127117f1b4Smrg               dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]);
15137117f1b4Smrg               dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]);
15147117f1b4Smrg            }
15157117f1b4Smrg         }
15167117f1b4Smrg         if (useTemp)
1517cdc920a0Smrg            memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
15187117f1b4Smrg      }
15197117f1b4Smrg      else {
15207117f1b4Smrg         const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
15217117f1b4Smrg         GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
15227117f1b4Smrg         GLuint i;
15237117f1b4Smrg         ASSERT(dstType == GL_FLOAT);
15247117f1b4Smrg         for (i = 0; i < count; i++) {
15257117f1b4Smrg            if (!mask || mask[i]) {
15267117f1b4Smrg               dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]);
15277117f1b4Smrg               dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]);
15287117f1b4Smrg               dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]);
15297117f1b4Smrg               dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]);
15307117f1b4Smrg            }
15317117f1b4Smrg         }
15327117f1b4Smrg         if (useTemp)
1533cdc920a0Smrg            memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
15347117f1b4Smrg      }
15357117f1b4Smrg      break;
15367117f1b4Smrg   case GL_FLOAT:
15377117f1b4Smrg      if (dstType == GL_UNSIGNED_BYTE) {
15387117f1b4Smrg         const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
15397117f1b4Smrg         GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
15407117f1b4Smrg         GLuint i;
15417117f1b4Smrg         for (i = 0; i < count; i++) {
15427117f1b4Smrg            if (!mask || mask[i]) {
15437117f1b4Smrg               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]);
15447117f1b4Smrg               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]);
15457117f1b4Smrg               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]);
15467117f1b4Smrg               UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]);
15477117f1b4Smrg            }
15487117f1b4Smrg         }
15497117f1b4Smrg         if (useTemp)
1550cdc920a0Smrg            memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
15517117f1b4Smrg      }
15527117f1b4Smrg      else {
15537117f1b4Smrg         const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
15547117f1b4Smrg         GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
15557117f1b4Smrg         GLuint i;
15567117f1b4Smrg         ASSERT(dstType == GL_UNSIGNED_SHORT);
15577117f1b4Smrg         for (i = 0; i < count; i++) {
15587117f1b4Smrg            if (!mask || mask[i]) {
15597117f1b4Smrg               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]);
15607117f1b4Smrg               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]);
15617117f1b4Smrg               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]);
15627117f1b4Smrg               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]);
15637117f1b4Smrg            }
15647117f1b4Smrg         }
15657117f1b4Smrg         if (useTemp)
1566cdc920a0Smrg            memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
15677117f1b4Smrg      }
15687117f1b4Smrg      break;
15697117f1b4Smrg   default:
15707117f1b4Smrg      _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
15717117f1b4Smrg   }
15727117f1b4Smrg}
15737117f1b4Smrg
15747117f1b4Smrg
15757117f1b4Smrg
15767117f1b4Smrg
15777117f1b4Smrg/**
15787117f1b4Smrg * Perform basic clipping for glDrawPixels.  The image's position and size
15797117f1b4Smrg * and the unpack SkipPixels and SkipRows are adjusted so that the image
15807117f1b4Smrg * region is entirely within the window and scissor bounds.
15817117f1b4Smrg * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
15827117f1b4Smrg * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
15837117f1b4Smrg * we'll actually write.  Beforehand, *destY-1 is the first drawing row.
15847117f1b4Smrg *
15857117f1b4Smrg * \return  GL_TRUE if image is ready for drawing or
15867117f1b4Smrg *          GL_FALSE if image was completely clipped away (draw nothing)
15877117f1b4Smrg */
15887117f1b4SmrgGLboolean
15893464ebd5Sriastradh_mesa_clip_drawpixels(const struct gl_context *ctx,
15907117f1b4Smrg                      GLint *destX, GLint *destY,
15917117f1b4Smrg                      GLsizei *width, GLsizei *height,
15927117f1b4Smrg                      struct gl_pixelstore_attrib *unpack)
15937117f1b4Smrg{
15943464ebd5Sriastradh   const struct gl_framebuffer *buffer = ctx->DrawBuffer;
15957117f1b4Smrg
15967117f1b4Smrg   if (unpack->RowLength == 0) {
15977117f1b4Smrg      unpack->RowLength = *width;
15987117f1b4Smrg   }
15997117f1b4Smrg
16007117f1b4Smrg   ASSERT(ctx->Pixel.ZoomX == 1.0F);
16017117f1b4Smrg   ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
16027117f1b4Smrg
16037117f1b4Smrg   /* left clipping */
16047117f1b4Smrg   if (*destX < buffer->_Xmin) {
16057117f1b4Smrg      unpack->SkipPixels += (buffer->_Xmin - *destX);
16067117f1b4Smrg      *width -= (buffer->_Xmin - *destX);
16077117f1b4Smrg      *destX = buffer->_Xmin;
16087117f1b4Smrg   }
16097117f1b4Smrg   /* right clipping */
16107117f1b4Smrg   if (*destX + *width > buffer->_Xmax)
16117117f1b4Smrg      *width -= (*destX + *width - buffer->_Xmax);
16127117f1b4Smrg
16137117f1b4Smrg   if (*width <= 0)
16147117f1b4Smrg      return GL_FALSE;
16157117f1b4Smrg
16167117f1b4Smrg   if (ctx->Pixel.ZoomY == 1.0F) {
16177117f1b4Smrg      /* bottom clipping */
16187117f1b4Smrg      if (*destY < buffer->_Ymin) {
16197117f1b4Smrg         unpack->SkipRows += (buffer->_Ymin - *destY);
16207117f1b4Smrg         *height -= (buffer->_Ymin - *destY);
16217117f1b4Smrg         *destY = buffer->_Ymin;
16227117f1b4Smrg      }
16237117f1b4Smrg      /* top clipping */
16247117f1b4Smrg      if (*destY + *height > buffer->_Ymax)
16257117f1b4Smrg         *height -= (*destY + *height - buffer->_Ymax);
16267117f1b4Smrg   }
16277117f1b4Smrg   else { /* upside down */
16287117f1b4Smrg      /* top clipping */
16297117f1b4Smrg      if (*destY > buffer->_Ymax) {
16307117f1b4Smrg         unpack->SkipRows += (*destY - buffer->_Ymax);
16317117f1b4Smrg         *height -= (*destY - buffer->_Ymax);
16327117f1b4Smrg         *destY = buffer->_Ymax;
16337117f1b4Smrg      }
16347117f1b4Smrg      /* bottom clipping */
16357117f1b4Smrg      if (*destY - *height < buffer->_Ymin)
16367117f1b4Smrg         *height -= (buffer->_Ymin - (*destY - *height));
16377117f1b4Smrg      /* adjust destY so it's the first row to write to */
16387117f1b4Smrg      (*destY)--;
16397117f1b4Smrg   }
16407117f1b4Smrg
16417117f1b4Smrg   if (*height <= 0)
16424a49301eSmrg      return GL_FALSE;
16437117f1b4Smrg
16447117f1b4Smrg   return GL_TRUE;
16457117f1b4Smrg}
16467117f1b4Smrg
16477117f1b4Smrg
16487117f1b4Smrg/**
16497117f1b4Smrg * Perform clipping for glReadPixels.  The image's window position
16507117f1b4Smrg * and size, and the pack skipPixels, skipRows and rowLength are adjusted
16517117f1b4Smrg * so that the image region is entirely within the window bounds.
16527117f1b4Smrg * Note: this is different from _mesa_clip_drawpixels() in that the
16537117f1b4Smrg * scissor box is ignored, and we use the bounds of the current readbuffer
16547117f1b4Smrg * surface.
16557117f1b4Smrg *
16563464ebd5Sriastradh * \return  GL_TRUE if region to read is in bounds
16573464ebd5Sriastradh *          GL_FALSE if region is completely out of bounds (nothing to read)
16587117f1b4Smrg */
16597117f1b4SmrgGLboolean
16603464ebd5Sriastradh_mesa_clip_readpixels(const struct gl_context *ctx,
16617117f1b4Smrg                      GLint *srcX, GLint *srcY,
16627117f1b4Smrg                      GLsizei *width, GLsizei *height,
16637117f1b4Smrg                      struct gl_pixelstore_attrib *pack)
16647117f1b4Smrg{
16653464ebd5Sriastradh   const struct gl_framebuffer *buffer = ctx->ReadBuffer;
16667117f1b4Smrg
16677117f1b4Smrg   if (pack->RowLength == 0) {
16687117f1b4Smrg      pack->RowLength = *width;
16697117f1b4Smrg   }
16707117f1b4Smrg
16717117f1b4Smrg   /* left clipping */
16727117f1b4Smrg   if (*srcX < 0) {
16737117f1b4Smrg      pack->SkipPixels += (0 - *srcX);
16747117f1b4Smrg      *width -= (0 - *srcX);
16757117f1b4Smrg      *srcX = 0;
16767117f1b4Smrg   }
16777117f1b4Smrg   /* right clipping */
16787117f1b4Smrg   if (*srcX + *width > (GLsizei) buffer->Width)
16797117f1b4Smrg      *width -= (*srcX + *width - buffer->Width);
16807117f1b4Smrg
16817117f1b4Smrg   if (*width <= 0)
16827117f1b4Smrg      return GL_FALSE;
16837117f1b4Smrg
16847117f1b4Smrg   /* bottom clipping */
16857117f1b4Smrg   if (*srcY < 0) {
16867117f1b4Smrg      pack->SkipRows += (0 - *srcY);
16877117f1b4Smrg      *height -= (0 - *srcY);
16887117f1b4Smrg      *srcY = 0;
16897117f1b4Smrg   }
16907117f1b4Smrg   /* top clipping */
16917117f1b4Smrg   if (*srcY + *height > (GLsizei) buffer->Height)
16927117f1b4Smrg      *height -= (*srcY + *height - buffer->Height);
16937117f1b4Smrg
16947117f1b4Smrg   if (*height <= 0)
16954a49301eSmrg      return GL_FALSE;
16967117f1b4Smrg
16977117f1b4Smrg   return GL_TRUE;
16987117f1b4Smrg}
16997117f1b4Smrg
17007117f1b4Smrg
1701c1f859d4Smrg/**
1702c1f859d4Smrg * Do clipping for a glCopyTexSubImage call.
1703c1f859d4Smrg * The framebuffer source region might extend outside the framebuffer
1704c1f859d4Smrg * bounds.  Clip the source region against the framebuffer bounds and
1705c1f859d4Smrg * adjust the texture/dest position and size accordingly.
1706c1f859d4Smrg *
1707c1f859d4Smrg * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
1708c1f859d4Smrg */
1709c1f859d4SmrgGLboolean
17103464ebd5Sriastradh_mesa_clip_copytexsubimage(const struct gl_context *ctx,
1711c1f859d4Smrg                           GLint *destX, GLint *destY,
1712c1f859d4Smrg                           GLint *srcX, GLint *srcY,
1713c1f859d4Smrg                           GLsizei *width, GLsizei *height)
1714c1f859d4Smrg{
1715c1f859d4Smrg   const struct gl_framebuffer *fb = ctx->ReadBuffer;
1716c1f859d4Smrg   const GLint srcX0 = *srcX, srcY0 = *srcY;
1717c1f859d4Smrg
1718c1f859d4Smrg   if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
1719c1f859d4Smrg                            srcX, srcY, width, height)) {
1720c1f859d4Smrg      *destX = *destX + *srcX - srcX0;
1721c1f859d4Smrg      *destY = *destY + *srcY - srcY0;
1722c1f859d4Smrg
1723c1f859d4Smrg      return GL_TRUE;
1724c1f859d4Smrg   }
1725c1f859d4Smrg   else {
1726c1f859d4Smrg      return GL_FALSE;
1727c1f859d4Smrg   }
1728c1f859d4Smrg}
1729c1f859d4Smrg
1730c1f859d4Smrg
1731c1f859d4Smrg
17327117f1b4Smrg/**
17337117f1b4Smrg * Clip the rectangle defined by (x, y, width, height) against the bounds
17347117f1b4Smrg * specified by [xmin, xmax) and [ymin, ymax).
17357117f1b4Smrg * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
17367117f1b4Smrg */
17377117f1b4SmrgGLboolean
17387117f1b4Smrg_mesa_clip_to_region(GLint xmin, GLint ymin,
17397117f1b4Smrg                     GLint xmax, GLint ymax,
17407117f1b4Smrg                     GLint *x, GLint *y,
17417117f1b4Smrg                     GLsizei *width, GLsizei *height )
17427117f1b4Smrg{
17437117f1b4Smrg   /* left clipping */
17447117f1b4Smrg   if (*x < xmin) {
17457117f1b4Smrg      *width -= (xmin - *x);
17467117f1b4Smrg      *x = xmin;
17477117f1b4Smrg   }
17487117f1b4Smrg
17497117f1b4Smrg   /* right clipping */
17507117f1b4Smrg   if (*x + *width > xmax)
1751c1f859d4Smrg      *width -= (*x + *width - xmax);
17527117f1b4Smrg
17537117f1b4Smrg   if (*width <= 0)
17547117f1b4Smrg      return GL_FALSE;
17557117f1b4Smrg
17567117f1b4Smrg   /* bottom (or top) clipping */
17577117f1b4Smrg   if (*y < ymin) {
17587117f1b4Smrg      *height -= (ymin - *y);
17597117f1b4Smrg      *y = ymin;
17607117f1b4Smrg   }
17617117f1b4Smrg
17627117f1b4Smrg   /* top (or bottom) clipping */
17637117f1b4Smrg   if (*y + *height > ymax)
1764c1f859d4Smrg      *height -= (*y + *height - ymax);
17657117f1b4Smrg
17667117f1b4Smrg   if (*height <= 0)
17677117f1b4Smrg      return GL_FALSE;
17687117f1b4Smrg
17697117f1b4Smrg   return GL_TRUE;
17707117f1b4Smrg}
17714a49301eSmrg
17724a49301eSmrg
17734a49301eSmrg/**
17744a49301eSmrg * Clip dst coords against Xmax (or Ymax).
17754a49301eSmrg */
17764a49301eSmrgstatic INLINE void
17774a49301eSmrgclip_right_or_top(GLint *srcX0, GLint *srcX1,
17784a49301eSmrg                  GLint *dstX0, GLint *dstX1,
17794a49301eSmrg                  GLint maxValue)
17804a49301eSmrg{
17814a49301eSmrg   GLfloat t, bias;
17824a49301eSmrg
17834a49301eSmrg   if (*dstX1 > maxValue) {
17844a49301eSmrg      /* X1 outside right edge */
17854a49301eSmrg      ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */
17864a49301eSmrg      t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
17874a49301eSmrg      /* chop off [t, 1] part */
17884a49301eSmrg      ASSERT(t >= 0.0 && t <= 1.0);
17894a49301eSmrg      *dstX1 = maxValue;
1790cdc920a0Smrg      bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
17914a49301eSmrg      *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
17924a49301eSmrg   }
17934a49301eSmrg   else if (*dstX0 > maxValue) {
17944a49301eSmrg      /* X0 outside right edge */
17954a49301eSmrg      ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */
17964a49301eSmrg      t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
17974a49301eSmrg      /* chop off [t, 1] part */
17984a49301eSmrg      ASSERT(t >= 0.0 && t <= 1.0);
17994a49301eSmrg      *dstX0 = maxValue;
1800cdc920a0Smrg      bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
18014a49301eSmrg      *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
18024a49301eSmrg   }
18034a49301eSmrg}
18044a49301eSmrg
18054a49301eSmrg
18064a49301eSmrg/**
18074a49301eSmrg * Clip dst coords against Xmin (or Ymin).
18084a49301eSmrg */
18094a49301eSmrgstatic INLINE void
18104a49301eSmrgclip_left_or_bottom(GLint *srcX0, GLint *srcX1,
18114a49301eSmrg                    GLint *dstX0, GLint *dstX1,
18124a49301eSmrg                    GLint minValue)
18134a49301eSmrg{
18144a49301eSmrg   GLfloat t, bias;
18154a49301eSmrg
18164a49301eSmrg   if (*dstX0 < minValue) {
18174a49301eSmrg      /* X0 outside left edge */
18184a49301eSmrg      ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */
18194a49301eSmrg      t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
18204a49301eSmrg      /* chop off [0, t] part */
18214a49301eSmrg      ASSERT(t >= 0.0 && t <= 1.0);
18224a49301eSmrg      *dstX0 = minValue;
1823cdc920a0Smrg      bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; /* flipped??? */
18244a49301eSmrg      *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
18254a49301eSmrg   }
18264a49301eSmrg   else if (*dstX1 < minValue) {
18274a49301eSmrg      /* X1 outside left edge */
18284a49301eSmrg      ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */
18294a49301eSmrg      t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
18304a49301eSmrg      /* chop off [0, t] part */
18314a49301eSmrg      ASSERT(t >= 0.0 && t <= 1.0);
18324a49301eSmrg      *dstX1 = minValue;
1833cdc920a0Smrg      bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
18344a49301eSmrg      *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
18354a49301eSmrg   }
18364a49301eSmrg}
18374a49301eSmrg
18384a49301eSmrg
18394a49301eSmrg/**
18404a49301eSmrg * Do clipping of blit src/dest rectangles.
18414a49301eSmrg * The dest rect is clipped against both the buffer bounds and scissor bounds.
18424a49301eSmrg * The src rect is just clipped against the buffer bounds.
18434a49301eSmrg *
18444a49301eSmrg * When either the src or dest rect is clipped, the other is also clipped
18454a49301eSmrg * proportionately!
18464a49301eSmrg *
18474a49301eSmrg * Note that X0 need not be less than X1 (same for Y) for either the source
18484a49301eSmrg * and dest rects.  That makes the clipping a little trickier.
18494a49301eSmrg *
18504a49301eSmrg * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
18514a49301eSmrg */
18524a49301eSmrgGLboolean
18533464ebd5Sriastradh_mesa_clip_blit(struct gl_context *ctx,
18544a49301eSmrg                GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
18554a49301eSmrg                GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
18564a49301eSmrg{
18574a49301eSmrg   const GLint srcXmin = 0;
18584a49301eSmrg   const GLint srcXmax = ctx->ReadBuffer->Width;
18594a49301eSmrg   const GLint srcYmin = 0;
18604a49301eSmrg   const GLint srcYmax = ctx->ReadBuffer->Height;
18614a49301eSmrg
18624a49301eSmrg   /* these include scissor bounds */
18634a49301eSmrg   const GLint dstXmin = ctx->DrawBuffer->_Xmin;
18644a49301eSmrg   const GLint dstXmax = ctx->DrawBuffer->_Xmax;
18654a49301eSmrg   const GLint dstYmin = ctx->DrawBuffer->_Ymin;
18664a49301eSmrg   const GLint dstYmax = ctx->DrawBuffer->_Ymax;
18674a49301eSmrg
18684a49301eSmrg   /*
18694a49301eSmrg   printf("PreClipX:  src: %d .. %d  dst: %d .. %d\n",
18704a49301eSmrg          *srcX0, *srcX1, *dstX0, *dstX1);
18714a49301eSmrg   printf("PreClipY:  src: %d .. %d  dst: %d .. %d\n",
18724a49301eSmrg          *srcY0, *srcY1, *dstY0, *dstY1);
18734a49301eSmrg   */
18744a49301eSmrg
18754a49301eSmrg   /* trivial rejection tests */
18764a49301eSmrg   if (*dstX0 == *dstX1)
18774a49301eSmrg      return GL_FALSE; /* no width */
18784a49301eSmrg   if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
18794a49301eSmrg      return GL_FALSE; /* totally out (left) of bounds */
18804a49301eSmrg   if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
18814a49301eSmrg      return GL_FALSE; /* totally out (right) of bounds */
18824a49301eSmrg
18834a49301eSmrg   if (*dstY0 == *dstY1)
18844a49301eSmrg      return GL_FALSE;
18854a49301eSmrg   if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
18864a49301eSmrg      return GL_FALSE;
18874a49301eSmrg   if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
18884a49301eSmrg      return GL_FALSE;
18894a49301eSmrg
18904a49301eSmrg   if (*srcX0 == *srcX1)
18914a49301eSmrg      return GL_FALSE;
18924a49301eSmrg   if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
18934a49301eSmrg      return GL_FALSE;
18944a49301eSmrg   if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
18954a49301eSmrg      return GL_FALSE;
18964a49301eSmrg
18974a49301eSmrg   if (*srcY0 == *srcY1)
18984a49301eSmrg      return GL_FALSE;
18994a49301eSmrg   if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
19004a49301eSmrg      return GL_FALSE;
19014a49301eSmrg   if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
19024a49301eSmrg      return GL_FALSE;
19034a49301eSmrg
19044a49301eSmrg   /*
19054a49301eSmrg    * dest clip
19064a49301eSmrg    */
19074a49301eSmrg   clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
19084a49301eSmrg   clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
19094a49301eSmrg   clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
19104a49301eSmrg   clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
19114a49301eSmrg
19124a49301eSmrg   /*
19134a49301eSmrg    * src clip (just swap src/dst values from above)
19144a49301eSmrg    */
19154a49301eSmrg   clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
19164a49301eSmrg   clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
19174a49301eSmrg   clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
19184a49301eSmrg   clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
19194a49301eSmrg
19204a49301eSmrg   /*
19214a49301eSmrg   printf("PostClipX: src: %d .. %d  dst: %d .. %d\n",
19224a49301eSmrg          *srcX0, *srcX1, *dstX0, *dstX1);
19234a49301eSmrg   printf("PostClipY: src: %d .. %d  dst: %d .. %d\n",
19244a49301eSmrg          *srcY0, *srcY1, *dstY0, *dstY1);
19254a49301eSmrg   */
19264a49301eSmrg
19274a49301eSmrg   ASSERT(*dstX0 >= dstXmin);
19284a49301eSmrg   ASSERT(*dstX0 <= dstXmax);
19294a49301eSmrg   ASSERT(*dstX1 >= dstXmin);
19304a49301eSmrg   ASSERT(*dstX1 <= dstXmax);
19314a49301eSmrg
19324a49301eSmrg   ASSERT(*dstY0 >= dstYmin);
19334a49301eSmrg   ASSERT(*dstY0 <= dstYmax);
19344a49301eSmrg   ASSERT(*dstY1 >= dstYmin);
19354a49301eSmrg   ASSERT(*dstY1 <= dstYmax);
19364a49301eSmrg
19374a49301eSmrg   ASSERT(*srcX0 >= srcXmin);
19384a49301eSmrg   ASSERT(*srcX0 <= srcXmax);
19394a49301eSmrg   ASSERT(*srcX1 >= srcXmin);
19404a49301eSmrg   ASSERT(*srcX1 <= srcXmax);
19414a49301eSmrg
19424a49301eSmrg   ASSERT(*srcY0 >= srcYmin);
19434a49301eSmrg   ASSERT(*srcY0 <= srcYmax);
19444a49301eSmrg   ASSERT(*srcY1 >= srcYmin);
19454a49301eSmrg   ASSERT(*srcY1 <= srcYmax);
19464a49301eSmrg
19474a49301eSmrg   return GL_TRUE;
19484a49301eSmrg}
1949