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