teximage.c revision 7117f1b4
17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * Version: 7.0.3 47117f1b4Smrg * 57117f1b4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 67117f1b4Smrg * 77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 97117f1b4Smrg * to deal in the Software without restriction, including without limitation 107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 127117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 137117f1b4Smrg * 147117f1b4Smrg * The above copyright notice and this permission notice shall be included 157117f1b4Smrg * in all copies or substantial portions of the Software. 167117f1b4Smrg * 177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 207117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 217117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 227117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg */ 247117f1b4Smrg 257117f1b4Smrg 267117f1b4Smrg/** 277117f1b4Smrg * \file teximage.c 287117f1b4Smrg * Texture image-related functions. 297117f1b4Smrg */ 307117f1b4Smrg 317117f1b4Smrg 327117f1b4Smrg#include "glheader.h" 337117f1b4Smrg#include "bufferobj.h" 347117f1b4Smrg#include "context.h" 357117f1b4Smrg#include "convolve.h" 367117f1b4Smrg#include "fbobject.h" 377117f1b4Smrg#include "framebuffer.h" 387117f1b4Smrg#include "image.h" 397117f1b4Smrg#include "imports.h" 407117f1b4Smrg#include "macros.h" 417117f1b4Smrg#include "state.h" 427117f1b4Smrg#include "texcompress.h" 437117f1b4Smrg#include "texformat.h" 447117f1b4Smrg#include "teximage.h" 457117f1b4Smrg#include "texstate.h" 467117f1b4Smrg#include "texstore.h" 477117f1b4Smrg#include "mtypes.h" 487117f1b4Smrg 497117f1b4Smrg 507117f1b4Smrg/** 517117f1b4Smrg * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE 527117f1b4Smrg * elsewhere. 537117f1b4Smrg */ 547117f1b4Smrgvoid * 557117f1b4Smrg_mesa_alloc_texmemory(GLsizei bytes) 567117f1b4Smrg{ 577117f1b4Smrg return _mesa_align_malloc(bytes, 512); 587117f1b4Smrg} 597117f1b4Smrg 607117f1b4Smrg 617117f1b4Smrg/** 627117f1b4Smrg * Free texture memory allocated with _mesa_alloc_texmemory() 637117f1b4Smrg */ 647117f1b4Smrgvoid 657117f1b4Smrg_mesa_free_texmemory(void *m) 667117f1b4Smrg{ 677117f1b4Smrg _mesa_align_free(m); 687117f1b4Smrg} 697117f1b4Smrg 707117f1b4Smrg 717117f1b4Smrg 727117f1b4Smrg 737117f1b4Smrg#if 0 747117f1b4Smrgstatic void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) 757117f1b4Smrg{ 767117f1b4Smrg#if CHAN_TYPE != GL_UNSIGNED_BYTE 777117f1b4Smrg _mesa_problem(NULL, "PrintTexture not supported"); 787117f1b4Smrg#else 797117f1b4Smrg GLuint i, j, c; 807117f1b4Smrg const GLubyte *data = (const GLubyte *) img->Data; 817117f1b4Smrg 827117f1b4Smrg if (!data) { 837117f1b4Smrg _mesa_printf("No texture data\n"); 847117f1b4Smrg return; 857117f1b4Smrg } 867117f1b4Smrg 877117f1b4Smrg switch (img->Format) { 887117f1b4Smrg case GL_ALPHA: 897117f1b4Smrg case GL_LUMINANCE: 907117f1b4Smrg case GL_INTENSITY: 917117f1b4Smrg case GL_COLOR_INDEX: 927117f1b4Smrg c = 1; 937117f1b4Smrg break; 947117f1b4Smrg case GL_LUMINANCE_ALPHA: 957117f1b4Smrg c = 2; 967117f1b4Smrg break; 977117f1b4Smrg case GL_RGB: 987117f1b4Smrg c = 3; 997117f1b4Smrg break; 1007117f1b4Smrg case GL_RGBA: 1017117f1b4Smrg c = 4; 1027117f1b4Smrg break; 1037117f1b4Smrg default: 1047117f1b4Smrg _mesa_problem(NULL, "error in PrintTexture\n"); 1057117f1b4Smrg return; 1067117f1b4Smrg } 1077117f1b4Smrg 1087117f1b4Smrg for (i = 0; i < img->Height; i++) { 1097117f1b4Smrg for (j = 0; j < img->Width; j++) { 1107117f1b4Smrg if (c==1) 1117117f1b4Smrg _mesa_printf("%02x ", data[0]); 1127117f1b4Smrg else if (c==2) 1137117f1b4Smrg _mesa_printf("%02x%02x ", data[0], data[1]); 1147117f1b4Smrg else if (c==3) 1157117f1b4Smrg _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]); 1167117f1b4Smrg else if (c==4) 1177117f1b4Smrg _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 1187117f1b4Smrg data += (img->RowStride - img->Width) * c; 1197117f1b4Smrg } 1207117f1b4Smrg /* XXX use img->ImageStride here */ 1217117f1b4Smrg _mesa_printf("\n"); 1227117f1b4Smrg } 1237117f1b4Smrg#endif 1247117f1b4Smrg} 1257117f1b4Smrg#endif 1267117f1b4Smrg 1277117f1b4Smrg 1287117f1b4Smrg/* 1297117f1b4Smrg * Compute floor(log_base_2(n)). 1307117f1b4Smrg * If n < 0 return -1. 1317117f1b4Smrg */ 1327117f1b4Smrgstatic int 1337117f1b4Smrglogbase2( int n ) 1347117f1b4Smrg{ 1357117f1b4Smrg GLint i = 1; 1367117f1b4Smrg GLint log2 = 0; 1377117f1b4Smrg 1387117f1b4Smrg if (n < 0) 1397117f1b4Smrg return -1; 1407117f1b4Smrg 1417117f1b4Smrg if (n == 0) 1427117f1b4Smrg return 0; 1437117f1b4Smrg 1447117f1b4Smrg while ( n > i ) { 1457117f1b4Smrg i *= 2; 1467117f1b4Smrg log2++; 1477117f1b4Smrg } 1487117f1b4Smrg if (i != n) { 1497117f1b4Smrg return log2 - 1; 1507117f1b4Smrg } 1517117f1b4Smrg else { 1527117f1b4Smrg return log2; 1537117f1b4Smrg } 1547117f1b4Smrg} 1557117f1b4Smrg 1567117f1b4Smrg 1577117f1b4Smrg 1587117f1b4Smrg/** 1597117f1b4Smrg * Return the simple base format for a given internal texture format. 1607117f1b4Smrg * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. 1617117f1b4Smrg * 1627117f1b4Smrg * \param ctx GL context. 1637117f1b4Smrg * \param internalFormat the internal texture format token or 1, 2, 3, or 4. 1647117f1b4Smrg * 1657117f1b4Smrg * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, 1667117f1b4Smrg * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. 1677117f1b4Smrg * 1687117f1b4Smrg * This is the format which is used during texture application (i.e. the 1697117f1b4Smrg * texture format and env mode determine the arithmetic used. 1707117f1b4Smrg */ 1717117f1b4SmrgGLint 1727117f1b4Smrg_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) 1737117f1b4Smrg{ 1747117f1b4Smrg switch (internalFormat) { 1757117f1b4Smrg case GL_ALPHA: 1767117f1b4Smrg case GL_ALPHA4: 1777117f1b4Smrg case GL_ALPHA8: 1787117f1b4Smrg case GL_ALPHA12: 1797117f1b4Smrg case GL_ALPHA16: 1807117f1b4Smrg return GL_ALPHA; 1817117f1b4Smrg case 1: 1827117f1b4Smrg case GL_LUMINANCE: 1837117f1b4Smrg case GL_LUMINANCE4: 1847117f1b4Smrg case GL_LUMINANCE8: 1857117f1b4Smrg case GL_LUMINANCE12: 1867117f1b4Smrg case GL_LUMINANCE16: 1877117f1b4Smrg return GL_LUMINANCE; 1887117f1b4Smrg case 2: 1897117f1b4Smrg case GL_LUMINANCE_ALPHA: 1907117f1b4Smrg case GL_LUMINANCE4_ALPHA4: 1917117f1b4Smrg case GL_LUMINANCE6_ALPHA2: 1927117f1b4Smrg case GL_LUMINANCE8_ALPHA8: 1937117f1b4Smrg case GL_LUMINANCE12_ALPHA4: 1947117f1b4Smrg case GL_LUMINANCE12_ALPHA12: 1957117f1b4Smrg case GL_LUMINANCE16_ALPHA16: 1967117f1b4Smrg return GL_LUMINANCE_ALPHA; 1977117f1b4Smrg case GL_INTENSITY: 1987117f1b4Smrg case GL_INTENSITY4: 1997117f1b4Smrg case GL_INTENSITY8: 2007117f1b4Smrg case GL_INTENSITY12: 2017117f1b4Smrg case GL_INTENSITY16: 2027117f1b4Smrg return GL_INTENSITY; 2037117f1b4Smrg case 3: 2047117f1b4Smrg case GL_RGB: 2057117f1b4Smrg case GL_R3_G3_B2: 2067117f1b4Smrg case GL_RGB4: 2077117f1b4Smrg case GL_RGB5: 2087117f1b4Smrg case GL_RGB8: 2097117f1b4Smrg case GL_RGB10: 2107117f1b4Smrg case GL_RGB12: 2117117f1b4Smrg case GL_RGB16: 2127117f1b4Smrg return GL_RGB; 2137117f1b4Smrg case 4: 2147117f1b4Smrg case GL_RGBA: 2157117f1b4Smrg case GL_RGBA2: 2167117f1b4Smrg case GL_RGBA4: 2177117f1b4Smrg case GL_RGB5_A1: 2187117f1b4Smrg case GL_RGBA8: 2197117f1b4Smrg case GL_RGB10_A2: 2207117f1b4Smrg case GL_RGBA12: 2217117f1b4Smrg case GL_RGBA16: 2227117f1b4Smrg return GL_RGBA; 2237117f1b4Smrg default: 2247117f1b4Smrg ; /* fallthrough */ 2257117f1b4Smrg } 2267117f1b4Smrg 2277117f1b4Smrg if (ctx->Extensions.EXT_paletted_texture) { 2287117f1b4Smrg switch (internalFormat) { 2297117f1b4Smrg case GL_COLOR_INDEX: 2307117f1b4Smrg case GL_COLOR_INDEX1_EXT: 2317117f1b4Smrg case GL_COLOR_INDEX2_EXT: 2327117f1b4Smrg case GL_COLOR_INDEX4_EXT: 2337117f1b4Smrg case GL_COLOR_INDEX8_EXT: 2347117f1b4Smrg case GL_COLOR_INDEX12_EXT: 2357117f1b4Smrg case GL_COLOR_INDEX16_EXT: 2367117f1b4Smrg return GL_COLOR_INDEX; 2377117f1b4Smrg default: 2387117f1b4Smrg ; /* fallthrough */ 2397117f1b4Smrg } 2407117f1b4Smrg } 2417117f1b4Smrg 2427117f1b4Smrg if (ctx->Extensions.SGIX_depth_texture || 2437117f1b4Smrg ctx->Extensions.ARB_depth_texture) { 2447117f1b4Smrg switch (internalFormat) { 2457117f1b4Smrg case GL_DEPTH_COMPONENT: 2467117f1b4Smrg case GL_DEPTH_COMPONENT16_SGIX: 2477117f1b4Smrg case GL_DEPTH_COMPONENT24_SGIX: 2487117f1b4Smrg case GL_DEPTH_COMPONENT32_SGIX: 2497117f1b4Smrg return GL_DEPTH_COMPONENT; 2507117f1b4Smrg default: 2517117f1b4Smrg ; /* fallthrough */ 2527117f1b4Smrg } 2537117f1b4Smrg } 2547117f1b4Smrg 2557117f1b4Smrg if (ctx->Extensions.ARB_texture_compression) { 2567117f1b4Smrg switch (internalFormat) { 2577117f1b4Smrg case GL_COMPRESSED_ALPHA: 2587117f1b4Smrg return GL_ALPHA; 2597117f1b4Smrg case GL_COMPRESSED_LUMINANCE: 2607117f1b4Smrg return GL_LUMINANCE; 2617117f1b4Smrg case GL_COMPRESSED_LUMINANCE_ALPHA: 2627117f1b4Smrg return GL_LUMINANCE_ALPHA; 2637117f1b4Smrg case GL_COMPRESSED_INTENSITY: 2647117f1b4Smrg return GL_INTENSITY; 2657117f1b4Smrg case GL_COMPRESSED_RGB: 2667117f1b4Smrg return GL_RGB; 2677117f1b4Smrg case GL_COMPRESSED_RGBA: 2687117f1b4Smrg return GL_RGBA; 2697117f1b4Smrg default: 2707117f1b4Smrg ; /* fallthrough */ 2717117f1b4Smrg } 2727117f1b4Smrg } 2737117f1b4Smrg 2747117f1b4Smrg if (ctx->Extensions.TDFX_texture_compression_FXT1) { 2757117f1b4Smrg switch (internalFormat) { 2767117f1b4Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 2777117f1b4Smrg return GL_RGB; 2787117f1b4Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 2797117f1b4Smrg return GL_RGBA; 2807117f1b4Smrg default: 2817117f1b4Smrg ; /* fallthrough */ 2827117f1b4Smrg } 2837117f1b4Smrg } 2847117f1b4Smrg 2857117f1b4Smrg if (ctx->Extensions.EXT_texture_compression_s3tc) { 2867117f1b4Smrg switch (internalFormat) { 2877117f1b4Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 2887117f1b4Smrg return GL_RGB; 2897117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 2907117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 2917117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 2927117f1b4Smrg return GL_RGBA; 2937117f1b4Smrg default: 2947117f1b4Smrg ; /* fallthrough */ 2957117f1b4Smrg } 2967117f1b4Smrg } 2977117f1b4Smrg 2987117f1b4Smrg if (ctx->Extensions.S3_s3tc) { 2997117f1b4Smrg switch (internalFormat) { 3007117f1b4Smrg case GL_RGB_S3TC: 3017117f1b4Smrg case GL_RGB4_S3TC: 3027117f1b4Smrg return GL_RGB; 3037117f1b4Smrg case GL_RGBA_S3TC: 3047117f1b4Smrg case GL_RGBA4_S3TC: 3057117f1b4Smrg return GL_RGBA; 3067117f1b4Smrg default: 3077117f1b4Smrg ; /* fallthrough */ 3087117f1b4Smrg } 3097117f1b4Smrg } 3107117f1b4Smrg 3117117f1b4Smrg if (ctx->Extensions.MESA_ycbcr_texture) { 3127117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) 3137117f1b4Smrg return GL_YCBCR_MESA; 3147117f1b4Smrg } 3157117f1b4Smrg 3167117f1b4Smrg if (ctx->Extensions.ARB_texture_float) { 3177117f1b4Smrg switch (internalFormat) { 3187117f1b4Smrg case GL_ALPHA16F_ARB: 3197117f1b4Smrg case GL_ALPHA32F_ARB: 3207117f1b4Smrg return GL_ALPHA; 3217117f1b4Smrg case GL_RGBA16F_ARB: 3227117f1b4Smrg case GL_RGBA32F_ARB: 3237117f1b4Smrg return GL_RGBA; 3247117f1b4Smrg case GL_RGB16F_ARB: 3257117f1b4Smrg case GL_RGB32F_ARB: 3267117f1b4Smrg return GL_RGB; 3277117f1b4Smrg case GL_INTENSITY16F_ARB: 3287117f1b4Smrg case GL_INTENSITY32F_ARB: 3297117f1b4Smrg return GL_INTENSITY; 3307117f1b4Smrg case GL_LUMINANCE16F_ARB: 3317117f1b4Smrg case GL_LUMINANCE32F_ARB: 3327117f1b4Smrg return GL_LUMINANCE; 3337117f1b4Smrg case GL_LUMINANCE_ALPHA16F_ARB: 3347117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 3357117f1b4Smrg return GL_LUMINANCE_ALPHA; 3367117f1b4Smrg default: 3377117f1b4Smrg ; /* fallthrough */ 3387117f1b4Smrg } 3397117f1b4Smrg } 3407117f1b4Smrg 3417117f1b4Smrg if (ctx->Extensions.EXT_packed_depth_stencil) { 3427117f1b4Smrg switch (internalFormat) { 3437117f1b4Smrg case GL_DEPTH_STENCIL_EXT: 3447117f1b4Smrg case GL_DEPTH24_STENCIL8_EXT: 3457117f1b4Smrg return GL_DEPTH_STENCIL_EXT; 3467117f1b4Smrg default: 3477117f1b4Smrg ; /* fallthrough */ 3487117f1b4Smrg } 3497117f1b4Smrg } 3507117f1b4Smrg 3517117f1b4Smrg#if FEATURE_EXT_texture_sRGB 3527117f1b4Smrg if (ctx->Extensions.EXT_texture_sRGB) { 3537117f1b4Smrg switch (internalFormat) { 3547117f1b4Smrg case GL_SRGB_EXT: 3557117f1b4Smrg case GL_SRGB8_EXT: 3567117f1b4Smrg case GL_COMPRESSED_SRGB_EXT: 3577117f1b4Smrg case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 3587117f1b4Smrg return GL_RGB; 3597117f1b4Smrg case GL_SRGB_ALPHA_EXT: 3607117f1b4Smrg case GL_SRGB8_ALPHA8_EXT: 3617117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_EXT: 3627117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 3637117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 3647117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 3657117f1b4Smrg return GL_RGBA; 3667117f1b4Smrg case GL_SLUMINANCE_ALPHA_EXT: 3677117f1b4Smrg case GL_SLUMINANCE8_ALPHA8_EXT: 3687117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_EXT: 3697117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 3707117f1b4Smrg return GL_LUMINANCE_ALPHA; 3717117f1b4Smrg case GL_SLUMINANCE_EXT: 3727117f1b4Smrg case GL_SLUMINANCE8_EXT: 3737117f1b4Smrg return GL_LUMINANCE; 3747117f1b4Smrg default: 3757117f1b4Smrg ; /* fallthrough */ 3767117f1b4Smrg } 3777117f1b4Smrg } 3787117f1b4Smrg 3797117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */ 3807117f1b4Smrg 3817117f1b4Smrg return -1; /* error */ 3827117f1b4Smrg} 3837117f1b4Smrg 3847117f1b4Smrg 3857117f1b4Smrg/** 3867117f1b4Smrg * Test if the given image format is a color/RGBA format (i.e., not color 3877117f1b4Smrg * index, depth, stencil, etc). 3887117f1b4Smrg * \param format the image format value (may by an internal texture format) 3897117f1b4Smrg * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. 3907117f1b4Smrg */ 3917117f1b4Smrgstatic GLboolean 3927117f1b4Smrgis_color_format(GLenum format) 3937117f1b4Smrg{ 3947117f1b4Smrg switch (format) { 3957117f1b4Smrg case GL_RED: 3967117f1b4Smrg case GL_GREEN: 3977117f1b4Smrg case GL_BLUE: 3987117f1b4Smrg case GL_ALPHA: 3997117f1b4Smrg case GL_ALPHA4: 4007117f1b4Smrg case GL_ALPHA8: 4017117f1b4Smrg case GL_ALPHA12: 4027117f1b4Smrg case GL_ALPHA16: 4037117f1b4Smrg case 1: 4047117f1b4Smrg case GL_LUMINANCE: 4057117f1b4Smrg case GL_LUMINANCE4: 4067117f1b4Smrg case GL_LUMINANCE8: 4077117f1b4Smrg case GL_LUMINANCE12: 4087117f1b4Smrg case GL_LUMINANCE16: 4097117f1b4Smrg case 2: 4107117f1b4Smrg case GL_LUMINANCE_ALPHA: 4117117f1b4Smrg case GL_LUMINANCE4_ALPHA4: 4127117f1b4Smrg case GL_LUMINANCE6_ALPHA2: 4137117f1b4Smrg case GL_LUMINANCE8_ALPHA8: 4147117f1b4Smrg case GL_LUMINANCE12_ALPHA4: 4157117f1b4Smrg case GL_LUMINANCE12_ALPHA12: 4167117f1b4Smrg case GL_LUMINANCE16_ALPHA16: 4177117f1b4Smrg case GL_INTENSITY: 4187117f1b4Smrg case GL_INTENSITY4: 4197117f1b4Smrg case GL_INTENSITY8: 4207117f1b4Smrg case GL_INTENSITY12: 4217117f1b4Smrg case GL_INTENSITY16: 4227117f1b4Smrg case 3: 4237117f1b4Smrg case GL_RGB: 4247117f1b4Smrg case GL_BGR: 4257117f1b4Smrg case GL_R3_G3_B2: 4267117f1b4Smrg case GL_RGB4: 4277117f1b4Smrg case GL_RGB5: 4287117f1b4Smrg case GL_RGB8: 4297117f1b4Smrg case GL_RGB10: 4307117f1b4Smrg case GL_RGB12: 4317117f1b4Smrg case GL_RGB16: 4327117f1b4Smrg case 4: 4337117f1b4Smrg case GL_ABGR_EXT: 4347117f1b4Smrg case GL_RGBA: 4357117f1b4Smrg case GL_BGRA: 4367117f1b4Smrg case GL_RGBA2: 4377117f1b4Smrg case GL_RGBA4: 4387117f1b4Smrg case GL_RGB5_A1: 4397117f1b4Smrg case GL_RGBA8: 4407117f1b4Smrg case GL_RGB10_A2: 4417117f1b4Smrg case GL_RGBA12: 4427117f1b4Smrg case GL_RGBA16: 4437117f1b4Smrg /* float texture formats */ 4447117f1b4Smrg case GL_ALPHA16F_ARB: 4457117f1b4Smrg case GL_ALPHA32F_ARB: 4467117f1b4Smrg case GL_LUMINANCE16F_ARB: 4477117f1b4Smrg case GL_LUMINANCE32F_ARB: 4487117f1b4Smrg case GL_LUMINANCE_ALPHA16F_ARB: 4497117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 4507117f1b4Smrg case GL_INTENSITY16F_ARB: 4517117f1b4Smrg case GL_INTENSITY32F_ARB: 4527117f1b4Smrg case GL_RGB16F_ARB: 4537117f1b4Smrg case GL_RGB32F_ARB: 4547117f1b4Smrg case GL_RGBA16F_ARB: 4557117f1b4Smrg case GL_RGBA32F_ARB: 4567117f1b4Smrg /* compressed formats */ 4577117f1b4Smrg case GL_COMPRESSED_ALPHA: 4587117f1b4Smrg case GL_COMPRESSED_LUMINANCE: 4597117f1b4Smrg case GL_COMPRESSED_LUMINANCE_ALPHA: 4607117f1b4Smrg case GL_COMPRESSED_INTENSITY: 4617117f1b4Smrg case GL_COMPRESSED_RGB: 4627117f1b4Smrg case GL_COMPRESSED_RGBA: 4637117f1b4Smrg case GL_RGB_S3TC: 4647117f1b4Smrg case GL_RGB4_S3TC: 4657117f1b4Smrg case GL_RGBA_S3TC: 4667117f1b4Smrg case GL_RGBA4_S3TC: 4677117f1b4Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 4687117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 4697117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 4707117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 4717117f1b4Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 4727117f1b4Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 4737117f1b4Smrg#if FEATURE_EXT_texture_sRGB 4747117f1b4Smrg case GL_SRGB_EXT: 4757117f1b4Smrg case GL_SRGB8_EXT: 4767117f1b4Smrg case GL_SRGB_ALPHA_EXT: 4777117f1b4Smrg case GL_SRGB8_ALPHA8_EXT: 4787117f1b4Smrg case GL_SLUMINANCE_ALPHA_EXT: 4797117f1b4Smrg case GL_SLUMINANCE8_ALPHA8_EXT: 4807117f1b4Smrg case GL_SLUMINANCE_EXT: 4817117f1b4Smrg case GL_SLUMINANCE8_EXT: 4827117f1b4Smrg case GL_COMPRESSED_SRGB_EXT: 4837117f1b4Smrg case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 4847117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_EXT: 4857117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 4867117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 4877117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 4887117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_EXT: 4897117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 4907117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */ 4917117f1b4Smrg return GL_TRUE; 4927117f1b4Smrg case GL_YCBCR_MESA: /* not considered to be RGB */ 4937117f1b4Smrg default: 4947117f1b4Smrg return GL_FALSE; 4957117f1b4Smrg } 4967117f1b4Smrg} 4977117f1b4Smrg 4987117f1b4Smrg 4997117f1b4Smrg/** 5007117f1b4Smrg * Test if the given image format is a color index format. 5017117f1b4Smrg */ 5027117f1b4Smrgstatic GLboolean 5037117f1b4Smrgis_index_format(GLenum format) 5047117f1b4Smrg{ 5057117f1b4Smrg switch (format) { 5067117f1b4Smrg case GL_COLOR_INDEX: 5077117f1b4Smrg case GL_COLOR_INDEX1_EXT: 5087117f1b4Smrg case GL_COLOR_INDEX2_EXT: 5097117f1b4Smrg case GL_COLOR_INDEX4_EXT: 5107117f1b4Smrg case GL_COLOR_INDEX8_EXT: 5117117f1b4Smrg case GL_COLOR_INDEX12_EXT: 5127117f1b4Smrg case GL_COLOR_INDEX16_EXT: 5137117f1b4Smrg return GL_TRUE; 5147117f1b4Smrg default: 5157117f1b4Smrg return GL_FALSE; 5167117f1b4Smrg } 5177117f1b4Smrg} 5187117f1b4Smrg 5197117f1b4Smrg 5207117f1b4Smrg/** 5217117f1b4Smrg * Test if the given image format is a depth component format. 5227117f1b4Smrg */ 5237117f1b4Smrgstatic GLboolean 5247117f1b4Smrgis_depth_format(GLenum format) 5257117f1b4Smrg{ 5267117f1b4Smrg switch (format) { 5277117f1b4Smrg case GL_DEPTH_COMPONENT16_ARB: 5287117f1b4Smrg case GL_DEPTH_COMPONENT24_ARB: 5297117f1b4Smrg case GL_DEPTH_COMPONENT32_ARB: 5307117f1b4Smrg case GL_DEPTH_COMPONENT: 5317117f1b4Smrg return GL_TRUE; 5327117f1b4Smrg default: 5337117f1b4Smrg return GL_FALSE; 5347117f1b4Smrg } 5357117f1b4Smrg} 5367117f1b4Smrg 5377117f1b4Smrg 5387117f1b4Smrg/** 5397117f1b4Smrg * Test if the given image format is a YCbCr format. 5407117f1b4Smrg */ 5417117f1b4Smrgstatic GLboolean 5427117f1b4Smrgis_ycbcr_format(GLenum format) 5437117f1b4Smrg{ 5447117f1b4Smrg switch (format) { 5457117f1b4Smrg case GL_YCBCR_MESA: 5467117f1b4Smrg return GL_TRUE; 5477117f1b4Smrg default: 5487117f1b4Smrg return GL_FALSE; 5497117f1b4Smrg } 5507117f1b4Smrg} 5517117f1b4Smrg 5527117f1b4Smrg 5537117f1b4Smrg/** 5547117f1b4Smrg * Test if the given image format is a Depth/Stencil format. 5557117f1b4Smrg */ 5567117f1b4Smrgstatic GLboolean 5577117f1b4Smrgis_depthstencil_format(GLenum format) 5587117f1b4Smrg{ 5597117f1b4Smrg switch (format) { 5607117f1b4Smrg case GL_DEPTH24_STENCIL8_EXT: 5617117f1b4Smrg case GL_DEPTH_STENCIL_EXT: 5627117f1b4Smrg return GL_TRUE; 5637117f1b4Smrg default: 5647117f1b4Smrg return GL_FALSE; 5657117f1b4Smrg } 5667117f1b4Smrg} 5677117f1b4Smrg 5687117f1b4Smrg 5697117f1b4Smrg 5707117f1b4Smrg/** 5717117f1b4Smrg * Test if it is a supported compressed format. 5727117f1b4Smrg * 5737117f1b4Smrg * \param internalFormat the internal format token provided by the user. 5747117f1b4Smrg * 5757117f1b4Smrg * \ret GL_TRUE if \p internalFormat is a supported compressed format, or 5767117f1b4Smrg * GL_FALSE otherwise. 5777117f1b4Smrg * 5787117f1b4Smrg * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX 5797117f1b4Smrg * are supported. 5807117f1b4Smrg */ 5817117f1b4Smrgstatic GLboolean 5827117f1b4Smrgis_compressed_format(GLcontext *ctx, GLenum internalFormat) 5837117f1b4Smrg{ 5847117f1b4Smrg GLint supported[100]; /* 100 should be plenty */ 5857117f1b4Smrg GLuint i, n; 5867117f1b4Smrg 5877117f1b4Smrg n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE); 5887117f1b4Smrg ASSERT(n < 100); 5897117f1b4Smrg for (i = 0; i < n; i++) { 5907117f1b4Smrg if ((GLint) internalFormat == supported[i]) { 5917117f1b4Smrg return GL_TRUE; 5927117f1b4Smrg } 5937117f1b4Smrg } 5947117f1b4Smrg return GL_FALSE; 5957117f1b4Smrg} 5967117f1b4Smrg 5977117f1b4Smrg 5987117f1b4Smrgstatic GLuint 5997117f1b4Smrgtexture_face(GLenum target) 6007117f1b4Smrg{ 6017117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 6027117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 6037117f1b4Smrg return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 6047117f1b4Smrg else 6057117f1b4Smrg return 0; 6067117f1b4Smrg} 6077117f1b4Smrg 6087117f1b4Smrg 6097117f1b4Smrg 6107117f1b4Smrg/** 6117117f1b4Smrg * Store a gl_texture_image pointer in a gl_texture_object structure 6127117f1b4Smrg * according to the target and level parameters. 6137117f1b4Smrg * 6147117f1b4Smrg * \param tObj texture object. 6157117f1b4Smrg * \param target texture target. 6167117f1b4Smrg * \param level image level. 6177117f1b4Smrg * \param texImage texture image. 6187117f1b4Smrg * 6197117f1b4Smrg * This was basically prompted by the introduction of cube maps. 6207117f1b4Smrg */ 6217117f1b4Smrgvoid 6227117f1b4Smrg_mesa_set_tex_image(struct gl_texture_object *tObj, 6237117f1b4Smrg GLenum target, GLint level, 6247117f1b4Smrg struct gl_texture_image *texImage) 6257117f1b4Smrg{ 6267117f1b4Smrg ASSERT(tObj); 6277117f1b4Smrg ASSERT(texImage); 6287117f1b4Smrg switch (target) { 6297117f1b4Smrg case GL_TEXTURE_1D: 6307117f1b4Smrg case GL_TEXTURE_2D: 6317117f1b4Smrg case GL_TEXTURE_3D: 6327117f1b4Smrg tObj->Image[0][level] = texImage; 6337117f1b4Smrg break; 6347117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 6357117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 6367117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 6377117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 6387117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 6397117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 6407117f1b4Smrg { 6417117f1b4Smrg GLuint face = ((GLuint) target - 6427117f1b4Smrg (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); 6437117f1b4Smrg tObj->Image[face][level] = texImage; 6447117f1b4Smrg } 6457117f1b4Smrg break; 6467117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 6477117f1b4Smrg ASSERT(level == 0); 6487117f1b4Smrg tObj->Image[0][level] = texImage; 6497117f1b4Smrg break; 6507117f1b4Smrg default: 6517117f1b4Smrg _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); 6527117f1b4Smrg return; 6537117f1b4Smrg } 6547117f1b4Smrg /* Set the 'back' pointer */ 6557117f1b4Smrg texImage->TexObject = tObj; 6567117f1b4Smrg} 6577117f1b4Smrg 6587117f1b4Smrg 6597117f1b4Smrg/** 6607117f1b4Smrg * Allocate a texture image structure. 6617117f1b4Smrg * 6627117f1b4Smrg * Called via ctx->Driver.NewTextureImage() unless overriden by a device 6637117f1b4Smrg * driver. 6647117f1b4Smrg * 6657117f1b4Smrg * \return a pointer to gl_texture_image struct with all fields initialized to 6667117f1b4Smrg * zero. 6677117f1b4Smrg */ 6687117f1b4Smrgstruct gl_texture_image * 6697117f1b4Smrg_mesa_new_texture_image( GLcontext *ctx ) 6707117f1b4Smrg{ 6717117f1b4Smrg (void) ctx; 6727117f1b4Smrg return CALLOC_STRUCT(gl_texture_image); 6737117f1b4Smrg} 6747117f1b4Smrg 6757117f1b4Smrg 6767117f1b4Smrg/** 6777117f1b4Smrg * Free texture image data. 6787117f1b4Smrg * This function is a fallback called via ctx->Driver.FreeTexImageData(). 6797117f1b4Smrg * 6807117f1b4Smrg * \param teximage texture image. 6817117f1b4Smrg * 6827117f1b4Smrg * Free the texture image data if it's not marked as client data. 6837117f1b4Smrg */ 6847117f1b4Smrgvoid 6857117f1b4Smrg_mesa_free_texture_image_data(GLcontext *ctx, 6867117f1b4Smrg struct gl_texture_image *texImage) 6877117f1b4Smrg{ 6887117f1b4Smrg (void) ctx; 6897117f1b4Smrg 6907117f1b4Smrg if (texImage->Data && !texImage->IsClientData) { 6917117f1b4Smrg /* free the old texture data */ 6927117f1b4Smrg _mesa_free_texmemory(texImage->Data); 6937117f1b4Smrg } 6947117f1b4Smrg 6957117f1b4Smrg texImage->Data = NULL; 6967117f1b4Smrg} 6977117f1b4Smrg 6987117f1b4Smrg 6997117f1b4Smrg/** 7007117f1b4Smrg * Free texture image. 7017117f1b4Smrg * 7027117f1b4Smrg * \param teximage texture image. 7037117f1b4Smrg * 7047117f1b4Smrg * Free the texture image structure and the associated image data. 7057117f1b4Smrg */ 7067117f1b4Smrgvoid 7077117f1b4Smrg_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) 7087117f1b4Smrg{ 7097117f1b4Smrg /* Free texImage->Data and/or any other driver-specific texture 7107117f1b4Smrg * image storage. 7117117f1b4Smrg */ 7127117f1b4Smrg ASSERT(ctx->Driver.FreeTexImageData); 7137117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 7147117f1b4Smrg 7157117f1b4Smrg ASSERT(texImage->Data == NULL); 7167117f1b4Smrg if (texImage->ImageOffsets) 7177117f1b4Smrg _mesa_free(texImage->ImageOffsets); 7187117f1b4Smrg _mesa_free(texImage); 7197117f1b4Smrg} 7207117f1b4Smrg 7217117f1b4Smrg 7227117f1b4Smrg/** 7237117f1b4Smrg * Test if a target is a proxy target. 7247117f1b4Smrg * 7257117f1b4Smrg * \param target texture target. 7267117f1b4Smrg * 7277117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 7287117f1b4Smrg */ 7297117f1b4SmrgGLboolean 7307117f1b4Smrg_mesa_is_proxy_texture(GLenum target) 7317117f1b4Smrg{ 7327117f1b4Smrg return (target == GL_PROXY_TEXTURE_1D || 7337117f1b4Smrg target == GL_PROXY_TEXTURE_2D || 7347117f1b4Smrg target == GL_PROXY_TEXTURE_3D || 7357117f1b4Smrg target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 7367117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV); 7377117f1b4Smrg} 7387117f1b4Smrg 7397117f1b4Smrg 7407117f1b4Smrg/** 7417117f1b4Smrg * Get the texture object that corresponds to the target of the given texture unit. 7427117f1b4Smrg * 7437117f1b4Smrg * \param ctx GL context. 7447117f1b4Smrg * \param texUnit texture unit. 7457117f1b4Smrg * \param target texture target. 7467117f1b4Smrg * 7477117f1b4Smrg * \return pointer to the texture object on success, or NULL on failure. 7487117f1b4Smrg * 7497117f1b4Smrg * \sa gl_texture_unit. 7507117f1b4Smrg */ 7517117f1b4Smrgstruct gl_texture_object * 7527117f1b4Smrg_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 7537117f1b4Smrg GLenum target) 7547117f1b4Smrg{ 7557117f1b4Smrg switch (target) { 7567117f1b4Smrg case GL_TEXTURE_1D: 7577117f1b4Smrg return texUnit->Current1D; 7587117f1b4Smrg case GL_PROXY_TEXTURE_1D: 7597117f1b4Smrg return ctx->Texture.Proxy1D; 7607117f1b4Smrg case GL_TEXTURE_2D: 7617117f1b4Smrg return texUnit->Current2D; 7627117f1b4Smrg case GL_PROXY_TEXTURE_2D: 7637117f1b4Smrg return ctx->Texture.Proxy2D; 7647117f1b4Smrg case GL_TEXTURE_3D: 7657117f1b4Smrg return texUnit->Current3D; 7667117f1b4Smrg case GL_PROXY_TEXTURE_3D: 7677117f1b4Smrg return ctx->Texture.Proxy3D; 7687117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 7697117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 7707117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 7717117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 7727117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 7737117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 7747117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 7757117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 7767117f1b4Smrg ? texUnit->CurrentCubeMap : NULL; 7777117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 7787117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 7797117f1b4Smrg ? ctx->Texture.ProxyCubeMap : NULL; 7807117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 7817117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 7827117f1b4Smrg ? texUnit->CurrentRect : NULL; 7837117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 7847117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 7857117f1b4Smrg ? ctx->Texture.ProxyRect : NULL; 7867117f1b4Smrg default: 7877117f1b4Smrg _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 7887117f1b4Smrg return NULL; 7897117f1b4Smrg } 7907117f1b4Smrg} 7917117f1b4Smrg 7927117f1b4Smrg 7937117f1b4Smrg/** 7947117f1b4Smrg * Get the texture image struct which corresponds to target and level 7957117f1b4Smrg * of the given texture unit. 7967117f1b4Smrg * 7977117f1b4Smrg * \param ctx GL context. 7987117f1b4Smrg * \param texUnit texture unit. 7997117f1b4Smrg * \param target texture target. 8007117f1b4Smrg * \param level image level. 8017117f1b4Smrg * 8027117f1b4Smrg * \return pointer to the texture image structure on success, or NULL on failure. 8037117f1b4Smrg * 8047117f1b4Smrg * \sa gl_texture_unit. 8057117f1b4Smrg */ 8067117f1b4Smrgstruct gl_texture_image * 8077117f1b4Smrg_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, 8087117f1b4Smrg GLenum target, GLint level) 8097117f1b4Smrg{ 8107117f1b4Smrg ASSERT(texObj); 8117117f1b4Smrg 8127117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) 8137117f1b4Smrg return NULL; 8147117f1b4Smrg 8157117f1b4Smrg switch (target) { 8167117f1b4Smrg case GL_TEXTURE_1D: 8177117f1b4Smrg case GL_PROXY_TEXTURE_1D: 8187117f1b4Smrg case GL_TEXTURE_2D: 8197117f1b4Smrg case GL_PROXY_TEXTURE_2D: 8207117f1b4Smrg case GL_TEXTURE_3D: 8217117f1b4Smrg case GL_PROXY_TEXTURE_3D: 8227117f1b4Smrg return texObj->Image[0][level]; 8237117f1b4Smrg 8247117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 8257117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 8267117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 8277117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 8287117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 8297117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 8307117f1b4Smrg if (ctx->Extensions.ARB_texture_cube_map) { 8317117f1b4Smrg GLuint face = ((GLuint) target - 8327117f1b4Smrg (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); 8337117f1b4Smrg return texObj->Image[face][level]; 8347117f1b4Smrg } 8357117f1b4Smrg else 8367117f1b4Smrg return NULL; 8377117f1b4Smrg 8387117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 8397117f1b4Smrg if (ctx->Extensions.ARB_texture_cube_map) 8407117f1b4Smrg return texObj->Image[0][level]; 8417117f1b4Smrg else 8427117f1b4Smrg return NULL; 8437117f1b4Smrg 8447117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 8457117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 8467117f1b4Smrg if (ctx->Extensions.NV_texture_rectangle && level == 0) 8477117f1b4Smrg return texObj->Image[0][level]; 8487117f1b4Smrg else 8497117f1b4Smrg return NULL; 8507117f1b4Smrg 8517117f1b4Smrg default: 8527117f1b4Smrg return NULL; 8537117f1b4Smrg } 8547117f1b4Smrg} 8557117f1b4Smrg 8567117f1b4Smrg 8577117f1b4Smrg/** 8587117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 8597117f1b4Smrg * it and install it. Only return NULL if passed a bad parameter or run 8607117f1b4Smrg * out of memory. 8617117f1b4Smrg */ 8627117f1b4Smrgstruct gl_texture_image * 8637117f1b4Smrg_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj, 8647117f1b4Smrg GLenum target, GLint level) 8657117f1b4Smrg{ 8667117f1b4Smrg struct gl_texture_image *texImage; 8677117f1b4Smrg 8687117f1b4Smrg if (!texObj) 8697117f1b4Smrg return NULL; 8707117f1b4Smrg 8717117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 8727117f1b4Smrg if (!texImage) { 8737117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 8747117f1b4Smrg if (!texImage) { 8757117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 8767117f1b4Smrg return NULL; 8777117f1b4Smrg } 8787117f1b4Smrg 8797117f1b4Smrg _mesa_set_tex_image(texObj, target, level, texImage); 8807117f1b4Smrg } 8817117f1b4Smrg 8827117f1b4Smrg return texImage; 8837117f1b4Smrg} 8847117f1b4Smrg 8857117f1b4Smrg 8867117f1b4Smrg/** 8877117f1b4Smrg * Return pointer to the specified proxy texture image. 8887117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit. 8897117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid 8907117f1b4Smrg * level, or out of memory. 8917117f1b4Smrg */ 8927117f1b4Smrgstruct gl_texture_image * 8937117f1b4Smrg_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) 8947117f1b4Smrg{ 8957117f1b4Smrg struct gl_texture_image *texImage; 8967117f1b4Smrg 8977117f1b4Smrg if (level < 0 ) 8987117f1b4Smrg return NULL; 8997117f1b4Smrg 9007117f1b4Smrg switch (target) { 9017117f1b4Smrg case GL_PROXY_TEXTURE_1D: 9027117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 9037117f1b4Smrg return NULL; 9047117f1b4Smrg texImage = ctx->Texture.Proxy1D->Image[0][level]; 9057117f1b4Smrg if (!texImage) { 9067117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9077117f1b4Smrg if (!texImage) { 9087117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9097117f1b4Smrg return NULL; 9107117f1b4Smrg } 9117117f1b4Smrg ctx->Texture.Proxy1D->Image[0][level] = texImage; 9127117f1b4Smrg /* Set the 'back' pointer */ 9137117f1b4Smrg texImage->TexObject = ctx->Texture.Proxy1D; 9147117f1b4Smrg } 9157117f1b4Smrg return texImage; 9167117f1b4Smrg case GL_PROXY_TEXTURE_2D: 9177117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 9187117f1b4Smrg return NULL; 9197117f1b4Smrg texImage = ctx->Texture.Proxy2D->Image[0][level]; 9207117f1b4Smrg if (!texImage) { 9217117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9227117f1b4Smrg if (!texImage) { 9237117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9247117f1b4Smrg return NULL; 9257117f1b4Smrg } 9267117f1b4Smrg ctx->Texture.Proxy2D->Image[0][level] = texImage; 9277117f1b4Smrg /* Set the 'back' pointer */ 9287117f1b4Smrg texImage->TexObject = ctx->Texture.Proxy2D; 9297117f1b4Smrg } 9307117f1b4Smrg return texImage; 9317117f1b4Smrg case GL_PROXY_TEXTURE_3D: 9327117f1b4Smrg if (level >= ctx->Const.Max3DTextureLevels) 9337117f1b4Smrg return NULL; 9347117f1b4Smrg texImage = ctx->Texture.Proxy3D->Image[0][level]; 9357117f1b4Smrg if (!texImage) { 9367117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9377117f1b4Smrg if (!texImage) { 9387117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9397117f1b4Smrg return NULL; 9407117f1b4Smrg } 9417117f1b4Smrg ctx->Texture.Proxy3D->Image[0][level] = texImage; 9427117f1b4Smrg /* Set the 'back' pointer */ 9437117f1b4Smrg texImage->TexObject = ctx->Texture.Proxy3D; 9447117f1b4Smrg } 9457117f1b4Smrg return texImage; 9467117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP: 9477117f1b4Smrg if (level >= ctx->Const.MaxCubeTextureLevels) 9487117f1b4Smrg return NULL; 9497117f1b4Smrg texImage = ctx->Texture.ProxyCubeMap->Image[0][level]; 9507117f1b4Smrg if (!texImage) { 9517117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9527117f1b4Smrg if (!texImage) { 9537117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9547117f1b4Smrg return NULL; 9557117f1b4Smrg } 9567117f1b4Smrg ctx->Texture.ProxyCubeMap->Image[0][level] = texImage; 9577117f1b4Smrg /* Set the 'back' pointer */ 9587117f1b4Smrg texImage->TexObject = ctx->Texture.ProxyCubeMap; 9597117f1b4Smrg } 9607117f1b4Smrg return texImage; 9617117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 9627117f1b4Smrg if (level > 0) 9637117f1b4Smrg return NULL; 9647117f1b4Smrg texImage = ctx->Texture.ProxyRect->Image[0][level]; 9657117f1b4Smrg if (!texImage) { 9667117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9677117f1b4Smrg if (!texImage) { 9687117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9697117f1b4Smrg return NULL; 9707117f1b4Smrg } 9717117f1b4Smrg ctx->Texture.ProxyRect->Image[0][level] = texImage; 9727117f1b4Smrg /* Set the 'back' pointer */ 9737117f1b4Smrg texImage->TexObject = ctx->Texture.ProxyRect; 9747117f1b4Smrg } 9757117f1b4Smrg return texImage; 9767117f1b4Smrg default: 9777117f1b4Smrg return NULL; 9787117f1b4Smrg } 9797117f1b4Smrg} 9807117f1b4Smrg 9817117f1b4Smrg 9827117f1b4Smrg/** 9837117f1b4Smrg * Get the maximum number of allowed mipmap levels. 9847117f1b4Smrg * 9857117f1b4Smrg * \param ctx GL context. 9867117f1b4Smrg * \param target texture target. 9877117f1b4Smrg * 9887117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given 9897117f1b4Smrg * texture target, or zero if passed a bad target. 9907117f1b4Smrg * 9917117f1b4Smrg * \sa gl_constants. 9927117f1b4Smrg */ 9937117f1b4SmrgGLint 9947117f1b4Smrg_mesa_max_texture_levels(GLcontext *ctx, GLenum target) 9957117f1b4Smrg{ 9967117f1b4Smrg switch (target) { 9977117f1b4Smrg case GL_TEXTURE_1D: 9987117f1b4Smrg case GL_PROXY_TEXTURE_1D: 9997117f1b4Smrg case GL_TEXTURE_2D: 10007117f1b4Smrg case GL_PROXY_TEXTURE_2D: 10017117f1b4Smrg return ctx->Const.MaxTextureLevels; 10027117f1b4Smrg case GL_TEXTURE_3D: 10037117f1b4Smrg case GL_PROXY_TEXTURE_3D: 10047117f1b4Smrg return ctx->Const.Max3DTextureLevels; 10057117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 10067117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 10077117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 10087117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 10097117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 10107117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 10117117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 10127117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 10137117f1b4Smrg return ctx->Const.MaxCubeTextureLevels; 10147117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 10157117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 10167117f1b4Smrg return 1; 10177117f1b4Smrg default: 10187117f1b4Smrg return 0; /* bad target */ 10197117f1b4Smrg } 10207117f1b4Smrg} 10217117f1b4Smrg 10227117f1b4Smrg 10237117f1b4Smrg 10247117f1b4Smrg#if 000 /* not used anymore */ 10257117f1b4Smrg/* 10267117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer. In this case we 10277117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL 10287117f1b4Smrg * spec. 10297117f1b4Smrg */ 10307117f1b4Smrgstatic GLubyte * 10317117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format) 10327117f1b4Smrg{ 10337117f1b4Smrg const GLint components = _mesa_components_in_format(format); 10347117f1b4Smrg const GLint numPixels = width * height * depth; 10357117f1b4Smrg GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 10367117f1b4Smrg 10377117f1b4Smrg#ifdef DEBUG 10387117f1b4Smrg /* 10397117f1b4Smrg * Let's see if anyone finds this. If glTexImage2D() is called with 10407117f1b4Smrg * a NULL image pointer then load the texture image with something 10417117f1b4Smrg * interesting instead of leaving it indeterminate. 10427117f1b4Smrg */ 10437117f1b4Smrg if (data) { 10447117f1b4Smrg static const char message[8][32] = { 10457117f1b4Smrg " X X XXXXX XXX X ", 10467117f1b4Smrg " XX XX X X X X X ", 10477117f1b4Smrg " X X X X X X X ", 10487117f1b4Smrg " X X XXXX XXX XXXXX ", 10497117f1b4Smrg " X X X X X X ", 10507117f1b4Smrg " X X X X X X X ", 10517117f1b4Smrg " X X XXXXX XXX X X ", 10527117f1b4Smrg " " 10537117f1b4Smrg }; 10547117f1b4Smrg 10557117f1b4Smrg GLubyte *imgPtr = data; 10567117f1b4Smrg GLint h, i, j, k; 10577117f1b4Smrg for (h = 0; h < depth; h++) { 10587117f1b4Smrg for (i = 0; i < height; i++) { 10597117f1b4Smrg GLint srcRow = 7 - (i % 8); 10607117f1b4Smrg for (j = 0; j < width; j++) { 10617117f1b4Smrg GLint srcCol = j % 32; 10627117f1b4Smrg GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 10637117f1b4Smrg for (k = 0; k < components; k++) { 10647117f1b4Smrg *imgPtr++ = texel; 10657117f1b4Smrg } 10667117f1b4Smrg } 10677117f1b4Smrg } 10687117f1b4Smrg } 10697117f1b4Smrg } 10707117f1b4Smrg#endif 10717117f1b4Smrg 10727117f1b4Smrg return data; 10737117f1b4Smrg} 10747117f1b4Smrg#endif 10757117f1b4Smrg 10767117f1b4Smrg 10777117f1b4Smrg 10787117f1b4Smrg/** 10797117f1b4Smrg * Reset the fields of a gl_texture_image struct to zero. 10807117f1b4Smrg * 10817117f1b4Smrg * \param img texture image structure. 10827117f1b4Smrg * 10837117f1b4Smrg * This is called when a proxy texture test fails, we set all the 10847117f1b4Smrg * image members (except DriverData) to zero. 10857117f1b4Smrg * It's also used in glTexImage[123]D as a safeguard to be sure all 10867117f1b4Smrg * required fields get initialized properly by the Driver.TexImage[123]D 10877117f1b4Smrg * functions. 10887117f1b4Smrg */ 10897117f1b4Smrgstatic void 10907117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img) 10917117f1b4Smrg{ 10927117f1b4Smrg ASSERT(img); 10937117f1b4Smrg img->_BaseFormat = 0; 10947117f1b4Smrg img->InternalFormat = 0; 10957117f1b4Smrg img->Border = 0; 10967117f1b4Smrg img->Width = 0; 10977117f1b4Smrg img->Height = 0; 10987117f1b4Smrg img->Depth = 0; 10997117f1b4Smrg img->RowStride = 0; 11007117f1b4Smrg if (img->ImageOffsets) { 11017117f1b4Smrg _mesa_free(img->ImageOffsets); 11027117f1b4Smrg img->ImageOffsets = NULL; 11037117f1b4Smrg } 11047117f1b4Smrg img->Width2 = 0; 11057117f1b4Smrg img->Height2 = 0; 11067117f1b4Smrg img->Depth2 = 0; 11077117f1b4Smrg img->WidthLog2 = 0; 11087117f1b4Smrg img->HeightLog2 = 0; 11097117f1b4Smrg img->DepthLog2 = 0; 11107117f1b4Smrg img->Data = NULL; 11117117f1b4Smrg img->TexFormat = &_mesa_null_texformat; 11127117f1b4Smrg img->FetchTexelc = NULL; 11137117f1b4Smrg img->FetchTexelf = NULL; 11147117f1b4Smrg img->IsCompressed = 0; 11157117f1b4Smrg img->CompressedSize = 0; 11167117f1b4Smrg} 11177117f1b4Smrg 11187117f1b4Smrg 11197117f1b4Smrg/** 11207117f1b4Smrg * Initialize basic fields of the gl_texture_image struct. 11217117f1b4Smrg * 11227117f1b4Smrg * \param ctx GL context. 11237117f1b4Smrg * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 11247117f1b4Smrg * \param img texture image structure to be initialized. 11257117f1b4Smrg * \param width image width. 11267117f1b4Smrg * \param height image height. 11277117f1b4Smrg * \param depth image depth. 11287117f1b4Smrg * \param border image border. 11297117f1b4Smrg * \param internalFormat internal format. 11307117f1b4Smrg * 11317117f1b4Smrg * Fills in the fields of \p img with the given information. 11327117f1b4Smrg * Note: width, height and depth include the border. 11337117f1b4Smrg */ 11347117f1b4Smrgvoid 11357117f1b4Smrg_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, 11367117f1b4Smrg struct gl_texture_image *img, 11377117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 11387117f1b4Smrg GLint border, GLenum internalFormat) 11397117f1b4Smrg{ 11407117f1b4Smrg GLint i; 11417117f1b4Smrg 11427117f1b4Smrg ASSERT(img); 11437117f1b4Smrg ASSERT(width >= 0); 11447117f1b4Smrg ASSERT(height >= 0); 11457117f1b4Smrg ASSERT(depth >= 0); 11467117f1b4Smrg 11477117f1b4Smrg img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 11487117f1b4Smrg ASSERT(img->_BaseFormat > 0); 11497117f1b4Smrg img->InternalFormat = internalFormat; 11507117f1b4Smrg img->Border = border; 11517117f1b4Smrg img->Width = width; 11527117f1b4Smrg img->Height = height; 11537117f1b4Smrg img->Depth = depth; 11547117f1b4Smrg img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 11557117f1b4Smrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 11567117f1b4Smrg img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 11577117f1b4Smrg img->WidthLog2 = logbase2(img->Width2); 11587117f1b4Smrg if (height == 1) /* 1-D texture */ 11597117f1b4Smrg img->HeightLog2 = 0; 11607117f1b4Smrg else 11617117f1b4Smrg img->HeightLog2 = logbase2(img->Height2); 11627117f1b4Smrg if (depth == 1) /* 2-D texture */ 11637117f1b4Smrg img->DepthLog2 = 0; 11647117f1b4Smrg else 11657117f1b4Smrg img->DepthLog2 = logbase2(img->Depth2); 11667117f1b4Smrg img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 11677117f1b4Smrg img->IsCompressed = GL_FALSE; 11687117f1b4Smrg img->CompressedSize = 0; 11697117f1b4Smrg 11707117f1b4Smrg if ((width == 1 || _mesa_bitcount(img->Width2) == 1) && 11717117f1b4Smrg (height == 1 || _mesa_bitcount(img->Height2) == 1) && 11727117f1b4Smrg (depth == 1 || _mesa_bitcount(img->Depth2) == 1)) 11737117f1b4Smrg img->_IsPowerOfTwo = GL_TRUE; 11747117f1b4Smrg else 11757117f1b4Smrg img->_IsPowerOfTwo = GL_FALSE; 11767117f1b4Smrg 11777117f1b4Smrg /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 11787117f1b4Smrg img->RowStride = width; 11797117f1b4Smrg /* Allocate the ImageOffsets array and initialize to typical values. 11807117f1b4Smrg * We allocate the array for 1D/2D textures too in order to avoid special- 11817117f1b4Smrg * case code in the texstore routines. 11827117f1b4Smrg */ 11837117f1b4Smrg img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint)); 11847117f1b4Smrg for (i = 0; i < depth; i++) { 11857117f1b4Smrg img->ImageOffsets[i] = i * width * height; 11867117f1b4Smrg } 11877117f1b4Smrg 11887117f1b4Smrg /* Compute Width/Height/DepthScale for mipmap lod computation */ 11897117f1b4Smrg if (target == GL_TEXTURE_RECTANGLE_NV) { 11907117f1b4Smrg /* scale = 1.0 since texture coords directly map to texels */ 11917117f1b4Smrg img->WidthScale = 1.0; 11927117f1b4Smrg img->HeightScale = 1.0; 11937117f1b4Smrg img->DepthScale = 1.0; 11947117f1b4Smrg } 11957117f1b4Smrg else { 11967117f1b4Smrg img->WidthScale = (GLfloat) img->Width; 11977117f1b4Smrg img->HeightScale = (GLfloat) img->Height; 11987117f1b4Smrg img->DepthScale = (GLfloat) img->Depth; 11997117f1b4Smrg } 12007117f1b4Smrg} 12017117f1b4Smrg 12027117f1b4Smrg 12037117f1b4Smrg/** 12047117f1b4Smrg * This is the fallback for Driver.TestProxyTexImage(). Test the texture 12057117f1b4Smrg * level, width, height and depth against the ctx->Const limits for textures. 12067117f1b4Smrg * 12077117f1b4Smrg * A hardware driver might override this function if, for example, the 12087117f1b4Smrg * max 3D texture size is 512x512x64 (i.e. not a cube). 12097117f1b4Smrg * 12107117f1b4Smrg * Note that width, height, depth == 0 is not an error. However, a 12117117f1b4Smrg * texture with zero width/height/depth will be considered "incomplete" 12127117f1b4Smrg * and texturing will effectively be disabled. 12137117f1b4Smrg * 12147117f1b4Smrg * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 12157117f1b4Smrg * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 12167117f1b4Smrg * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 12177117f1b4Smrg * \param level as passed to glTexImage 12187117f1b4Smrg * \param internalFormat as passed to glTexImage 12197117f1b4Smrg * \param format as passed to glTexImage 12207117f1b4Smrg * \param type as passed to glTexImage 12217117f1b4Smrg * \param width as passed to glTexImage 12227117f1b4Smrg * \param height as passed to glTexImage 12237117f1b4Smrg * \param depth as passed to glTexImage 12247117f1b4Smrg * \param border as passed to glTexImage 12257117f1b4Smrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 12267117f1b4Smrg */ 12277117f1b4SmrgGLboolean 12287117f1b4Smrg_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 12297117f1b4Smrg GLint internalFormat, GLenum format, GLenum type, 12307117f1b4Smrg GLint width, GLint height, GLint depth, GLint border) 12317117f1b4Smrg{ 12327117f1b4Smrg GLint maxSize; 12337117f1b4Smrg 12347117f1b4Smrg (void) internalFormat; 12357117f1b4Smrg (void) format; 12367117f1b4Smrg (void) type; 12377117f1b4Smrg 12387117f1b4Smrg switch (target) { 12397117f1b4Smrg case GL_PROXY_TEXTURE_1D: 12407117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 12417117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 12427117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12437117f1b4Smrg width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 12447117f1b4Smrg level >= ctx->Const.MaxTextureLevels) { 12457117f1b4Smrg /* bad width or level */ 12467117f1b4Smrg return GL_FALSE; 12477117f1b4Smrg } 12487117f1b4Smrg return GL_TRUE; 12497117f1b4Smrg case GL_PROXY_TEXTURE_2D: 12507117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 12517117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 12527117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12537117f1b4Smrg width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 12547117f1b4Smrg height < 2 * border || height > 2 + maxSize || 12557117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12567117f1b4Smrg height > 0 && _mesa_bitcount(height - 2 * border) != 1) || 12577117f1b4Smrg level >= ctx->Const.MaxTextureLevels) { 12587117f1b4Smrg /* bad width or height or level */ 12597117f1b4Smrg return GL_FALSE; 12607117f1b4Smrg } 12617117f1b4Smrg return GL_TRUE; 12627117f1b4Smrg case GL_PROXY_TEXTURE_3D: 12637117f1b4Smrg maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 12647117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 12657117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12667117f1b4Smrg width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 12677117f1b4Smrg height < 2 * border || height > 2 + maxSize || 12687117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12697117f1b4Smrg height > 0 && _mesa_bitcount(height - 2 * border) != 1) || 12707117f1b4Smrg depth < 2 * border || depth > 2 + maxSize || 12717117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12727117f1b4Smrg depth > 0 && _mesa_bitcount(depth - 2 * border) != 1) || 12737117f1b4Smrg level >= ctx->Const.Max3DTextureLevels) { 12747117f1b4Smrg /* bad width or height or depth or level */ 12757117f1b4Smrg return GL_FALSE; 12767117f1b4Smrg } 12777117f1b4Smrg return GL_TRUE; 12787117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 12797117f1b4Smrg if (width < 0 || width > ctx->Const.MaxTextureRectSize || 12807117f1b4Smrg height < 0 || height > ctx->Const.MaxTextureRectSize || 12817117f1b4Smrg level != 0) { 12827117f1b4Smrg /* bad width or height or level */ 12837117f1b4Smrg return GL_FALSE; 12847117f1b4Smrg } 12857117f1b4Smrg return GL_TRUE; 12867117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 12877117f1b4Smrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 12887117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 12897117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12907117f1b4Smrg width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 12917117f1b4Smrg height < 2 * border || height > 2 + maxSize || 12927117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 12937117f1b4Smrg height > 0 && _mesa_bitcount(height - 2 * border) != 1) || 12947117f1b4Smrg level >= ctx->Const.MaxCubeTextureLevels) { 12957117f1b4Smrg /* bad width or height */ 12967117f1b4Smrg return GL_FALSE; 12977117f1b4Smrg } 12987117f1b4Smrg return GL_TRUE; 12997117f1b4Smrg default: 13007117f1b4Smrg _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 13017117f1b4Smrg return GL_FALSE; 13027117f1b4Smrg } 13037117f1b4Smrg} 13047117f1b4Smrg 13057117f1b4Smrg 13067117f1b4Smrg/** 13077117f1b4Smrg * Helper function to determine whether a target supports compressed textures 13087117f1b4Smrg */ 13097117f1b4Smrgstatic GLboolean 13107117f1b4Smrgtarget_can_be_compressed(GLcontext *ctx, GLenum target) 13117117f1b4Smrg{ 13127117f1b4Smrg return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 13137117f1b4Smrg || ((ctx->Extensions.ARB_texture_cube_map && 13147117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP || 13157117f1b4Smrg (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 13167117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))); 13177117f1b4Smrg} 13187117f1b4Smrg 13197117f1b4Smrg 13207117f1b4Smrg/** 13217117f1b4Smrg * Test the glTexImage[123]D() parameters for errors. 13227117f1b4Smrg * 13237117f1b4Smrg * \param ctx GL context. 13247117f1b4Smrg * \param target texture target given by the user. 13257117f1b4Smrg * \param level image level given by the user. 13267117f1b4Smrg * \param internalFormat internal format given by the user. 13277117f1b4Smrg * \param format pixel data format given by the user. 13287117f1b4Smrg * \param type pixel data type given by the user. 13297117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 13307117f1b4Smrg * \param width image width given by the user. 13317117f1b4Smrg * \param height image height given by the user. 13327117f1b4Smrg * \param depth image depth given by the user. 13337117f1b4Smrg * \param border image border given by the user. 13347117f1b4Smrg * 13357117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 13367117f1b4Smrg * 13377117f1b4Smrg * Verifies each of the parameters against the constants specified in 13387117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 13397117f1b4Smrg * OpenGL specification. 13407117f1b4Smrg */ 13417117f1b4Smrgstatic GLboolean 13427117f1b4Smrgtexture_error_check( GLcontext *ctx, GLenum target, 13437117f1b4Smrg GLint level, GLint internalFormat, 13447117f1b4Smrg GLenum format, GLenum type, 13457117f1b4Smrg GLuint dimensions, 13467117f1b4Smrg GLint width, GLint height, 13477117f1b4Smrg GLint depth, GLint border ) 13487117f1b4Smrg{ 13497117f1b4Smrg const GLboolean isProxy = _mesa_is_proxy_texture(target); 13507117f1b4Smrg GLboolean sizeOK = GL_TRUE; 13517117f1b4Smrg GLboolean colorFormat, indexFormat; 13527117f1b4Smrg GLenum proxy_target; 13537117f1b4Smrg 13547117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 13557117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 13567117f1b4Smrg if (!isProxy) { 13577117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 13587117f1b4Smrg "glTexImage%dD(level=%d)", dimensions, level); 13597117f1b4Smrg } 13607117f1b4Smrg return GL_TRUE; 13617117f1b4Smrg } 13627117f1b4Smrg 13637117f1b4Smrg /* Check border */ 13647117f1b4Smrg if (border < 0 || border > 1 || 13657117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 13667117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 13677117f1b4Smrg if (!isProxy) { 13687117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 13697117f1b4Smrg "glTexImage%dD(border=%d)", dimensions, border); 13707117f1b4Smrg } 13717117f1b4Smrg return GL_TRUE; 13727117f1b4Smrg } 13737117f1b4Smrg 13747117f1b4Smrg if (width < 0 || height < 0 || depth < 0) { 13757117f1b4Smrg if (!isProxy) { 13767117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 13777117f1b4Smrg "glTexImage%dD(width, height or depth < 0)", dimensions); 13787117f1b4Smrg } 13797117f1b4Smrg return GL_TRUE; 13807117f1b4Smrg } 13817117f1b4Smrg 13827117f1b4Smrg /* Check target and call ctx->Driver.TestProxyTexImage() to check the 13837117f1b4Smrg * level, width, height and depth. 13847117f1b4Smrg */ 13857117f1b4Smrg if (dimensions == 1) { 13867117f1b4Smrg if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 13877117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_1D; 13887117f1b4Smrg height = 1; 13897117f1b4Smrg depth = 1; 13907117f1b4Smrg } 13917117f1b4Smrg else { 13927117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 13937117f1b4Smrg return GL_TRUE; 13947117f1b4Smrg } 13957117f1b4Smrg } 13967117f1b4Smrg else if (dimensions == 2) { 13977117f1b4Smrg depth = 1; 13987117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 13997117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_2D; 14007117f1b4Smrg } 14017117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 14027117f1b4Smrg (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 14037117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 14047117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 14057117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 14067117f1b4Smrg return GL_TRUE; 14077117f1b4Smrg } 14087117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 14097117f1b4Smrg sizeOK = (width == height); 14107117f1b4Smrg } 14117117f1b4Smrg else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 14127117f1b4Smrg target == GL_TEXTURE_RECTANGLE_NV) { 14137117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 14147117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 14157117f1b4Smrg return GL_TRUE; 14167117f1b4Smrg } 14177117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 14187117f1b4Smrg } 14197117f1b4Smrg else { 14207117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 14217117f1b4Smrg return GL_TRUE; 14227117f1b4Smrg } 14237117f1b4Smrg } 14247117f1b4Smrg else if (dimensions == 3) { 14257117f1b4Smrg if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 14267117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_3D; 14277117f1b4Smrg } 14287117f1b4Smrg else { 14297117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 14307117f1b4Smrg return GL_TRUE; 14317117f1b4Smrg } 14327117f1b4Smrg } 14337117f1b4Smrg else { 14347117f1b4Smrg _mesa_problem( ctx, "bad dims in texture_error_check" ); 14357117f1b4Smrg return GL_TRUE; 14367117f1b4Smrg } 14377117f1b4Smrg 14387117f1b4Smrg sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 14397117f1b4Smrg internalFormat, format, 14407117f1b4Smrg type, width, height, 14417117f1b4Smrg depth, border); 14427117f1b4Smrg if (!sizeOK) { 14437117f1b4Smrg if (!isProxy) { 14447117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14457117f1b4Smrg "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 14467117f1b4Smrg dimensions, level, width, height, depth); 14477117f1b4Smrg } 14487117f1b4Smrg return GL_TRUE; 14497117f1b4Smrg } 14507117f1b4Smrg 14517117f1b4Smrg /* Check internalFormat */ 14527117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 14537117f1b4Smrg if (!isProxy) { 14547117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14557117f1b4Smrg "glTexImage%dD(internalFormat=0x%x)", 14567117f1b4Smrg dimensions, internalFormat); 14577117f1b4Smrg } 14587117f1b4Smrg return GL_TRUE; 14597117f1b4Smrg } 14607117f1b4Smrg 14617117f1b4Smrg /* Check incoming image format and type */ 14627117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 14637117f1b4Smrg /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 14647117f1b4Smrg * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 14657117f1b4Smrg */ 14667117f1b4Smrg if (!isProxy) { 14677117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 14687117f1b4Smrg "glTexImage%dD(format or type)", dimensions); 14697117f1b4Smrg } 14707117f1b4Smrg return GL_TRUE; 14717117f1b4Smrg } 14727117f1b4Smrg 14737117f1b4Smrg /* make sure internal format and format basically agree */ 14747117f1b4Smrg colorFormat = is_color_format(format); 14757117f1b4Smrg indexFormat = is_index_format(format); 14767117f1b4Smrg if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) || 14777117f1b4Smrg (is_index_format(internalFormat) && !indexFormat) || 14787117f1b4Smrg (is_depth_format(internalFormat) != is_depth_format(format)) || 14797117f1b4Smrg (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || 14807117f1b4Smrg (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) { 14817117f1b4Smrg if (!isProxy) 14827117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 14837117f1b4Smrg "glTexImage(internalFormat/format)"); 14847117f1b4Smrg return GL_TRUE; 14857117f1b4Smrg } 14867117f1b4Smrg 14877117f1b4Smrg /* additional checks for ycbcr textures */ 14887117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) { 14897117f1b4Smrg ASSERT(ctx->Extensions.MESA_ycbcr_texture); 14907117f1b4Smrg if (type != GL_UNSIGNED_SHORT_8_8_MESA && 14917117f1b4Smrg type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 14927117f1b4Smrg char message[100]; 14937117f1b4Smrg _mesa_sprintf(message, 14947117f1b4Smrg "glTexImage%d(format/type YCBCR mismatch", dimensions); 14957117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, message); 14967117f1b4Smrg return GL_TRUE; /* error */ 14977117f1b4Smrg } 14987117f1b4Smrg if (target != GL_TEXTURE_2D && 14997117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 15007117f1b4Smrg target != GL_TEXTURE_RECTANGLE_NV && 15017117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 15027117f1b4Smrg if (!isProxy) 15037117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 15047117f1b4Smrg return GL_TRUE; 15057117f1b4Smrg } 15067117f1b4Smrg if (border != 0) { 15077117f1b4Smrg if (!isProxy) { 15087117f1b4Smrg char message[100]; 15097117f1b4Smrg _mesa_sprintf(message, 15107117f1b4Smrg "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 15117117f1b4Smrg dimensions, border); 15127117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, message); 15137117f1b4Smrg } 15147117f1b4Smrg return GL_TRUE; 15157117f1b4Smrg } 15167117f1b4Smrg } 15177117f1b4Smrg 15187117f1b4Smrg /* additional checks for depth textures */ 15197117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 15207117f1b4Smrg /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 15217117f1b4Smrg if (target != GL_TEXTURE_1D && 15227117f1b4Smrg target != GL_PROXY_TEXTURE_1D && 15237117f1b4Smrg target != GL_TEXTURE_2D && 15247117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 15257117f1b4Smrg target != GL_TEXTURE_RECTANGLE_ARB && 15267117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 15277117f1b4Smrg if (!isProxy) 15287117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 15297117f1b4Smrg "glTexImage(target/internalFormat)"); 15307117f1b4Smrg return GL_TRUE; 15317117f1b4Smrg } 15327117f1b4Smrg } 15337117f1b4Smrg 15347117f1b4Smrg /* additional checks for compressed textures */ 15357117f1b4Smrg if (is_compressed_format(ctx, internalFormat)) { 15367117f1b4Smrg if (!target_can_be_compressed(ctx, target) && !isProxy) { 15377117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 15387117f1b4Smrg "glTexImage%d(target)", dimensions); 15397117f1b4Smrg return GL_TRUE; 15407117f1b4Smrg } 15417117f1b4Smrg if (border != 0) { 15427117f1b4Smrg if (!isProxy) { 15437117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 15447117f1b4Smrg "glTexImage%D(border!=0)", dimensions); 15457117f1b4Smrg } 15467117f1b4Smrg return GL_TRUE; 15477117f1b4Smrg } 15487117f1b4Smrg } 15497117f1b4Smrg 15507117f1b4Smrg /* if we get here, the parameters are OK */ 15517117f1b4Smrg return GL_FALSE; 15527117f1b4Smrg} 15537117f1b4Smrg 15547117f1b4Smrg 15557117f1b4Smrg/** 15567117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors. 15577117f1b4Smrg * 15587117f1b4Smrg * \param ctx GL context. 15597117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 15607117f1b4Smrg * \param target texture target given by the user. 15617117f1b4Smrg * \param level image level given by the user. 15627117f1b4Smrg * \param xoffset sub-image x offset given by the user. 15637117f1b4Smrg * \param yoffset sub-image y offset given by the user. 15647117f1b4Smrg * \param zoffset sub-image z offset given by the user. 15657117f1b4Smrg * \param format pixel data format given by the user. 15667117f1b4Smrg * \param type pixel data type given by the user. 15677117f1b4Smrg * \param width image width given by the user. 15687117f1b4Smrg * \param height image height given by the user. 15697117f1b4Smrg * \param depth image depth given by the user. 15707117f1b4Smrg * 15717117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 15727117f1b4Smrg * 15737117f1b4Smrg * Verifies each of the parameters against the constants specified in 15747117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 15757117f1b4Smrg * OpenGL specification. 15767117f1b4Smrg */ 15777117f1b4Smrgstatic GLboolean 15787117f1b4Smrgsubtexture_error_check( GLcontext *ctx, GLuint dimensions, 15797117f1b4Smrg GLenum target, GLint level, 15807117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 15817117f1b4Smrg GLint width, GLint height, GLint depth, 15827117f1b4Smrg GLenum format, GLenum type ) 15837117f1b4Smrg{ 15847117f1b4Smrg /* Check target */ 15857117f1b4Smrg if (dimensions == 1) { 15867117f1b4Smrg if (target != GL_TEXTURE_1D) { 15877117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 15887117f1b4Smrg return GL_TRUE; 15897117f1b4Smrg } 15907117f1b4Smrg } 15917117f1b4Smrg else if (dimensions == 2) { 15927117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 15937117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 15947117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 15957117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 15967117f1b4Smrg return GL_TRUE; 15977117f1b4Smrg } 15987117f1b4Smrg } 15997117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 16007117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 16017117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 16027117f1b4Smrg return GL_TRUE; 16037117f1b4Smrg } 16047117f1b4Smrg } 16057117f1b4Smrg else if (target != GL_TEXTURE_2D) { 16067117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 16077117f1b4Smrg return GL_TRUE; 16087117f1b4Smrg } 16097117f1b4Smrg } 16107117f1b4Smrg else if (dimensions == 3) { 16117117f1b4Smrg if (target != GL_TEXTURE_3D) { 16127117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 16137117f1b4Smrg return GL_TRUE; 16147117f1b4Smrg } 16157117f1b4Smrg } 16167117f1b4Smrg else { 16177117f1b4Smrg _mesa_problem( ctx, "invalid dims in texture_error_check" ); 16187117f1b4Smrg return GL_TRUE; 16197117f1b4Smrg } 16207117f1b4Smrg 16217117f1b4Smrg /* Basic level check */ 16227117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 16237117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 16247117f1b4Smrg return GL_TRUE; 16257117f1b4Smrg } 16267117f1b4Smrg 16277117f1b4Smrg if (width < 0) { 16287117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16297117f1b4Smrg "glTexSubImage%dD(width=%d)", dimensions, width); 16307117f1b4Smrg return GL_TRUE; 16317117f1b4Smrg } 16327117f1b4Smrg if (height < 0 && dimensions > 1) { 16337117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16347117f1b4Smrg "glTexSubImage%dD(height=%d)", dimensions, height); 16357117f1b4Smrg return GL_TRUE; 16367117f1b4Smrg } 16377117f1b4Smrg if (depth < 0 && dimensions > 2) { 16387117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16397117f1b4Smrg "glTexSubImage%dD(depth=%d)", dimensions, depth); 16407117f1b4Smrg return GL_TRUE; 16417117f1b4Smrg } 16427117f1b4Smrg 16437117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 16447117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 16457117f1b4Smrg "glTexSubImage%dD(format or type)", dimensions); 16467117f1b4Smrg return GL_TRUE; 16477117f1b4Smrg } 16487117f1b4Smrg 16497117f1b4Smrg return GL_FALSE; 16507117f1b4Smrg} 16517117f1b4Smrg 16527117f1b4Smrgstatic GLboolean 16537117f1b4Smrgsubtexture_error_check2( GLcontext *ctx, GLuint dimensions, 16547117f1b4Smrg GLenum target, GLint level, 16557117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 16567117f1b4Smrg GLint width, GLint height, GLint depth, 16577117f1b4Smrg GLenum format, GLenum type, 16587117f1b4Smrg const struct gl_texture_image *destTex ) 16597117f1b4Smrg{ 16607117f1b4Smrg if (!destTex) { 16617117f1b4Smrg /* undefined image level */ 16627117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 16637117f1b4Smrg return GL_TRUE; 16647117f1b4Smrg } 16657117f1b4Smrg 16667117f1b4Smrg if (xoffset < -((GLint)destTex->Border)) { 16677117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 16687117f1b4Smrg dimensions); 16697117f1b4Smrg return GL_TRUE; 16707117f1b4Smrg } 16717117f1b4Smrg if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 16727117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 16737117f1b4Smrg dimensions); 16747117f1b4Smrg return GL_TRUE; 16757117f1b4Smrg } 16767117f1b4Smrg if (dimensions > 1) { 16777117f1b4Smrg if (yoffset < -((GLint)destTex->Border)) { 16787117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 16797117f1b4Smrg dimensions); 16807117f1b4Smrg return GL_TRUE; 16817117f1b4Smrg } 16827117f1b4Smrg if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 16837117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 16847117f1b4Smrg dimensions); 16857117f1b4Smrg return GL_TRUE; 16867117f1b4Smrg } 16877117f1b4Smrg } 16887117f1b4Smrg if (dimensions > 2) { 16897117f1b4Smrg if (zoffset < -((GLint)destTex->Border)) { 16907117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 16917117f1b4Smrg return GL_TRUE; 16927117f1b4Smrg } 16937117f1b4Smrg if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 16947117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 16957117f1b4Smrg return GL_TRUE; 16967117f1b4Smrg } 16977117f1b4Smrg } 16987117f1b4Smrg 16997117f1b4Smrg#if FEATURE_EXT_texture_sRGB 17007117f1b4Smrg if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 17017117f1b4Smrg destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 17027117f1b4Smrg destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 17037117f1b4Smrg destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { 17047117f1b4Smrg if ((width & 0x3) || (height & 0x3) || 17057117f1b4Smrg (xoffset & 0x3) || (yoffset & 0x3)) 17067117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17077117f1b4Smrg "glTexSubImage%dD(size or offset not multiple of 4)", 17087117f1b4Smrg dimensions); 17097117f1b4Smrg return GL_TRUE; 17107117f1b4Smrg } 17117117f1b4Smrg#endif 17127117f1b4Smrg 17137117f1b4Smrg if (destTex->IsCompressed) { 17147117f1b4Smrg if (!target_can_be_compressed(ctx, target)) { 17157117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 17167117f1b4Smrg "glTexSubImage%D(target)", dimensions); 17177117f1b4Smrg return GL_TRUE; 17187117f1b4Smrg } 17197117f1b4Smrg /* offset must be multiple of 4 */ 17207117f1b4Smrg if ((xoffset & 3) || (yoffset & 3)) { 17217117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17227117f1b4Smrg "glTexSubImage%D(xoffset or yoffset)", dimensions); 17237117f1b4Smrg return GL_TRUE; 17247117f1b4Smrg } 17257117f1b4Smrg /* size must be multiple of 4 or equal to whole texture size */ 17267117f1b4Smrg if ((width & 3) && (GLuint) width != destTex->Width) { 17277117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17287117f1b4Smrg "glTexSubImage%D(width)", dimensions); 17297117f1b4Smrg return GL_TRUE; 17307117f1b4Smrg } 17317117f1b4Smrg if ((height & 3) && (GLuint) height != destTex->Height) { 17327117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17337117f1b4Smrg "glTexSubImage%D(width)", dimensions); 17347117f1b4Smrg return GL_TRUE; 17357117f1b4Smrg } 17367117f1b4Smrg } 17377117f1b4Smrg 17387117f1b4Smrg return GL_FALSE; 17397117f1b4Smrg} 17407117f1b4Smrg 17417117f1b4Smrg 17427117f1b4Smrg/** 17437117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors. 17447117f1b4Smrg * 17457117f1b4Smrg * \param ctx GL context. 17467117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 17477117f1b4Smrg * \param target texture target given by the user. 17487117f1b4Smrg * \param level image level given by the user. 17497117f1b4Smrg * \param internalFormat internal format given by the user. 17507117f1b4Smrg * \param width image width given by the user. 17517117f1b4Smrg * \param height image height given by the user. 17527117f1b4Smrg * \param depth image depth given by the user. 17537117f1b4Smrg * \param border texture border. 17547117f1b4Smrg * 17557117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 17567117f1b4Smrg * 17577117f1b4Smrg * Verifies each of the parameters against the constants specified in 17587117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 17597117f1b4Smrg * OpenGL specification. 17607117f1b4Smrg */ 17617117f1b4Smrgstatic GLboolean 17627117f1b4Smrgcopytexture_error_check( GLcontext *ctx, GLuint dimensions, 17637117f1b4Smrg GLenum target, GLint level, GLint internalFormat, 17647117f1b4Smrg GLint width, GLint height, GLint border ) 17657117f1b4Smrg{ 17667117f1b4Smrg GLenum type; 17677117f1b4Smrg GLboolean sizeOK; 17687117f1b4Smrg GLint format; 17697117f1b4Smrg 17707117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 17717117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 17727117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17737117f1b4Smrg "glCopyTexImage%dD(level=%d)", dimensions, level); 17747117f1b4Smrg return GL_TRUE; 17757117f1b4Smrg } 17767117f1b4Smrg 17777117f1b4Smrg /* Check that the source buffer is complete */ 17787117f1b4Smrg if (ctx->ReadBuffer->Name) { 17797117f1b4Smrg _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 17807117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 17817117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 17827117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 17837117f1b4Smrg return GL_TRUE; 17847117f1b4Smrg } 17857117f1b4Smrg } 17867117f1b4Smrg 17877117f1b4Smrg /* Check border */ 17887117f1b4Smrg if (border < 0 || border > 1 || 17897117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 17907117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 17917117f1b4Smrg return GL_TRUE; 17927117f1b4Smrg } 17937117f1b4Smrg 17947117f1b4Smrg format = _mesa_base_tex_format(ctx, internalFormat); 17957117f1b4Smrg if (format < 0) { 17967117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17977117f1b4Smrg "glCopyTexImage%dD(internalFormat)", dimensions); 17987117f1b4Smrg return GL_TRUE; 17997117f1b4Smrg } 18007117f1b4Smrg 18017117f1b4Smrg /* NOTE: the format and type aren't really significant for 18027117f1b4Smrg * TestProxyTexImage(). Only the internalformat really matters. 18037117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, format)) { 18047117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18057117f1b4Smrg "glCopyTexImage%dD(missing readbuffer)", dimensions); 18067117f1b4Smrg return GL_TRUE; 18077117f1b4Smrg } 18087117f1b4Smrg 18097117f1b4Smrg */ 18107117f1b4Smrg type = GL_FLOAT; 18117117f1b4Smrg 18127117f1b4Smrg /* Check target and call ctx->Driver.TestProxyTexImage() to check the 18137117f1b4Smrg * level, width, height and depth. 18147117f1b4Smrg */ 18157117f1b4Smrg if (dimensions == 1) { 18167117f1b4Smrg if (target == GL_TEXTURE_1D) { 18177117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 18187117f1b4Smrg level, internalFormat, 18197117f1b4Smrg format, type, 18207117f1b4Smrg width, 1, 1, border); 18217117f1b4Smrg } 18227117f1b4Smrg else { 18237117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 18247117f1b4Smrg return GL_TRUE; 18257117f1b4Smrg } 18267117f1b4Smrg } 18277117f1b4Smrg else if (dimensions == 2) { 18287117f1b4Smrg if (target == GL_TEXTURE_2D) { 18297117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 18307117f1b4Smrg level, internalFormat, 18317117f1b4Smrg format, type, 18327117f1b4Smrg width, height, 1, border); 18337117f1b4Smrg } 18347117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 18357117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 18367117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 18377117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 18387117f1b4Smrg return GL_TRUE; 18397117f1b4Smrg } 18407117f1b4Smrg sizeOK = (width == height) && 18417117f1b4Smrg ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 18427117f1b4Smrg level, internalFormat, format, type, 18437117f1b4Smrg width, height, 1, border); 18447117f1b4Smrg } 18457117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 18467117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 18477117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 18487117f1b4Smrg return GL_TRUE; 18497117f1b4Smrg } 18507117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, 18517117f1b4Smrg GL_PROXY_TEXTURE_RECTANGLE_NV, 18527117f1b4Smrg level, internalFormat, 18537117f1b4Smrg format, type, 18547117f1b4Smrg width, height, 1, border); 18557117f1b4Smrg } 18567117f1b4Smrg else { 18577117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 18587117f1b4Smrg return GL_TRUE; 18597117f1b4Smrg } 18607117f1b4Smrg } 18617117f1b4Smrg else { 18627117f1b4Smrg _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 18637117f1b4Smrg return GL_TRUE; 18647117f1b4Smrg } 18657117f1b4Smrg 18667117f1b4Smrg if (!sizeOK) { 18677117f1b4Smrg if (dimensions == 1) { 18687117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18697117f1b4Smrg "glCopyTexImage1D(width=%d)", width); 18707117f1b4Smrg } 18717117f1b4Smrg else { 18727117f1b4Smrg ASSERT(dimensions == 2); 18737117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18747117f1b4Smrg "glCopyTexImage2D(width=%d, height=%d)", width, height); 18757117f1b4Smrg } 18767117f1b4Smrg return GL_TRUE; 18777117f1b4Smrg } 18787117f1b4Smrg 18797117f1b4Smrg if (is_compressed_format(ctx, internalFormat)) { 18807117f1b4Smrg if (target != GL_TEXTURE_2D) { 18817117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 18827117f1b4Smrg "glCopyTexImage%d(target)", dimensions); 18837117f1b4Smrg return GL_TRUE; 18847117f1b4Smrg } 18857117f1b4Smrg if (border != 0) { 18867117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18877117f1b4Smrg "glCopyTexImage%D(border!=0)", dimensions); 18887117f1b4Smrg return GL_TRUE; 18897117f1b4Smrg } 18907117f1b4Smrg } 18917117f1b4Smrg else if (is_depth_format(internalFormat)) { 18927117f1b4Smrg /* make sure we have depth/stencil buffers */ 18937117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 18947117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18957117f1b4Smrg "glCopyTexImage%D(no depth)", dimensions); 18967117f1b4Smrg return GL_TRUE; 18977117f1b4Smrg } 18987117f1b4Smrg } 18997117f1b4Smrg else if (is_depthstencil_format(internalFormat)) { 19007117f1b4Smrg /* make sure we have depth/stencil buffers */ 19017117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 19027117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 19037117f1b4Smrg "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 19047117f1b4Smrg return GL_TRUE; 19057117f1b4Smrg } 19067117f1b4Smrg } 19077117f1b4Smrg 19087117f1b4Smrg /* if we get here, the parameters are OK */ 19097117f1b4Smrg return GL_FALSE; 19107117f1b4Smrg} 19117117f1b4Smrg 19127117f1b4Smrg 19137117f1b4Smrg/** 19147117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors. 19157117f1b4Smrg * 19167117f1b4Smrg * \param ctx GL context. 19177117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 19187117f1b4Smrg * \param target texture target given by the user. 19197117f1b4Smrg * \param level image level given by the user. 19207117f1b4Smrg * \param xoffset sub-image x offset given by the user. 19217117f1b4Smrg * \param yoffset sub-image y offset given by the user. 19227117f1b4Smrg * \param zoffset sub-image z offset given by the user. 19237117f1b4Smrg * \param width image width given by the user. 19247117f1b4Smrg * \param height image height given by the user. 19257117f1b4Smrg * 19267117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 19277117f1b4Smrg * 19287117f1b4Smrg * Verifies each of the parameters against the constants specified in 19297117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 19307117f1b4Smrg * OpenGL specification. 19317117f1b4Smrg */ 19327117f1b4Smrgstatic GLboolean 19337117f1b4Smrgcopytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, 19347117f1b4Smrg GLenum target, GLint level, 19357117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 19367117f1b4Smrg GLsizei width, GLsizei height) 19377117f1b4Smrg{ 19387117f1b4Smrg /* Check target */ 19397117f1b4Smrg /* Check that the source buffer is complete */ 19407117f1b4Smrg if (ctx->ReadBuffer->Name) { 19417117f1b4Smrg _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 19427117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 19437117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 19447117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 19457117f1b4Smrg return GL_TRUE; 19467117f1b4Smrg } 19477117f1b4Smrg } 19487117f1b4Smrg 19497117f1b4Smrg if (dimensions == 1) { 19507117f1b4Smrg if (target != GL_TEXTURE_1D) { 19517117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 19527117f1b4Smrg return GL_TRUE; 19537117f1b4Smrg } 19547117f1b4Smrg } 19557117f1b4Smrg else if (dimensions == 2) { 19567117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 19577117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 19587117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 19597117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 19607117f1b4Smrg return GL_TRUE; 19617117f1b4Smrg } 19627117f1b4Smrg } 19637117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 19647117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 19657117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 19667117f1b4Smrg return GL_TRUE; 19677117f1b4Smrg } 19687117f1b4Smrg } 19697117f1b4Smrg else if (target != GL_TEXTURE_2D) { 19707117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 19717117f1b4Smrg return GL_TRUE; 19727117f1b4Smrg } 19737117f1b4Smrg } 19747117f1b4Smrg else if (dimensions == 3) { 19757117f1b4Smrg if (target != GL_TEXTURE_3D) { 19767117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 19777117f1b4Smrg return GL_TRUE; 19787117f1b4Smrg } 19797117f1b4Smrg } 19807117f1b4Smrg 19817117f1b4Smrg /* Check level */ 19827117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 19837117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19847117f1b4Smrg "glCopyTexSubImage%dD(level=%d)", dimensions, level); 19857117f1b4Smrg return GL_TRUE; 19867117f1b4Smrg } 19877117f1b4Smrg 19887117f1b4Smrg /* Check size */ 19897117f1b4Smrg if (width < 0) { 19907117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19917117f1b4Smrg "glCopyTexSubImage%dD(width=%d)", dimensions, width); 19927117f1b4Smrg return GL_TRUE; 19937117f1b4Smrg } 19947117f1b4Smrg if (dimensions > 1 && height < 0) { 19957117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19967117f1b4Smrg "glCopyTexSubImage%dD(height=%d)", dimensions, height); 19977117f1b4Smrg return GL_TRUE; 19987117f1b4Smrg } 19997117f1b4Smrg 20007117f1b4Smrg return GL_FALSE; 20017117f1b4Smrg} 20027117f1b4Smrg 20037117f1b4Smrgstatic GLboolean 20047117f1b4Smrgcopytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 20057117f1b4Smrg GLenum target, GLint level, 20067117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 20077117f1b4Smrg GLsizei width, GLsizei height, 20087117f1b4Smrg const struct gl_texture_image *teximage ) 20097117f1b4Smrg{ 20107117f1b4Smrg if (!teximage) { 20117117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20127117f1b4Smrg "glCopyTexSubImage%dD(undefined texture level: %d)", 20137117f1b4Smrg dimensions, level); 20147117f1b4Smrg return GL_TRUE; 20157117f1b4Smrg } 20167117f1b4Smrg 20177117f1b4Smrg if (xoffset < -((GLint)teximage->Border)) { 20187117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20197117f1b4Smrg "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 20207117f1b4Smrg return GL_TRUE; 20217117f1b4Smrg } 20227117f1b4Smrg if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 20237117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20247117f1b4Smrg "glCopyTexSubImage%dD(xoffset+width)", dimensions); 20257117f1b4Smrg return GL_TRUE; 20267117f1b4Smrg } 20277117f1b4Smrg if (dimensions > 1) { 20287117f1b4Smrg if (yoffset < -((GLint)teximage->Border)) { 20297117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20307117f1b4Smrg "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 20317117f1b4Smrg return GL_TRUE; 20327117f1b4Smrg } 20337117f1b4Smrg /* NOTE: we're adding the border here, not subtracting! */ 20347117f1b4Smrg if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 20357117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20367117f1b4Smrg "glCopyTexSubImage%dD(yoffset+height)", dimensions); 20377117f1b4Smrg return GL_TRUE; 20387117f1b4Smrg } 20397117f1b4Smrg } 20407117f1b4Smrg 20417117f1b4Smrg if (dimensions > 2) { 20427117f1b4Smrg if (zoffset < -((GLint)teximage->Border)) { 20437117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20447117f1b4Smrg "glCopyTexSubImage%dD(zoffset)", dimensions); 20457117f1b4Smrg return GL_TRUE; 20467117f1b4Smrg } 20477117f1b4Smrg if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 20487117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20497117f1b4Smrg "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 20507117f1b4Smrg return GL_TRUE; 20517117f1b4Smrg } 20527117f1b4Smrg } 20537117f1b4Smrg 20547117f1b4Smrg if (teximage->IsCompressed) { 20557117f1b4Smrg if (target != GL_TEXTURE_2D) { 20567117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 20577117f1b4Smrg "glCopyTexSubImage%d(target)", dimensions); 20587117f1b4Smrg return GL_TRUE; 20597117f1b4Smrg } 20607117f1b4Smrg /* offset must be multiple of 4 */ 20617117f1b4Smrg if ((xoffset & 3) || (yoffset & 3)) { 20627117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20637117f1b4Smrg "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 20647117f1b4Smrg return GL_TRUE; 20657117f1b4Smrg } 20667117f1b4Smrg /* size must be multiple of 4 */ 20677117f1b4Smrg if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 20687117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20697117f1b4Smrg "glCopyTexSubImage%D(width)", dimensions); 20707117f1b4Smrg return GL_TRUE; 20717117f1b4Smrg } 20727117f1b4Smrg if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 20737117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20747117f1b4Smrg "glCopyTexSubImage%D(height)", dimensions); 20757117f1b4Smrg return GL_TRUE; 20767117f1b4Smrg } 20777117f1b4Smrg } 20787117f1b4Smrg 20797117f1b4Smrg if (teximage->InternalFormat == GL_YCBCR_MESA) { 20807117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 20817117f1b4Smrg return GL_TRUE; 20827117f1b4Smrg } 20837117f1b4Smrg 20847117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 20857117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20867117f1b4Smrg "glCopyTexSubImage%dD(missing readbuffer)", dimensions); 20877117f1b4Smrg return GL_TRUE; 20887117f1b4Smrg } 20897117f1b4Smrg 20907117f1b4Smrg if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 20917117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 20927117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20937117f1b4Smrg "glCopyTexSubImage%D(no depth buffer)", 20947117f1b4Smrg dimensions); 20957117f1b4Smrg return GL_TRUE; 20967117f1b4Smrg } 20977117f1b4Smrg } 20987117f1b4Smrg else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 20997117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 21007117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 21017117f1b4Smrg "glCopyTexSubImage%D(no depth/stencil buffer)", 21027117f1b4Smrg dimensions); 21037117f1b4Smrg return GL_TRUE; 21047117f1b4Smrg } 21057117f1b4Smrg } 21067117f1b4Smrg 21077117f1b4Smrg /* if we get here, the parameters are OK */ 21087117f1b4Smrg return GL_FALSE; 21097117f1b4Smrg} 21107117f1b4Smrg 21117117f1b4Smrg 21127117f1b4Smrg/** 21137117f1b4Smrg * Get texture image. Called by glGetTexImage. 21147117f1b4Smrg * 21157117f1b4Smrg * \param target texture target. 21167117f1b4Smrg * \param level image level. 21177117f1b4Smrg * \param format pixel data format for returned image. 21187117f1b4Smrg * \param type pixel data type for returned image. 21197117f1b4Smrg * \param pixels returned pixel data. 21207117f1b4Smrg */ 21217117f1b4Smrgvoid GLAPIENTRY 21227117f1b4Smrg_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 21237117f1b4Smrg GLenum type, GLvoid *pixels ) 21247117f1b4Smrg{ 21257117f1b4Smrg const struct gl_texture_unit *texUnit; 21267117f1b4Smrg struct gl_texture_object *texObj; 21277117f1b4Smrg struct gl_texture_image *texImage; 21287117f1b4Smrg GLint maxLevels = 0; 21297117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 21307117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 21317117f1b4Smrg 21327117f1b4Smrg texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 21337117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 21347117f1b4Smrg if (!texObj || _mesa_is_proxy_texture(target)) { 21357117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 21367117f1b4Smrg return; 21377117f1b4Smrg } 21387117f1b4Smrg 21397117f1b4Smrg maxLevels = _mesa_max_texture_levels(ctx, target); 21407117f1b4Smrg ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 21417117f1b4Smrg 21427117f1b4Smrg if (level < 0 || level >= maxLevels) { 21437117f1b4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 21447117f1b4Smrg return; 21457117f1b4Smrg } 21467117f1b4Smrg 21477117f1b4Smrg if (_mesa_sizeof_packed_type(type) <= 0) { 21487117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 21497117f1b4Smrg return; 21507117f1b4Smrg } 21517117f1b4Smrg 21527117f1b4Smrg if (_mesa_components_in_format(format) <= 0 || 21537117f1b4Smrg format == GL_STENCIL_INDEX) { 21547117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 21557117f1b4Smrg return; 21567117f1b4Smrg } 21577117f1b4Smrg 21587117f1b4Smrg if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { 21597117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 21607117f1b4Smrg return; 21617117f1b4Smrg } 21627117f1b4Smrg 21637117f1b4Smrg if (!ctx->Extensions.SGIX_depth_texture && 21647117f1b4Smrg !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { 21657117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 21667117f1b4Smrg return; 21677117f1b4Smrg } 21687117f1b4Smrg 21697117f1b4Smrg if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { 21707117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 21717117f1b4Smrg return; 21727117f1b4Smrg } 21737117f1b4Smrg 21747117f1b4Smrg if (!ctx->Extensions.EXT_packed_depth_stencil 21757117f1b4Smrg && is_depthstencil_format(format)) { 21767117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 21777117f1b4Smrg return; 21787117f1b4Smrg } 21797117f1b4Smrg 21807117f1b4Smrg _mesa_lock_texture(ctx, texObj); 21817117f1b4Smrg { 21827117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 21837117f1b4Smrg if (!texImage) { 21847117f1b4Smrg /* invalid mipmap level, not an error */ 21857117f1b4Smrg goto out; 21867117f1b4Smrg } 21877117f1b4Smrg 21887117f1b4Smrg 21897117f1b4Smrg /* Make sure the requested image format is compatible with the 21907117f1b4Smrg * texture's format. Note that a color index texture can be converted 21917117f1b4Smrg * to RGBA so that combo is allowed. 21927117f1b4Smrg */ 21937117f1b4Smrg if (is_color_format(format) 21947117f1b4Smrg && !is_color_format(texImage->TexFormat->BaseFormat) 21957117f1b4Smrg && !is_index_format(texImage->TexFormat->BaseFormat)) { 21967117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 21977117f1b4Smrg goto out; 21987117f1b4Smrg } 21997117f1b4Smrg else if (is_index_format(format) 22007117f1b4Smrg && !is_index_format(texImage->TexFormat->BaseFormat)) { 22017117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 22027117f1b4Smrg goto out; 22037117f1b4Smrg } 22047117f1b4Smrg else if (is_depth_format(format) 22057117f1b4Smrg && !is_depth_format(texImage->TexFormat->BaseFormat) 22067117f1b4Smrg && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 22077117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 22087117f1b4Smrg goto out; 22097117f1b4Smrg } 22107117f1b4Smrg else if (is_ycbcr_format(format) 22117117f1b4Smrg && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 22127117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 22137117f1b4Smrg goto out; 22147117f1b4Smrg } 22157117f1b4Smrg else if (is_depthstencil_format(format) 22167117f1b4Smrg && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 22177117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 22187117f1b4Smrg goto out; 22197117f1b4Smrg } 22207117f1b4Smrg 22217117f1b4Smrg if (ctx->Pack.BufferObj->Name) { 22227117f1b4Smrg /* packing texture image into a PBO */ 22237117f1b4Smrg const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 22247117f1b4Smrg if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 22257117f1b4Smrg texImage->Height, texImage->Depth, 22267117f1b4Smrg format, type, pixels)) { 22277117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 22287117f1b4Smrg "glGetTexImage(invalid PBO access)"); 22297117f1b4Smrg goto out; 22307117f1b4Smrg } 22317117f1b4Smrg } 22327117f1b4Smrg 22337117f1b4Smrg /* typically, this will call _mesa_get_teximage() */ 22347117f1b4Smrg ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 22357117f1b4Smrg texObj, texImage); 22367117f1b4Smrg 22377117f1b4Smrg } 22387117f1b4Smrg out: 22397117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 22407117f1b4Smrg} 22417117f1b4Smrg 22427117f1b4Smrg 22437117f1b4Smrg 22447117f1b4Smrg/** 22457117f1b4Smrg * Check if the given texture image is bound to any framebuffer objects 22467117f1b4Smrg * and update/invalidate them. 22477117f1b4Smrg * XXX We're only checking the currently bound framebuffer object for now. 22487117f1b4Smrg * In the future, perhaps struct gl_texture_image should have a pointer (or 22497117f1b4Smrg * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to. 22507117f1b4Smrg */ 22517117f1b4Smrgstatic void 22527117f1b4Smrgupdate_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 22537117f1b4Smrg GLuint face, GLuint level) 22547117f1b4Smrg{ 22557117f1b4Smrg if (ctx->DrawBuffer->Name) { 22567117f1b4Smrg GLuint i; 22577117f1b4Smrg for (i = 0; i < BUFFER_COUNT; i++) { 22587117f1b4Smrg struct gl_renderbuffer_attachment *att = 22597117f1b4Smrg ctx->DrawBuffer->Attachment + i; 22607117f1b4Smrg if (att->Type == GL_TEXTURE && 22617117f1b4Smrg att->Texture == texObj && 22627117f1b4Smrg att->TextureLevel == level && 22637117f1b4Smrg att->CubeMapFace == face) { 22647117f1b4Smrg ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 22657117f1b4Smrg /* Tell driver about the new renderbuffer texture */ 22667117f1b4Smrg ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 22677117f1b4Smrg } 22687117f1b4Smrg } 22697117f1b4Smrg } 22707117f1b4Smrg} 22717117f1b4Smrg 22727117f1b4Smrg 22737117f1b4Smrg 22747117f1b4Smrg/* 22757117f1b4Smrg * Called from the API. Note that width includes the border. 22767117f1b4Smrg */ 22777117f1b4Smrgvoid GLAPIENTRY 22787117f1b4Smrg_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 22797117f1b4Smrg GLsizei width, GLint border, GLenum format, 22807117f1b4Smrg GLenum type, const GLvoid *pixels ) 22817117f1b4Smrg{ 22827117f1b4Smrg GLsizei postConvWidth = width; 22837117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 22847117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 22857117f1b4Smrg 22867117f1b4Smrg if (is_color_format(internalFormat)) { 22877117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 22887117f1b4Smrg } 22897117f1b4Smrg 22907117f1b4Smrg if (target == GL_TEXTURE_1D) { 22917117f1b4Smrg /* non-proxy target */ 22927117f1b4Smrg struct gl_texture_unit *texUnit; 22937117f1b4Smrg struct gl_texture_object *texObj; 22947117f1b4Smrg struct gl_texture_image *texImage; 22957117f1b4Smrg const GLuint face = texture_face(target); 22967117f1b4Smrg 22977117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 22987117f1b4Smrg format, type, 1, postConvWidth, 1, 1, border)) { 22997117f1b4Smrg return; /* error was recorded */ 23007117f1b4Smrg } 23017117f1b4Smrg 23027117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 23037117f1b4Smrg _mesa_update_state(ctx); 23047117f1b4Smrg 23057117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 23067117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 23077117f1b4Smrg _mesa_lock_texture(ctx, texObj); 23087117f1b4Smrg { 23097117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 23107117f1b4Smrg if (!texImage) { 23117117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 23127117f1b4Smrg goto out; 23137117f1b4Smrg } 23147117f1b4Smrg 23157117f1b4Smrg if (texImage->Data) { 23167117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 23177117f1b4Smrg } 23187117f1b4Smrg 23197117f1b4Smrg ASSERT(texImage->Data == NULL); 23207117f1b4Smrg 23217117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 23227117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 23237117f1b4Smrg postConvWidth, 1, 1, 23247117f1b4Smrg border, internalFormat); 23257117f1b4Smrg 23267117f1b4Smrg ASSERT(ctx->Driver.TexImage1D); 23277117f1b4Smrg 23287117f1b4Smrg /* Give the texture to the driver! <pixels> may be null! */ 23297117f1b4Smrg (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 23307117f1b4Smrg width, border, format, type, pixels, 23317117f1b4Smrg &ctx->Unpack, texObj, texImage); 23327117f1b4Smrg 23337117f1b4Smrg ASSERT(texImage->TexFormat); 23347117f1b4Smrg 23357117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 23367117f1b4Smrg 23377117f1b4Smrg /* state update */ 23387117f1b4Smrg texObj->Complete = GL_FALSE; 23397117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 23407117f1b4Smrg } 23417117f1b4Smrg out: 23427117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 23437117f1b4Smrg } 23447117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 23457117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 23467117f1b4Smrg struct gl_texture_image *texImage; 23477117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 23487117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 23497117f1b4Smrg format, type, 1, postConvWidth, 1, 1, border)) { 23507117f1b4Smrg /* when error, clear all proxy texture image parameters */ 23517117f1b4Smrg if (texImage) 23527117f1b4Smrg clear_teximage_fields(texImage); 23537117f1b4Smrg } 23547117f1b4Smrg else { 23557117f1b4Smrg /* no error, set the tex image parameters */ 23567117f1b4Smrg ASSERT(texImage); 23577117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 23587117f1b4Smrg postConvWidth, 1, 1, 23597117f1b4Smrg border, internalFormat); 23607117f1b4Smrg texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 23617117f1b4Smrg internalFormat, format, type); 23627117f1b4Smrg } 23637117f1b4Smrg } 23647117f1b4Smrg else { 23657117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 23667117f1b4Smrg return; 23677117f1b4Smrg } 23687117f1b4Smrg} 23697117f1b4Smrg 23707117f1b4Smrg 23717117f1b4Smrgvoid GLAPIENTRY 23727117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 23737117f1b4Smrg GLsizei width, GLsizei height, GLint border, 23747117f1b4Smrg GLenum format, GLenum type, 23757117f1b4Smrg const GLvoid *pixels ) 23767117f1b4Smrg{ 23777117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 23787117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 23797117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 23807117f1b4Smrg 23817117f1b4Smrg if (is_color_format(internalFormat)) { 23827117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 23837117f1b4Smrg &postConvHeight); 23847117f1b4Smrg } 23857117f1b4Smrg 23867117f1b4Smrg if (target == GL_TEXTURE_2D || 23877117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 23887117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 23897117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 23907117f1b4Smrg (ctx->Extensions.NV_texture_rectangle && 23917117f1b4Smrg target == GL_TEXTURE_RECTANGLE_NV)) { 23927117f1b4Smrg /* non-proxy target */ 23937117f1b4Smrg struct gl_texture_unit *texUnit; 23947117f1b4Smrg struct gl_texture_object *texObj; 23957117f1b4Smrg struct gl_texture_image *texImage; 23967117f1b4Smrg const GLuint face = texture_face(target); 23977117f1b4Smrg 23987117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 23997117f1b4Smrg format, type, 2, postConvWidth, postConvHeight, 24007117f1b4Smrg 1, border)) { 24017117f1b4Smrg return; /* error was recorded */ 24027117f1b4Smrg } 24037117f1b4Smrg 24047117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 24057117f1b4Smrg _mesa_update_state(ctx); 24067117f1b4Smrg 24077117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 24087117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 24097117f1b4Smrg _mesa_lock_texture(ctx, texObj); 24107117f1b4Smrg { 24117117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 24127117f1b4Smrg if (!texImage) { 24137117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 24147117f1b4Smrg goto out; 24157117f1b4Smrg } 24167117f1b4Smrg 24177117f1b4Smrg if (texImage->Data) { 24187117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 24197117f1b4Smrg } 24207117f1b4Smrg 24217117f1b4Smrg ASSERT(texImage->Data == NULL); 24227117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 24237117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 24247117f1b4Smrg postConvWidth, postConvHeight, 1, 24257117f1b4Smrg border, internalFormat); 24267117f1b4Smrg 24277117f1b4Smrg ASSERT(ctx->Driver.TexImage2D); 24287117f1b4Smrg 24297117f1b4Smrg /* Give the texture to the driver! <pixels> may be null! */ 24307117f1b4Smrg (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 24317117f1b4Smrg width, height, border, format, type, pixels, 24327117f1b4Smrg &ctx->Unpack, texObj, texImage); 24337117f1b4Smrg 24347117f1b4Smrg ASSERT(texImage->TexFormat); 24357117f1b4Smrg 24367117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 24377117f1b4Smrg 24387117f1b4Smrg /* state update */ 24397117f1b4Smrg texObj->Complete = GL_FALSE; 24407117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 24417117f1b4Smrg } 24427117f1b4Smrg out: 24437117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 24447117f1b4Smrg } 24457117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 24467117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 24477117f1b4Smrg ctx->Extensions.ARB_texture_cube_map) || 24487117f1b4Smrg (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 24497117f1b4Smrg ctx->Extensions.NV_texture_rectangle)) { 24507117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 24517117f1b4Smrg struct gl_texture_image *texImage; 24527117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 24537117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 24547117f1b4Smrg format, type, 2, postConvWidth, postConvHeight, 24557117f1b4Smrg 1, border)) { 24567117f1b4Smrg /* when error, clear all proxy texture image parameters */ 24577117f1b4Smrg if (texImage) 24587117f1b4Smrg clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]); 24597117f1b4Smrg } 24607117f1b4Smrg else { 24617117f1b4Smrg /* no error, set the tex image parameters */ 24627117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 24637117f1b4Smrg postConvWidth, postConvHeight, 1, 24647117f1b4Smrg border, internalFormat); 24657117f1b4Smrg texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 24667117f1b4Smrg internalFormat, format, type); 24677117f1b4Smrg } 24687117f1b4Smrg } 24697117f1b4Smrg else { 24707117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 24717117f1b4Smrg return; 24727117f1b4Smrg } 24737117f1b4Smrg} 24747117f1b4Smrg 24757117f1b4Smrg 24767117f1b4Smrg/* 24777117f1b4Smrg * Called by the API or display list executor. 24787117f1b4Smrg * Note that width and height include the border. 24797117f1b4Smrg */ 24807117f1b4Smrgvoid GLAPIENTRY 24817117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 24827117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 24837117f1b4Smrg GLint border, GLenum format, GLenum type, 24847117f1b4Smrg const GLvoid *pixels ) 24857117f1b4Smrg{ 24867117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 24877117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 24887117f1b4Smrg 24897117f1b4Smrg if (target == GL_TEXTURE_3D) { 24907117f1b4Smrg /* non-proxy target */ 24917117f1b4Smrg struct gl_texture_unit *texUnit; 24927117f1b4Smrg struct gl_texture_object *texObj; 24937117f1b4Smrg struct gl_texture_image *texImage; 24947117f1b4Smrg const GLuint face = texture_face(target); 24957117f1b4Smrg 24967117f1b4Smrg if (texture_error_check(ctx, target, level, (GLint) internalFormat, 24977117f1b4Smrg format, type, 3, width, height, depth, border)) { 24987117f1b4Smrg return; /* error was recorded */ 24997117f1b4Smrg } 25007117f1b4Smrg 25017117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 25027117f1b4Smrg _mesa_update_state(ctx); 25037117f1b4Smrg 25047117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 25057117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 25067117f1b4Smrg _mesa_lock_texture(ctx, texObj); 25077117f1b4Smrg { 25087117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 25097117f1b4Smrg if (!texImage) { 25107117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 25117117f1b4Smrg goto out; 25127117f1b4Smrg } 25137117f1b4Smrg 25147117f1b4Smrg if (texImage->Data) { 25157117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 25167117f1b4Smrg } 25177117f1b4Smrg 25187117f1b4Smrg ASSERT(texImage->Data == NULL); 25197117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 25207117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 25217117f1b4Smrg width, height, depth, 25227117f1b4Smrg border, internalFormat); 25237117f1b4Smrg 25247117f1b4Smrg ASSERT(ctx->Driver.TexImage3D); 25257117f1b4Smrg 25267117f1b4Smrg /* Give the texture to the driver! <pixels> may be null! */ 25277117f1b4Smrg (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, 25287117f1b4Smrg width, height, depth, border, format, type, 25297117f1b4Smrg pixels, &ctx->Unpack, texObj, texImage); 25307117f1b4Smrg 25317117f1b4Smrg ASSERT(texImage->TexFormat); 25327117f1b4Smrg 25337117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 25347117f1b4Smrg 25357117f1b4Smrg /* state update */ 25367117f1b4Smrg texObj->Complete = GL_FALSE; 25377117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 25387117f1b4Smrg } 25397117f1b4Smrg out: 25407117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 25417117f1b4Smrg } 25427117f1b4Smrg else if (target == GL_PROXY_TEXTURE_3D) { 25437117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 25447117f1b4Smrg struct gl_texture_image *texImage; 25457117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 25467117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 25477117f1b4Smrg format, type, 3, width, height, depth, border)) { 25487117f1b4Smrg /* when error, clear all proxy texture image parameters */ 25497117f1b4Smrg if (texImage) 25507117f1b4Smrg clear_teximage_fields(texImage); 25517117f1b4Smrg } 25527117f1b4Smrg else { 25537117f1b4Smrg /* no error, set the tex image parameters */ 25547117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 25557117f1b4Smrg depth, border, internalFormat); 25567117f1b4Smrg texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 25577117f1b4Smrg internalFormat, format, type); 25587117f1b4Smrg } 25597117f1b4Smrg } 25607117f1b4Smrg else { 25617117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 25627117f1b4Smrg return; 25637117f1b4Smrg } 25647117f1b4Smrg} 25657117f1b4Smrg 25667117f1b4Smrg 25677117f1b4Smrgvoid GLAPIENTRY 25687117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 25697117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 25707117f1b4Smrg GLint border, GLenum format, GLenum type, 25717117f1b4Smrg const GLvoid *pixels ) 25727117f1b4Smrg{ 25737117f1b4Smrg _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 25747117f1b4Smrg depth, border, format, type, pixels); 25757117f1b4Smrg} 25767117f1b4Smrg 25777117f1b4Smrg 25787117f1b4Smrg 25797117f1b4Smrgvoid GLAPIENTRY 25807117f1b4Smrg_mesa_TexSubImage1D( GLenum target, GLint level, 25817117f1b4Smrg GLint xoffset, GLsizei width, 25827117f1b4Smrg GLenum format, GLenum type, 25837117f1b4Smrg const GLvoid *pixels ) 25847117f1b4Smrg{ 25857117f1b4Smrg GLsizei postConvWidth = width; 25867117f1b4Smrg struct gl_texture_unit *texUnit; 25877117f1b4Smrg struct gl_texture_object *texObj; 25887117f1b4Smrg struct gl_texture_image *texImage = NULL; 25897117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25907117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 25917117f1b4Smrg 25927117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 25937117f1b4Smrg _mesa_update_state(ctx); 25947117f1b4Smrg 25957117f1b4Smrg /* XXX should test internal format */ 25967117f1b4Smrg if (is_color_format(format)) { 25977117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 25987117f1b4Smrg } 25997117f1b4Smrg 26007117f1b4Smrg if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 26017117f1b4Smrg postConvWidth, 1, 1, format, type)) { 26027117f1b4Smrg return; /* error was detected */ 26037117f1b4Smrg } 26047117f1b4Smrg 26057117f1b4Smrg 26067117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 26077117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 26087117f1b4Smrg assert(texObj); 26097117f1b4Smrg 26107117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26117117f1b4Smrg { 26127117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 26137117f1b4Smrg 26147117f1b4Smrg if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 26157117f1b4Smrg postConvWidth, 1, 1, format, type, texImage)) { 26167117f1b4Smrg goto out; /* error was detected */ 26177117f1b4Smrg } 26187117f1b4Smrg 26197117f1b4Smrg if (width == 0) 26207117f1b4Smrg goto out; /* no-op, not an error */ 26217117f1b4Smrg 26227117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 26237117f1b4Smrg xoffset += texImage->Border; 26247117f1b4Smrg 26257117f1b4Smrg ASSERT(ctx->Driver.TexSubImage1D); 26267117f1b4Smrg (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 26277117f1b4Smrg format, type, pixels, &ctx->Unpack, 26287117f1b4Smrg texObj, texImage); 26297117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 26307117f1b4Smrg } 26317117f1b4Smrg out: 26327117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 26337117f1b4Smrg} 26347117f1b4Smrg 26357117f1b4Smrg 26367117f1b4Smrgvoid GLAPIENTRY 26377117f1b4Smrg_mesa_TexSubImage2D( GLenum target, GLint level, 26387117f1b4Smrg GLint xoffset, GLint yoffset, 26397117f1b4Smrg GLsizei width, GLsizei height, 26407117f1b4Smrg GLenum format, GLenum type, 26417117f1b4Smrg const GLvoid *pixels ) 26427117f1b4Smrg{ 26437117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 26447117f1b4Smrg struct gl_texture_unit *texUnit; 26457117f1b4Smrg struct gl_texture_object *texObj; 26467117f1b4Smrg struct gl_texture_image *texImage; 26477117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 26487117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 26497117f1b4Smrg 26507117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 26517117f1b4Smrg _mesa_update_state(ctx); 26527117f1b4Smrg 26537117f1b4Smrg /* XXX should test internal format */ 26547117f1b4Smrg if (is_color_format(format)) { 26557117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 26567117f1b4Smrg &postConvHeight); 26577117f1b4Smrg } 26587117f1b4Smrg 26597117f1b4Smrg if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 26607117f1b4Smrg postConvWidth, postConvHeight, 1, format, type)) { 26617117f1b4Smrg return; /* error was detected */ 26627117f1b4Smrg } 26637117f1b4Smrg 26647117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 26657117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 26667117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26677117f1b4Smrg { 26687117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 26697117f1b4Smrg 26707117f1b4Smrg if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 26717117f1b4Smrg postConvWidth, postConvHeight, 1, format, type, 26727117f1b4Smrg texImage)) { 26737117f1b4Smrg goto out; /* error was detected */ 26747117f1b4Smrg } 26757117f1b4Smrg 26767117f1b4Smrg if (width == 0 || height == 0) 26777117f1b4Smrg goto out; /* no-op, not an error */ 26787117f1b4Smrg 26797117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 26807117f1b4Smrg xoffset += texImage->Border; 26817117f1b4Smrg yoffset += texImage->Border; 26827117f1b4Smrg 26837117f1b4Smrg ASSERT(ctx->Driver.TexSubImage2D); 26847117f1b4Smrg (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 26857117f1b4Smrg width, height, format, type, pixels, 26867117f1b4Smrg &ctx->Unpack, texObj, texImage); 26877117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 26887117f1b4Smrg } 26897117f1b4Smrg out: 26907117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 26917117f1b4Smrg} 26927117f1b4Smrg 26937117f1b4Smrg 26947117f1b4Smrg 26957117f1b4Smrgvoid GLAPIENTRY 26967117f1b4Smrg_mesa_TexSubImage3D( GLenum target, GLint level, 26977117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 26987117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 26997117f1b4Smrg GLenum format, GLenum type, 27007117f1b4Smrg const GLvoid *pixels ) 27017117f1b4Smrg{ 27027117f1b4Smrg struct gl_texture_unit *texUnit; 27037117f1b4Smrg struct gl_texture_object *texObj; 27047117f1b4Smrg struct gl_texture_image *texImage; 27057117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27067117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 27077117f1b4Smrg 27087117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 27097117f1b4Smrg _mesa_update_state(ctx); 27107117f1b4Smrg 27117117f1b4Smrg if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 27127117f1b4Smrg width, height, depth, format, type)) { 27137117f1b4Smrg return; /* error was detected */ 27147117f1b4Smrg } 27157117f1b4Smrg 27167117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 27177117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 27187117f1b4Smrg 27197117f1b4Smrg _mesa_lock_texture(ctx, texObj); 27207117f1b4Smrg { 27217117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 27227117f1b4Smrg 27237117f1b4Smrg if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, 27247117f1b4Smrg width, height, depth, format, type, texImage)) { 27257117f1b4Smrg goto out; /* error was detected */ 27267117f1b4Smrg } 27277117f1b4Smrg 27287117f1b4Smrg if (width == 0 || height == 0 || height == 0) 27297117f1b4Smrg goto out; /* no-op, not an error */ 27307117f1b4Smrg 27317117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 27327117f1b4Smrg xoffset += texImage->Border; 27337117f1b4Smrg yoffset += texImage->Border; 27347117f1b4Smrg zoffset += texImage->Border; 27357117f1b4Smrg 27367117f1b4Smrg ASSERT(ctx->Driver.TexSubImage3D); 27377117f1b4Smrg (*ctx->Driver.TexSubImage3D)(ctx, target, level, 27387117f1b4Smrg xoffset, yoffset, zoffset, 27397117f1b4Smrg width, height, depth, 27407117f1b4Smrg format, type, pixels, 27417117f1b4Smrg &ctx->Unpack, texObj, texImage ); 27427117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 27437117f1b4Smrg } 27447117f1b4Smrg out: 27457117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 27467117f1b4Smrg} 27477117f1b4Smrg 27487117f1b4Smrg 27497117f1b4Smrg 27507117f1b4Smrgvoid GLAPIENTRY 27517117f1b4Smrg_mesa_CopyTexImage1D( GLenum target, GLint level, 27527117f1b4Smrg GLenum internalFormat, 27537117f1b4Smrg GLint x, GLint y, 27547117f1b4Smrg GLsizei width, GLint border ) 27557117f1b4Smrg{ 27567117f1b4Smrg struct gl_texture_unit *texUnit; 27577117f1b4Smrg struct gl_texture_object *texObj; 27587117f1b4Smrg struct gl_texture_image *texImage; 27597117f1b4Smrg GLsizei postConvWidth = width; 27607117f1b4Smrg const GLuint face = texture_face(target); 27617117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27627117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 27637117f1b4Smrg 27647117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 27657117f1b4Smrg _mesa_update_state(ctx); 27667117f1b4Smrg 27677117f1b4Smrg if (is_color_format(internalFormat)) { 27687117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 27697117f1b4Smrg } 27707117f1b4Smrg 27717117f1b4Smrg if (copytexture_error_check(ctx, 1, target, level, internalFormat, 27727117f1b4Smrg postConvWidth, 1, border)) 27737117f1b4Smrg return; 27747117f1b4Smrg 27757117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 27767117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 27777117f1b4Smrg _mesa_lock_texture(ctx, texObj); 27787117f1b4Smrg { 27797117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 27807117f1b4Smrg if (!texImage) { 27817117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 27827117f1b4Smrg goto out; 27837117f1b4Smrg } 27847117f1b4Smrg 27857117f1b4Smrg if (texImage->Data) { 27867117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 27877117f1b4Smrg } 27887117f1b4Smrg 27897117f1b4Smrg ASSERT(texImage->Data == NULL); 27907117f1b4Smrg 27917117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 27927117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 27937117f1b4Smrg border, internalFormat); 27947117f1b4Smrg 27957117f1b4Smrg 27967117f1b4Smrg ASSERT(ctx->Driver.CopyTexImage1D); 27977117f1b4Smrg (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 27987117f1b4Smrg x, y, width, border); 27997117f1b4Smrg 28007117f1b4Smrg ASSERT(texImage->TexFormat); 28017117f1b4Smrg 28027117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 28037117f1b4Smrg 28047117f1b4Smrg /* state update */ 28057117f1b4Smrg texObj->Complete = GL_FALSE; 28067117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 28077117f1b4Smrg } 28087117f1b4Smrg out: 28097117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28107117f1b4Smrg} 28117117f1b4Smrg 28127117f1b4Smrg 28137117f1b4Smrg 28147117f1b4Smrgvoid GLAPIENTRY 28157117f1b4Smrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 28167117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height, 28177117f1b4Smrg GLint border ) 28187117f1b4Smrg{ 28197117f1b4Smrg struct gl_texture_unit *texUnit; 28207117f1b4Smrg struct gl_texture_object *texObj; 28217117f1b4Smrg struct gl_texture_image *texImage; 28227117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 28237117f1b4Smrg const GLuint face = texture_face(target); 28247117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28257117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28267117f1b4Smrg 28277117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 28287117f1b4Smrg _mesa_update_state(ctx); 28297117f1b4Smrg 28307117f1b4Smrg if (is_color_format(internalFormat)) { 28317117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 28327117f1b4Smrg &postConvHeight); 28337117f1b4Smrg } 28347117f1b4Smrg 28357117f1b4Smrg if (copytexture_error_check(ctx, 2, target, level, internalFormat, 28367117f1b4Smrg postConvWidth, postConvHeight, border)) 28377117f1b4Smrg return; 28387117f1b4Smrg 28397117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 28407117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 28417117f1b4Smrg 28427117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28437117f1b4Smrg { 28447117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 28457117f1b4Smrg 28467117f1b4Smrg if (!texImage) { 28477117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 28487117f1b4Smrg goto out; 28497117f1b4Smrg } 28507117f1b4Smrg 28517117f1b4Smrg if (texImage->Data) { 28527117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 28537117f1b4Smrg } 28547117f1b4Smrg 28557117f1b4Smrg ASSERT(texImage->Data == NULL); 28567117f1b4Smrg 28577117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 28587117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 28597117f1b4Smrg postConvWidth, postConvHeight, 1, 28607117f1b4Smrg border, internalFormat); 28617117f1b4Smrg 28627117f1b4Smrg ASSERT(ctx->Driver.CopyTexImage2D); 28637117f1b4Smrg (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 28647117f1b4Smrg x, y, width, height, border); 28657117f1b4Smrg 28667117f1b4Smrg ASSERT(texImage->TexFormat); 28677117f1b4Smrg 28687117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 28697117f1b4Smrg 28707117f1b4Smrg /* state update */ 28717117f1b4Smrg texObj->Complete = GL_FALSE; 28727117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 28737117f1b4Smrg } 28747117f1b4Smrg out: 28757117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28767117f1b4Smrg} 28777117f1b4Smrg 28787117f1b4Smrg 28797117f1b4Smrgvoid GLAPIENTRY 28807117f1b4Smrg_mesa_CopyTexSubImage1D( GLenum target, GLint level, 28817117f1b4Smrg GLint xoffset, GLint x, GLint y, GLsizei width ) 28827117f1b4Smrg{ 28837117f1b4Smrg struct gl_texture_unit *texUnit; 28847117f1b4Smrg struct gl_texture_object *texObj; 28857117f1b4Smrg struct gl_texture_image *texImage; 28867117f1b4Smrg GLsizei postConvWidth = width; 28877117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28887117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28897117f1b4Smrg 28907117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 28917117f1b4Smrg _mesa_update_state(ctx); 28927117f1b4Smrg 28937117f1b4Smrg /* XXX should test internal format */ 28947117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 28957117f1b4Smrg 28967117f1b4Smrg if (copytexsubimage_error_check(ctx, 1, target, level, 28977117f1b4Smrg xoffset, 0, 0, postConvWidth, 1)) 28987117f1b4Smrg return; 28997117f1b4Smrg 29007117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 29017117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 29027117f1b4Smrg 29037117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29047117f1b4Smrg { 29057117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 29067117f1b4Smrg 29077117f1b4Smrg if (copytexsubimage_error_check2(ctx, 1, target, level, 29087117f1b4Smrg xoffset, 0, 0, postConvWidth, 1, 29097117f1b4Smrg texImage)) 29107117f1b4Smrg goto out; 29117117f1b4Smrg 29127117f1b4Smrg 29137117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 29147117f1b4Smrg xoffset += texImage->Border; 29157117f1b4Smrg 29167117f1b4Smrg ASSERT(ctx->Driver.CopyTexSubImage1D); 29177117f1b4Smrg (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width); 29187117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 29197117f1b4Smrg } 29207117f1b4Smrg out: 29217117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29227117f1b4Smrg} 29237117f1b4Smrg 29247117f1b4Smrg 29257117f1b4Smrg 29267117f1b4Smrgvoid GLAPIENTRY 29277117f1b4Smrg_mesa_CopyTexSubImage2D( GLenum target, GLint level, 29287117f1b4Smrg GLint xoffset, GLint yoffset, 29297117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 29307117f1b4Smrg{ 29317117f1b4Smrg struct gl_texture_unit *texUnit; 29327117f1b4Smrg struct gl_texture_object *texObj; 29337117f1b4Smrg struct gl_texture_image *texImage; 29347117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 29357117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29367117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29377117f1b4Smrg 29387117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 29397117f1b4Smrg _mesa_update_state(ctx); 29407117f1b4Smrg 29417117f1b4Smrg /* XXX should test internal format */ 29427117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 29437117f1b4Smrg 29447117f1b4Smrg if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 29457117f1b4Smrg postConvWidth, postConvHeight)) 29467117f1b4Smrg return; 29477117f1b4Smrg 29487117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 29497117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 29507117f1b4Smrg 29517117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29527117f1b4Smrg { 29537117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 29547117f1b4Smrg 29557117f1b4Smrg if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 29567117f1b4Smrg postConvWidth, postConvHeight, texImage)) 29577117f1b4Smrg goto out; 29587117f1b4Smrg 29597117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 29607117f1b4Smrg xoffset += texImage->Border; 29617117f1b4Smrg yoffset += texImage->Border; 29627117f1b4Smrg 29637117f1b4Smrg ASSERT(ctx->Driver.CopyTexSubImage2D); 29647117f1b4Smrg (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, 29657117f1b4Smrg xoffset, yoffset, x, y, width, height); 29667117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 29677117f1b4Smrg } 29687117f1b4Smrg out: 29697117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29707117f1b4Smrg} 29717117f1b4Smrg 29727117f1b4Smrg 29737117f1b4Smrg 29747117f1b4Smrgvoid GLAPIENTRY 29757117f1b4Smrg_mesa_CopyTexSubImage3D( GLenum target, GLint level, 29767117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 29777117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 29787117f1b4Smrg{ 29797117f1b4Smrg struct gl_texture_unit *texUnit; 29807117f1b4Smrg struct gl_texture_object *texObj; 29817117f1b4Smrg struct gl_texture_image *texImage; 29827117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 29837117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29847117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29857117f1b4Smrg 29867117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 29877117f1b4Smrg _mesa_update_state(ctx); 29887117f1b4Smrg 29897117f1b4Smrg /* XXX should test internal format */ 29907117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 29917117f1b4Smrg 29927117f1b4Smrg if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset, 29937117f1b4Smrg zoffset, postConvWidth, postConvHeight)) 29947117f1b4Smrg return; 29957117f1b4Smrg 29967117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 29977117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 29987117f1b4Smrg 29997117f1b4Smrg _mesa_lock_texture(ctx, texObj); 30007117f1b4Smrg { 30017117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 30027117f1b4Smrg 30037117f1b4Smrg if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 30047117f1b4Smrg zoffset, postConvWidth, postConvHeight, 30057117f1b4Smrg texImage)) 30067117f1b4Smrg goto out; 30077117f1b4Smrg 30087117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 30097117f1b4Smrg xoffset += texImage->Border; 30107117f1b4Smrg yoffset += texImage->Border; 30117117f1b4Smrg zoffset += texImage->Border; 30127117f1b4Smrg 30137117f1b4Smrg ASSERT(ctx->Driver.CopyTexSubImage3D); 30147117f1b4Smrg (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, 30157117f1b4Smrg xoffset, yoffset, zoffset, 30167117f1b4Smrg x, y, width, height); 30177117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 30187117f1b4Smrg } 30197117f1b4Smrg out: 30207117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 30217117f1b4Smrg} 30227117f1b4Smrg 30237117f1b4Smrg 30247117f1b4Smrg 30257117f1b4Smrg 30267117f1b4Smrg/**********************************************************************/ 30277117f1b4Smrg/****** Compressed Textures ******/ 30287117f1b4Smrg/**********************************************************************/ 30297117f1b4Smrg 30307117f1b4Smrg 30317117f1b4Smrg/** 30327117f1b4Smrg * Error checking for glCompressedTexImage[123]D(). 30337117f1b4Smrg * \return error code or GL_NO_ERROR. 30347117f1b4Smrg */ 30357117f1b4Smrgstatic GLenum 30367117f1b4Smrgcompressed_texture_error_check(GLcontext *ctx, GLint dimensions, 30377117f1b4Smrg GLenum target, GLint level, 30387117f1b4Smrg GLenum internalFormat, GLsizei width, 30397117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 30407117f1b4Smrg GLsizei imageSize) 30417117f1b4Smrg{ 30427117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 30437117f1b4Smrg 30447117f1b4Smrg if (dimensions == 1) { 30457117f1b4Smrg /* 1D compressed textures not allowed */ 30467117f1b4Smrg return GL_INVALID_ENUM; 30477117f1b4Smrg } 30487117f1b4Smrg else if (dimensions == 2) { 30497117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 30507117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 30517117f1b4Smrg } 30527117f1b4Smrg else if (target == GL_TEXTURE_2D) { 30537117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 30547117f1b4Smrg } 30557117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 30567117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 30577117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30587117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 30597117f1b4Smrg } 30607117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 30617117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 30627117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 30637117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30647117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 30657117f1b4Smrg } 30667117f1b4Smrg else { 30677117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30687117f1b4Smrg } 30697117f1b4Smrg } 30707117f1b4Smrg else if (dimensions == 3) { 30717117f1b4Smrg /* 3D compressed textures not allowed */ 30727117f1b4Smrg return GL_INVALID_ENUM; 30737117f1b4Smrg } 30747117f1b4Smrg 30757117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 30767117f1b4Smrg 30777117f1b4Smrg /* This will detect any invalid internalFormat value */ 30787117f1b4Smrg if (!is_compressed_format(ctx, internalFormat)) 30797117f1b4Smrg return GL_INVALID_ENUM; 30807117f1b4Smrg 30817117f1b4Smrg /* This should really never fail */ 30827117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) 30837117f1b4Smrg return GL_INVALID_ENUM; 30847117f1b4Smrg 30857117f1b4Smrg if (border != 0) 30867117f1b4Smrg return GL_INVALID_VALUE; 30877117f1b4Smrg 30887117f1b4Smrg /* 30897117f1b4Smrg * XXX We should probably use the proxy texture error check function here. 30907117f1b4Smrg */ 30917117f1b4Smrg if (width < 1 || width > maxTextureSize || 30927117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1)) 30937117f1b4Smrg return GL_INVALID_VALUE; 30947117f1b4Smrg 30957117f1b4Smrg if ((height < 1 || height > maxTextureSize || 30967117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1)) 30977117f1b4Smrg && dimensions > 1) 30987117f1b4Smrg return GL_INVALID_VALUE; 30997117f1b4Smrg 31007117f1b4Smrg if ((depth < 1 || depth > maxTextureSize || 31017117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1)) 31027117f1b4Smrg && dimensions > 2) 31037117f1b4Smrg return GL_INVALID_VALUE; 31047117f1b4Smrg 31057117f1b4Smrg /* For cube map, width must equal height */ 31067117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 31077117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 31087117f1b4Smrg return GL_INVALID_VALUE; 31097117f1b4Smrg 31107117f1b4Smrg if (level < 0 || level >= maxLevels) 31117117f1b4Smrg return GL_INVALID_VALUE; 31127117f1b4Smrg 31137117f1b4Smrg expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 31147117f1b4Smrg depth, internalFormat); 31157117f1b4Smrg if (expectedSize != imageSize) 31167117f1b4Smrg return GL_INVALID_VALUE; 31177117f1b4Smrg 31187117f1b4Smrg#if FEATURE_EXT_texture_sRGB 31197117f1b4Smrg if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 31207117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 31217117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 31227117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 31237117f1b4Smrg && border != 0) { 31247117f1b4Smrg return GL_INVALID_OPERATION; 31257117f1b4Smrg } 31267117f1b4Smrg#endif 31277117f1b4Smrg 31287117f1b4Smrg return GL_NO_ERROR; 31297117f1b4Smrg} 31307117f1b4Smrg 31317117f1b4Smrg 31327117f1b4Smrg/** 31337117f1b4Smrg * Error checking for glCompressedTexSubImage[123]D(). 31347117f1b4Smrg * \warning There are some bad assumptions here about the size of compressed 31357117f1b4Smrg * texture tiles (multiple of 4) used to test the validity of the 31367117f1b4Smrg * offset and size parameters. 31377117f1b4Smrg * \return error code or GL_NO_ERROR. 31387117f1b4Smrg */ 31397117f1b4Smrgstatic GLenum 31407117f1b4Smrgcompressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 31417117f1b4Smrg GLenum target, GLint level, 31427117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 31437117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 31447117f1b4Smrg GLenum format, GLsizei imageSize) 31457117f1b4Smrg{ 31467117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 31477117f1b4Smrg (void) zoffset; 31487117f1b4Smrg 31497117f1b4Smrg if (dimensions == 1) { 31507117f1b4Smrg /* 1D compressed textures not allowed */ 31517117f1b4Smrg return GL_INVALID_ENUM; 31527117f1b4Smrg } 31537117f1b4Smrg else if (dimensions == 2) { 31547117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 31557117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 31567117f1b4Smrg } 31577117f1b4Smrg else if (target == GL_TEXTURE_2D) { 31587117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 31597117f1b4Smrg } 31607117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 31617117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 31627117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31637117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 31647117f1b4Smrg } 31657117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 31667117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 31677117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 31687117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31697117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 31707117f1b4Smrg } 31717117f1b4Smrg else { 31727117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31737117f1b4Smrg } 31747117f1b4Smrg } 31757117f1b4Smrg else if (dimensions == 3) { 31767117f1b4Smrg /* 3D compressed textures not allowed */ 31777117f1b4Smrg return GL_INVALID_ENUM; 31787117f1b4Smrg } 31797117f1b4Smrg 31807117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 31817117f1b4Smrg 31827117f1b4Smrg /* this will catch any invalid compressed format token */ 31837117f1b4Smrg if (!is_compressed_format(ctx, format)) 31847117f1b4Smrg return GL_INVALID_ENUM; 31857117f1b4Smrg 31867117f1b4Smrg if (width < 1 || width > maxTextureSize) 31877117f1b4Smrg return GL_INVALID_VALUE; 31887117f1b4Smrg 31897117f1b4Smrg if ((height < 1 || height > maxTextureSize) 31907117f1b4Smrg && dimensions > 1) 31917117f1b4Smrg return GL_INVALID_VALUE; 31927117f1b4Smrg 31937117f1b4Smrg if (level < 0 || level >= maxLevels) 31947117f1b4Smrg return GL_INVALID_VALUE; 31957117f1b4Smrg 31967117f1b4Smrg /* XXX these tests are specific to the compressed format. 31977117f1b4Smrg * this code should be generalized in some way. 31987117f1b4Smrg */ 31997117f1b4Smrg if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 32007117f1b4Smrg return GL_INVALID_VALUE; 32017117f1b4Smrg 32027117f1b4Smrg if ((width & 3) != 0 && width != 2 && width != 1) 32037117f1b4Smrg return GL_INVALID_VALUE; 32047117f1b4Smrg 32057117f1b4Smrg if ((height & 3) != 0 && height != 2 && height != 1) 32067117f1b4Smrg return GL_INVALID_VALUE; 32077117f1b4Smrg 32087117f1b4Smrg expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 32097117f1b4Smrg depth, format); 32107117f1b4Smrg if (expectedSize != imageSize) 32117117f1b4Smrg return GL_INVALID_VALUE; 32127117f1b4Smrg 32137117f1b4Smrg return GL_NO_ERROR; 32147117f1b4Smrg} 32157117f1b4Smrg 32167117f1b4Smrg 32177117f1b4Smrg 32187117f1b4Smrgvoid GLAPIENTRY 32197117f1b4Smrg_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 32207117f1b4Smrg GLenum internalFormat, GLsizei width, 32217117f1b4Smrg GLint border, GLsizei imageSize, 32227117f1b4Smrg const GLvoid *data) 32237117f1b4Smrg{ 32247117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 32257117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 32267117f1b4Smrg 32277117f1b4Smrg if (target == GL_TEXTURE_1D) { 32287117f1b4Smrg /* non-proxy target */ 32297117f1b4Smrg struct gl_texture_unit *texUnit; 32307117f1b4Smrg struct gl_texture_object *texObj; 32317117f1b4Smrg struct gl_texture_image *texImage; 32327117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 32337117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 32347117f1b4Smrg if (error) { 32357117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage1D"); 32367117f1b4Smrg return; 32377117f1b4Smrg } 32387117f1b4Smrg 32397117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 32407117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 32417117f1b4Smrg 32427117f1b4Smrg _mesa_lock_texture(ctx, texObj); 32437117f1b4Smrg { 32447117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 32457117f1b4Smrg if (!texImage) { 32467117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 32477117f1b4Smrg goto out; 32487117f1b4Smrg } 32497117f1b4Smrg 32507117f1b4Smrg if (texImage->Data) { 32517117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 32527117f1b4Smrg } 32537117f1b4Smrg ASSERT(texImage->Data == NULL); 32547117f1b4Smrg 32557117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 32567117f1b4Smrg border, internalFormat); 32577117f1b4Smrg 32587117f1b4Smrg ASSERT(ctx->Driver.CompressedTexImage1D); 32597117f1b4Smrg (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 32607117f1b4Smrg internalFormat, width, border, 32617117f1b4Smrg imageSize, data, 32627117f1b4Smrg texObj, texImage); 32637117f1b4Smrg 32647117f1b4Smrg /* state update */ 32657117f1b4Smrg texObj->Complete = GL_FALSE; 32667117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 32677117f1b4Smrg } 32687117f1b4Smrg out: 32697117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 32707117f1b4Smrg } 32717117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 32727117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 32737117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 32747117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 32757117f1b4Smrg if (!error) { 32767117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 32777117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 32787117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 32797117f1b4Smrg width, 1, 1, border); 32807117f1b4Smrg } 32817117f1b4Smrg if (error) { 32827117f1b4Smrg /* if error, clear all proxy texture image parameters */ 32837117f1b4Smrg struct gl_texture_image *texImage; 32847117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 32857117f1b4Smrg if (texImage) 32867117f1b4Smrg clear_teximage_fields(texImage); 32877117f1b4Smrg } 32887117f1b4Smrg else { 32897117f1b4Smrg /* store the teximage parameters */ 32907117f1b4Smrg struct gl_texture_unit *texUnit; 32917117f1b4Smrg struct gl_texture_object *texObj; 32927117f1b4Smrg struct gl_texture_image *texImage; 32937117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 32947117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 32957117f1b4Smrg 32967117f1b4Smrg _mesa_lock_texture(ctx, texObj); 32977117f1b4Smrg { 32987117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 32997117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 33007117f1b4Smrg border, internalFormat); 33017117f1b4Smrg } 33027117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33037117f1b4Smrg } 33047117f1b4Smrg } 33057117f1b4Smrg else { 33067117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 33077117f1b4Smrg return; 33087117f1b4Smrg } 33097117f1b4Smrg} 33107117f1b4Smrg 33117117f1b4Smrg 33127117f1b4Smrgvoid GLAPIENTRY 33137117f1b4Smrg_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 33147117f1b4Smrg GLenum internalFormat, GLsizei width, 33157117f1b4Smrg GLsizei height, GLint border, GLsizei imageSize, 33167117f1b4Smrg const GLvoid *data) 33177117f1b4Smrg{ 33187117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 33197117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 33207117f1b4Smrg 33217117f1b4Smrg if (target == GL_TEXTURE_2D || 33227117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 33237117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 33247117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 33257117f1b4Smrg /* non-proxy target */ 33267117f1b4Smrg struct gl_texture_unit *texUnit; 33277117f1b4Smrg struct gl_texture_object *texObj; 33287117f1b4Smrg struct gl_texture_image *texImage; 33297117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 33307117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 33317117f1b4Smrg if (error) { 33327117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage2D"); 33337117f1b4Smrg return; 33347117f1b4Smrg } 33357117f1b4Smrg 33367117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 33377117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 33387117f1b4Smrg 33397117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33407117f1b4Smrg { 33417117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 33427117f1b4Smrg if (!texImage) { 33437117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 33447117f1b4Smrg goto out; 33457117f1b4Smrg } 33467117f1b4Smrg 33477117f1b4Smrg if (texImage->Data) { 33487117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 33497117f1b4Smrg } 33507117f1b4Smrg ASSERT(texImage->Data == NULL); 33517117f1b4Smrg 33527117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 33537117f1b4Smrg border, internalFormat); 33547117f1b4Smrg 33557117f1b4Smrg ASSERT(ctx->Driver.CompressedTexImage2D); 33567117f1b4Smrg (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 33577117f1b4Smrg internalFormat, width, height, 33587117f1b4Smrg border, imageSize, data, 33597117f1b4Smrg texObj, texImage); 33607117f1b4Smrg 33617117f1b4Smrg /* state update */ 33627117f1b4Smrg texObj->Complete = GL_FALSE; 33637117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 33647117f1b4Smrg } 33657117f1b4Smrg out: 33667117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33677117f1b4Smrg } 33687117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 33697117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 33707117f1b4Smrg ctx->Extensions.ARB_texture_cube_map)) { 33717117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 33727117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 33737117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 33747117f1b4Smrg if (!error) { 33757117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 33767117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 33777117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 33787117f1b4Smrg width, height, 1, border); 33797117f1b4Smrg } 33807117f1b4Smrg if (error) { 33817117f1b4Smrg /* if error, clear all proxy texture image parameters */ 33827117f1b4Smrg struct gl_texture_image *texImage; 33837117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 33847117f1b4Smrg if (texImage) 33857117f1b4Smrg clear_teximage_fields(texImage); 33867117f1b4Smrg } 33877117f1b4Smrg else { 33887117f1b4Smrg /* store the teximage parameters */ 33897117f1b4Smrg struct gl_texture_unit *texUnit; 33907117f1b4Smrg struct gl_texture_object *texObj; 33917117f1b4Smrg struct gl_texture_image *texImage; 33927117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 33937117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 33947117f1b4Smrg 33957117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33967117f1b4Smrg { 33977117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 33987117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 33997117f1b4Smrg border, internalFormat); 34007117f1b4Smrg } 34017117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34027117f1b4Smrg } 34037117f1b4Smrg } 34047117f1b4Smrg else { 34057117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 34067117f1b4Smrg return; 34077117f1b4Smrg } 34087117f1b4Smrg} 34097117f1b4Smrg 34107117f1b4Smrg 34117117f1b4Smrgvoid GLAPIENTRY 34127117f1b4Smrg_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 34137117f1b4Smrg GLenum internalFormat, GLsizei width, 34147117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 34157117f1b4Smrg GLsizei imageSize, const GLvoid *data) 34167117f1b4Smrg{ 34177117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 34187117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 34197117f1b4Smrg 34207117f1b4Smrg if (target == GL_TEXTURE_3D) { 34217117f1b4Smrg /* non-proxy target */ 34227117f1b4Smrg struct gl_texture_unit *texUnit; 34237117f1b4Smrg struct gl_texture_object *texObj; 34247117f1b4Smrg struct gl_texture_image *texImage; 34257117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 34267117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 34277117f1b4Smrg if (error) { 34287117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage3D"); 34297117f1b4Smrg return; 34307117f1b4Smrg } 34317117f1b4Smrg 34327117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 34337117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 34347117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34357117f1b4Smrg { 34367117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 34377117f1b4Smrg if (!texImage) { 34387117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 34397117f1b4Smrg goto out; 34407117f1b4Smrg } 34417117f1b4Smrg 34427117f1b4Smrg if (texImage->Data) { 34437117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 34447117f1b4Smrg } 34457117f1b4Smrg ASSERT(texImage->Data == NULL); 34467117f1b4Smrg 34477117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, 34487117f1b4Smrg border, internalFormat); 34497117f1b4Smrg 34507117f1b4Smrg ASSERT(ctx->Driver.CompressedTexImage3D); 34517117f1b4Smrg (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 34527117f1b4Smrg internalFormat, 34537117f1b4Smrg width, height, depth, 34547117f1b4Smrg border, imageSize, data, 34557117f1b4Smrg texObj, texImage); 34567117f1b4Smrg 34577117f1b4Smrg /* state update */ 34587117f1b4Smrg texObj->Complete = GL_FALSE; 34597117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 34607117f1b4Smrg } 34617117f1b4Smrg out: 34627117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34637117f1b4Smrg } 34647117f1b4Smrg else if (target == GL_PROXY_TEXTURE_3D) { 34657117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 34667117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 34677117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 34687117f1b4Smrg if (!error) { 34697117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 34707117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 34717117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 34727117f1b4Smrg width, height, depth, border); 34737117f1b4Smrg } 34747117f1b4Smrg if (error) { 34757117f1b4Smrg /* if error, clear all proxy texture image parameters */ 34767117f1b4Smrg struct gl_texture_image *texImage; 34777117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 34787117f1b4Smrg if (texImage) 34797117f1b4Smrg clear_teximage_fields(texImage); 34807117f1b4Smrg } 34817117f1b4Smrg else { 34827117f1b4Smrg /* store the teximage parameters */ 34837117f1b4Smrg struct gl_texture_unit *texUnit; 34847117f1b4Smrg struct gl_texture_object *texObj; 34857117f1b4Smrg struct gl_texture_image *texImage; 34867117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 34877117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 34887117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34897117f1b4Smrg { 34907117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 34917117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 34927117f1b4Smrg depth, border, internalFormat); 34937117f1b4Smrg } 34947117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34957117f1b4Smrg } 34967117f1b4Smrg } 34977117f1b4Smrg else { 34987117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 34997117f1b4Smrg return; 35007117f1b4Smrg } 35017117f1b4Smrg} 35027117f1b4Smrg 35037117f1b4Smrg 35047117f1b4Smrgvoid GLAPIENTRY 35057117f1b4Smrg_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 35067117f1b4Smrg GLsizei width, GLenum format, 35077117f1b4Smrg GLsizei imageSize, const GLvoid *data) 35087117f1b4Smrg{ 35097117f1b4Smrg struct gl_texture_unit *texUnit; 35107117f1b4Smrg struct gl_texture_object *texObj; 35117117f1b4Smrg struct gl_texture_image *texImage; 35127117f1b4Smrg GLenum error; 35137117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35147117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 35157117f1b4Smrg 35167117f1b4Smrg error = compressed_subtexture_error_check(ctx, 1, target, level, 35177117f1b4Smrg xoffset, 0, 0, /* pos */ 35187117f1b4Smrg width, 1, 1, /* size */ 35197117f1b4Smrg format, imageSize); 35207117f1b4Smrg if (error) { 35217117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 35227117f1b4Smrg return; 35237117f1b4Smrg } 35247117f1b4Smrg 35257117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 35267117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 35277117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35287117f1b4Smrg { 35297117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 35307117f1b4Smrg assert(texImage); 35317117f1b4Smrg 35327117f1b4Smrg if ((GLint) format != texImage->InternalFormat) { 35337117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 35347117f1b4Smrg "glCompressedTexSubImage1D(format)"); 35357117f1b4Smrg goto out; 35367117f1b4Smrg } 35377117f1b4Smrg 35387117f1b4Smrg if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { 35397117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); 35407117f1b4Smrg goto out; 35417117f1b4Smrg } 35427117f1b4Smrg 35437117f1b4Smrg if (width == 0) 35447117f1b4Smrg goto out; /* no-op, not an error */ 35457117f1b4Smrg 35467117f1b4Smrg if (ctx->Driver.CompressedTexSubImage1D) { 35477117f1b4Smrg (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 35487117f1b4Smrg xoffset, width, 35497117f1b4Smrg format, imageSize, data, 35507117f1b4Smrg texObj, texImage); 35517117f1b4Smrg } 35527117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 35537117f1b4Smrg } 35547117f1b4Smrg out: 35557117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35567117f1b4Smrg} 35577117f1b4Smrg 35587117f1b4Smrg 35597117f1b4Smrgvoid GLAPIENTRY 35607117f1b4Smrg_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 35617117f1b4Smrg GLint yoffset, GLsizei width, GLsizei height, 35627117f1b4Smrg GLenum format, GLsizei imageSize, 35637117f1b4Smrg const GLvoid *data) 35647117f1b4Smrg{ 35657117f1b4Smrg struct gl_texture_unit *texUnit; 35667117f1b4Smrg struct gl_texture_object *texObj; 35677117f1b4Smrg struct gl_texture_image *texImage; 35687117f1b4Smrg GLenum error; 35697117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35707117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 35717117f1b4Smrg 35727117f1b4Smrg error = compressed_subtexture_error_check(ctx, 2, target, level, 35737117f1b4Smrg xoffset, yoffset, 0, /* pos */ 35747117f1b4Smrg width, height, 1, /* size */ 35757117f1b4Smrg format, imageSize); 35767117f1b4Smrg if (error) { 35777117f1b4Smrg /* XXX proxy target? */ 35787117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 35797117f1b4Smrg return; 35807117f1b4Smrg } 35817117f1b4Smrg 35827117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 35837117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 35847117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35857117f1b4Smrg { 35867117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 35877117f1b4Smrg assert(texImage); 35887117f1b4Smrg 35897117f1b4Smrg if ((GLint) format != texImage->InternalFormat) { 35907117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 35917117f1b4Smrg "glCompressedTexSubImage2D(format)"); 35927117f1b4Smrg goto out; 35937117f1b4Smrg } 35947117f1b4Smrg 35957117f1b4Smrg if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 35967117f1b4Smrg ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { 35977117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 35987117f1b4Smrg goto out; 35997117f1b4Smrg } 36007117f1b4Smrg 36017117f1b4Smrg if (width == 0 || height == 0) 36027117f1b4Smrg goto out; /* no-op, not an error */ 36037117f1b4Smrg 36047117f1b4Smrg if (ctx->Driver.CompressedTexSubImage2D) { 36057117f1b4Smrg (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 36067117f1b4Smrg xoffset, yoffset, width, height, 36077117f1b4Smrg format, imageSize, data, 36087117f1b4Smrg texObj, texImage); 36097117f1b4Smrg } 36107117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 36117117f1b4Smrg } 36127117f1b4Smrg out: 36137117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36147117f1b4Smrg} 36157117f1b4Smrg 36167117f1b4Smrg 36177117f1b4Smrgvoid GLAPIENTRY 36187117f1b4Smrg_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 36197117f1b4Smrg GLint yoffset, GLint zoffset, GLsizei width, 36207117f1b4Smrg GLsizei height, GLsizei depth, GLenum format, 36217117f1b4Smrg GLsizei imageSize, const GLvoid *data) 36227117f1b4Smrg{ 36237117f1b4Smrg struct gl_texture_unit *texUnit; 36247117f1b4Smrg struct gl_texture_object *texObj; 36257117f1b4Smrg struct gl_texture_image *texImage; 36267117f1b4Smrg GLenum error; 36277117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 36287117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 36297117f1b4Smrg 36307117f1b4Smrg error = compressed_subtexture_error_check(ctx, 3, target, level, 36317117f1b4Smrg xoffset, yoffset, zoffset,/*pos*/ 36327117f1b4Smrg width, height, depth, /*size*/ 36337117f1b4Smrg format, imageSize); 36347117f1b4Smrg if (error) { 36357117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 36367117f1b4Smrg return; 36377117f1b4Smrg } 36387117f1b4Smrg 36397117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 36407117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 36417117f1b4Smrg _mesa_lock_texture(ctx, texObj); 36427117f1b4Smrg { 36437117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 36447117f1b4Smrg assert(texImage); 36457117f1b4Smrg 36467117f1b4Smrg if ((GLint) format != texImage->InternalFormat) { 36477117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 36487117f1b4Smrg "glCompressedTexSubImage3D(format)"); 36497117f1b4Smrg goto out; 36507117f1b4Smrg } 36517117f1b4Smrg 36527117f1b4Smrg if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 36537117f1b4Smrg ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || 36547117f1b4Smrg ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { 36557117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 36567117f1b4Smrg goto out; 36577117f1b4Smrg } 36587117f1b4Smrg 36597117f1b4Smrg if (width == 0 || height == 0 || depth == 0) 36607117f1b4Smrg goto out; /* no-op, not an error */ 36617117f1b4Smrg 36627117f1b4Smrg if (ctx->Driver.CompressedTexSubImage3D) { 36637117f1b4Smrg (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 36647117f1b4Smrg xoffset, yoffset, zoffset, 36657117f1b4Smrg width, height, depth, 36667117f1b4Smrg format, imageSize, data, 36677117f1b4Smrg texObj, texImage); 36687117f1b4Smrg } 36697117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 36707117f1b4Smrg } 36717117f1b4Smrg out: 36727117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36737117f1b4Smrg} 36747117f1b4Smrg 36757117f1b4Smrg 36767117f1b4Smrgvoid GLAPIENTRY 36777117f1b4Smrg_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 36787117f1b4Smrg{ 36797117f1b4Smrg const struct gl_texture_unit *texUnit; 36807117f1b4Smrg struct gl_texture_object *texObj; 36817117f1b4Smrg struct gl_texture_image *texImage; 36827117f1b4Smrg GLint maxLevels; 36837117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 36847117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 36857117f1b4Smrg 36867117f1b4Smrg 36877117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 36887117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 36897117f1b4Smrg if (!texObj) { 36907117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 36917117f1b4Smrg return; 36927117f1b4Smrg } 36937117f1b4Smrg 36947117f1b4Smrg maxLevels = _mesa_max_texture_levels(ctx, target); 36957117f1b4Smrg ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 36967117f1b4Smrg 36977117f1b4Smrg if (level < 0 || level >= maxLevels) { 36987117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 36997117f1b4Smrg return; 37007117f1b4Smrg } 37017117f1b4Smrg 37027117f1b4Smrg if (_mesa_is_proxy_texture(target)) { 37037117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 37047117f1b4Smrg return; 37057117f1b4Smrg } 37067117f1b4Smrg 37077117f1b4Smrg 37087117f1b4Smrg _mesa_lock_texture(ctx, texObj); 37097117f1b4Smrg { 37107117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 37117117f1b4Smrg if (!texImage) { 37127117f1b4Smrg /* probably invalid mipmap level */ 37137117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 37147117f1b4Smrg goto out; 37157117f1b4Smrg } 37167117f1b4Smrg 37177117f1b4Smrg if (!texImage->IsCompressed) { 37187117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); 37197117f1b4Smrg goto out; 37207117f1b4Smrg } 37217117f1b4Smrg 37227117f1b4Smrg /* this typically calls _mesa_get_compressed_teximage() */ 37237117f1b4Smrg ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage); 37247117f1b4Smrg } 37257117f1b4Smrg out: 37267117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 37277117f1b4Smrg} 3728