teximage.c revision c1f859d4
17117f1b4Smrg/* 2c1f859d4Smrg * mesa 3-D graphics library 3c1f859d4Smrg * Version: 7.1 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" 35c1f859d4Smrg#if FEATURE_convolve 367117f1b4Smrg#include "convolve.h" 37c1f859d4Smrg#endif 387117f1b4Smrg#include "fbobject.h" 397117f1b4Smrg#include "framebuffer.h" 407117f1b4Smrg#include "image.h" 417117f1b4Smrg#include "imports.h" 427117f1b4Smrg#include "macros.h" 437117f1b4Smrg#include "state.h" 447117f1b4Smrg#include "texcompress.h" 457117f1b4Smrg#include "texformat.h" 467117f1b4Smrg#include "teximage.h" 477117f1b4Smrg#include "texstate.h" 487117f1b4Smrg#include "texstore.h" 497117f1b4Smrg#include "mtypes.h" 507117f1b4Smrg 517117f1b4Smrg 52c1f859d4Smrg/** 53c1f859d4Smrg * State changes which we care about for glCopyTex[Sub]Image() calls. 54c1f859d4Smrg * In particular, we care about pixel transfer state and buffer state 55c1f859d4Smrg * (such as glReadBuffer to make sure we read from the right renderbuffer). 56c1f859d4Smrg */ 57c1f859d4Smrg#define NEW_COPY_TEX_STATE (_IMAGE_NEW_TRANSFER_STATE | \ 58c1f859d4Smrg _NEW_BUFFERS | \ 59c1f859d4Smrg _NEW_PIXEL) 60c1f859d4Smrg 61c1f859d4Smrg 62c1f859d4Smrg 637117f1b4Smrg/** 647117f1b4Smrg * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE 657117f1b4Smrg * elsewhere. 667117f1b4Smrg */ 677117f1b4Smrgvoid * 687117f1b4Smrg_mesa_alloc_texmemory(GLsizei bytes) 697117f1b4Smrg{ 707117f1b4Smrg return _mesa_align_malloc(bytes, 512); 717117f1b4Smrg} 727117f1b4Smrg 737117f1b4Smrg 747117f1b4Smrg/** 757117f1b4Smrg * Free texture memory allocated with _mesa_alloc_texmemory() 767117f1b4Smrg */ 777117f1b4Smrgvoid 787117f1b4Smrg_mesa_free_texmemory(void *m) 797117f1b4Smrg{ 807117f1b4Smrg _mesa_align_free(m); 817117f1b4Smrg} 827117f1b4Smrg 837117f1b4Smrg 847117f1b4Smrg 857117f1b4Smrg 867117f1b4Smrg#if 0 877117f1b4Smrgstatic void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) 887117f1b4Smrg{ 897117f1b4Smrg#if CHAN_TYPE != GL_UNSIGNED_BYTE 907117f1b4Smrg _mesa_problem(NULL, "PrintTexture not supported"); 917117f1b4Smrg#else 927117f1b4Smrg GLuint i, j, c; 937117f1b4Smrg const GLubyte *data = (const GLubyte *) img->Data; 947117f1b4Smrg 957117f1b4Smrg if (!data) { 967117f1b4Smrg _mesa_printf("No texture data\n"); 977117f1b4Smrg return; 987117f1b4Smrg } 997117f1b4Smrg 1007117f1b4Smrg switch (img->Format) { 1017117f1b4Smrg case GL_ALPHA: 1027117f1b4Smrg case GL_LUMINANCE: 1037117f1b4Smrg case GL_INTENSITY: 1047117f1b4Smrg case GL_COLOR_INDEX: 1057117f1b4Smrg c = 1; 1067117f1b4Smrg break; 1077117f1b4Smrg case GL_LUMINANCE_ALPHA: 1087117f1b4Smrg c = 2; 1097117f1b4Smrg break; 1107117f1b4Smrg case GL_RGB: 1117117f1b4Smrg c = 3; 1127117f1b4Smrg break; 1137117f1b4Smrg case GL_RGBA: 1147117f1b4Smrg c = 4; 1157117f1b4Smrg break; 1167117f1b4Smrg default: 1177117f1b4Smrg _mesa_problem(NULL, "error in PrintTexture\n"); 1187117f1b4Smrg return; 1197117f1b4Smrg } 1207117f1b4Smrg 1217117f1b4Smrg for (i = 0; i < img->Height; i++) { 1227117f1b4Smrg for (j = 0; j < img->Width; j++) { 1237117f1b4Smrg if (c==1) 1247117f1b4Smrg _mesa_printf("%02x ", data[0]); 1257117f1b4Smrg else if (c==2) 1267117f1b4Smrg _mesa_printf("%02x%02x ", data[0], data[1]); 1277117f1b4Smrg else if (c==3) 1287117f1b4Smrg _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]); 1297117f1b4Smrg else if (c==4) 1307117f1b4Smrg _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 1317117f1b4Smrg data += (img->RowStride - img->Width) * c; 1327117f1b4Smrg } 1337117f1b4Smrg /* XXX use img->ImageStride here */ 1347117f1b4Smrg _mesa_printf("\n"); 1357117f1b4Smrg } 1367117f1b4Smrg#endif 1377117f1b4Smrg} 1387117f1b4Smrg#endif 1397117f1b4Smrg 1407117f1b4Smrg 1417117f1b4Smrg/* 1427117f1b4Smrg * Compute floor(log_base_2(n)). 1437117f1b4Smrg * If n < 0 return -1. 1447117f1b4Smrg */ 1457117f1b4Smrgstatic int 1467117f1b4Smrglogbase2( int n ) 1477117f1b4Smrg{ 1487117f1b4Smrg GLint i = 1; 1497117f1b4Smrg GLint log2 = 0; 1507117f1b4Smrg 1517117f1b4Smrg if (n < 0) 1527117f1b4Smrg return -1; 1537117f1b4Smrg 1547117f1b4Smrg if (n == 0) 1557117f1b4Smrg return 0; 1567117f1b4Smrg 1577117f1b4Smrg while ( n > i ) { 1587117f1b4Smrg i *= 2; 1597117f1b4Smrg log2++; 1607117f1b4Smrg } 1617117f1b4Smrg if (i != n) { 1627117f1b4Smrg return log2 - 1; 1637117f1b4Smrg } 1647117f1b4Smrg else { 1657117f1b4Smrg return log2; 1667117f1b4Smrg } 1677117f1b4Smrg} 1687117f1b4Smrg 1697117f1b4Smrg 1707117f1b4Smrg 1717117f1b4Smrg/** 1727117f1b4Smrg * Return the simple base format for a given internal texture format. 1737117f1b4Smrg * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. 1747117f1b4Smrg * 1757117f1b4Smrg * \param ctx GL context. 1767117f1b4Smrg * \param internalFormat the internal texture format token or 1, 2, 3, or 4. 1777117f1b4Smrg * 1787117f1b4Smrg * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, 1797117f1b4Smrg * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. 1807117f1b4Smrg * 1817117f1b4Smrg * This is the format which is used during texture application (i.e. the 1827117f1b4Smrg * texture format and env mode determine the arithmetic used. 1837117f1b4Smrg */ 1847117f1b4SmrgGLint 1857117f1b4Smrg_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) 1867117f1b4Smrg{ 1877117f1b4Smrg switch (internalFormat) { 1887117f1b4Smrg case GL_ALPHA: 1897117f1b4Smrg case GL_ALPHA4: 1907117f1b4Smrg case GL_ALPHA8: 1917117f1b4Smrg case GL_ALPHA12: 1927117f1b4Smrg case GL_ALPHA16: 1937117f1b4Smrg return GL_ALPHA; 1947117f1b4Smrg case 1: 1957117f1b4Smrg case GL_LUMINANCE: 1967117f1b4Smrg case GL_LUMINANCE4: 1977117f1b4Smrg case GL_LUMINANCE8: 1987117f1b4Smrg case GL_LUMINANCE12: 1997117f1b4Smrg case GL_LUMINANCE16: 2007117f1b4Smrg return GL_LUMINANCE; 2017117f1b4Smrg case 2: 2027117f1b4Smrg case GL_LUMINANCE_ALPHA: 2037117f1b4Smrg case GL_LUMINANCE4_ALPHA4: 2047117f1b4Smrg case GL_LUMINANCE6_ALPHA2: 2057117f1b4Smrg case GL_LUMINANCE8_ALPHA8: 2067117f1b4Smrg case GL_LUMINANCE12_ALPHA4: 2077117f1b4Smrg case GL_LUMINANCE12_ALPHA12: 2087117f1b4Smrg case GL_LUMINANCE16_ALPHA16: 2097117f1b4Smrg return GL_LUMINANCE_ALPHA; 2107117f1b4Smrg case GL_INTENSITY: 2117117f1b4Smrg case GL_INTENSITY4: 2127117f1b4Smrg case GL_INTENSITY8: 2137117f1b4Smrg case GL_INTENSITY12: 2147117f1b4Smrg case GL_INTENSITY16: 2157117f1b4Smrg return GL_INTENSITY; 2167117f1b4Smrg case 3: 2177117f1b4Smrg case GL_RGB: 2187117f1b4Smrg case GL_R3_G3_B2: 2197117f1b4Smrg case GL_RGB4: 2207117f1b4Smrg case GL_RGB5: 2217117f1b4Smrg case GL_RGB8: 2227117f1b4Smrg case GL_RGB10: 2237117f1b4Smrg case GL_RGB12: 2247117f1b4Smrg case GL_RGB16: 2257117f1b4Smrg return GL_RGB; 2267117f1b4Smrg case 4: 2277117f1b4Smrg case GL_RGBA: 2287117f1b4Smrg case GL_RGBA2: 2297117f1b4Smrg case GL_RGBA4: 2307117f1b4Smrg case GL_RGB5_A1: 2317117f1b4Smrg case GL_RGBA8: 2327117f1b4Smrg case GL_RGB10_A2: 2337117f1b4Smrg case GL_RGBA12: 2347117f1b4Smrg case GL_RGBA16: 2357117f1b4Smrg return GL_RGBA; 2367117f1b4Smrg default: 2377117f1b4Smrg ; /* fallthrough */ 2387117f1b4Smrg } 2397117f1b4Smrg 2407117f1b4Smrg if (ctx->Extensions.EXT_paletted_texture) { 2417117f1b4Smrg switch (internalFormat) { 2427117f1b4Smrg case GL_COLOR_INDEX: 2437117f1b4Smrg case GL_COLOR_INDEX1_EXT: 2447117f1b4Smrg case GL_COLOR_INDEX2_EXT: 2457117f1b4Smrg case GL_COLOR_INDEX4_EXT: 2467117f1b4Smrg case GL_COLOR_INDEX8_EXT: 2477117f1b4Smrg case GL_COLOR_INDEX12_EXT: 2487117f1b4Smrg case GL_COLOR_INDEX16_EXT: 2497117f1b4Smrg return GL_COLOR_INDEX; 2507117f1b4Smrg default: 2517117f1b4Smrg ; /* fallthrough */ 2527117f1b4Smrg } 2537117f1b4Smrg } 2547117f1b4Smrg 255c1f859d4Smrg if (ctx->Extensions.ARB_depth_texture) { 2567117f1b4Smrg switch (internalFormat) { 2577117f1b4Smrg case GL_DEPTH_COMPONENT: 258c1f859d4Smrg case GL_DEPTH_COMPONENT16: 259c1f859d4Smrg case GL_DEPTH_COMPONENT24: 260c1f859d4Smrg case GL_DEPTH_COMPONENT32: 2617117f1b4Smrg return GL_DEPTH_COMPONENT; 2627117f1b4Smrg default: 2637117f1b4Smrg ; /* fallthrough */ 2647117f1b4Smrg } 2657117f1b4Smrg } 2667117f1b4Smrg 2677117f1b4Smrg if (ctx->Extensions.ARB_texture_compression) { 2687117f1b4Smrg switch (internalFormat) { 2697117f1b4Smrg case GL_COMPRESSED_ALPHA: 2707117f1b4Smrg return GL_ALPHA; 2717117f1b4Smrg case GL_COMPRESSED_LUMINANCE: 2727117f1b4Smrg return GL_LUMINANCE; 2737117f1b4Smrg case GL_COMPRESSED_LUMINANCE_ALPHA: 2747117f1b4Smrg return GL_LUMINANCE_ALPHA; 2757117f1b4Smrg case GL_COMPRESSED_INTENSITY: 2767117f1b4Smrg return GL_INTENSITY; 2777117f1b4Smrg case GL_COMPRESSED_RGB: 2787117f1b4Smrg return GL_RGB; 2797117f1b4Smrg case GL_COMPRESSED_RGBA: 2807117f1b4Smrg return GL_RGBA; 2817117f1b4Smrg default: 2827117f1b4Smrg ; /* fallthrough */ 2837117f1b4Smrg } 2847117f1b4Smrg } 2857117f1b4Smrg 2867117f1b4Smrg if (ctx->Extensions.TDFX_texture_compression_FXT1) { 2877117f1b4Smrg switch (internalFormat) { 2887117f1b4Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 2897117f1b4Smrg return GL_RGB; 2907117f1b4Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 2917117f1b4Smrg return GL_RGBA; 2927117f1b4Smrg default: 2937117f1b4Smrg ; /* fallthrough */ 2947117f1b4Smrg } 2957117f1b4Smrg } 2967117f1b4Smrg 2977117f1b4Smrg if (ctx->Extensions.EXT_texture_compression_s3tc) { 2987117f1b4Smrg switch (internalFormat) { 2997117f1b4Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 3007117f1b4Smrg return GL_RGB; 3017117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 3027117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 3037117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 3047117f1b4Smrg return GL_RGBA; 3057117f1b4Smrg default: 3067117f1b4Smrg ; /* fallthrough */ 3077117f1b4Smrg } 3087117f1b4Smrg } 3097117f1b4Smrg 3107117f1b4Smrg if (ctx->Extensions.S3_s3tc) { 3117117f1b4Smrg switch (internalFormat) { 3127117f1b4Smrg case GL_RGB_S3TC: 3137117f1b4Smrg case GL_RGB4_S3TC: 3147117f1b4Smrg return GL_RGB; 3157117f1b4Smrg case GL_RGBA_S3TC: 3167117f1b4Smrg case GL_RGBA4_S3TC: 3177117f1b4Smrg return GL_RGBA; 3187117f1b4Smrg default: 3197117f1b4Smrg ; /* fallthrough */ 3207117f1b4Smrg } 3217117f1b4Smrg } 3227117f1b4Smrg 3237117f1b4Smrg if (ctx->Extensions.MESA_ycbcr_texture) { 3247117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) 3257117f1b4Smrg return GL_YCBCR_MESA; 3267117f1b4Smrg } 3277117f1b4Smrg 3287117f1b4Smrg if (ctx->Extensions.ARB_texture_float) { 3297117f1b4Smrg switch (internalFormat) { 3307117f1b4Smrg case GL_ALPHA16F_ARB: 3317117f1b4Smrg case GL_ALPHA32F_ARB: 3327117f1b4Smrg return GL_ALPHA; 3337117f1b4Smrg case GL_RGBA16F_ARB: 3347117f1b4Smrg case GL_RGBA32F_ARB: 3357117f1b4Smrg return GL_RGBA; 3367117f1b4Smrg case GL_RGB16F_ARB: 3377117f1b4Smrg case GL_RGB32F_ARB: 3387117f1b4Smrg return GL_RGB; 3397117f1b4Smrg case GL_INTENSITY16F_ARB: 3407117f1b4Smrg case GL_INTENSITY32F_ARB: 3417117f1b4Smrg return GL_INTENSITY; 3427117f1b4Smrg case GL_LUMINANCE16F_ARB: 3437117f1b4Smrg case GL_LUMINANCE32F_ARB: 3447117f1b4Smrg return GL_LUMINANCE; 3457117f1b4Smrg case GL_LUMINANCE_ALPHA16F_ARB: 3467117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 3477117f1b4Smrg return GL_LUMINANCE_ALPHA; 3487117f1b4Smrg default: 3497117f1b4Smrg ; /* fallthrough */ 3507117f1b4Smrg } 3517117f1b4Smrg } 3527117f1b4Smrg 3537117f1b4Smrg if (ctx->Extensions.EXT_packed_depth_stencil) { 3547117f1b4Smrg switch (internalFormat) { 3557117f1b4Smrg case GL_DEPTH_STENCIL_EXT: 3567117f1b4Smrg case GL_DEPTH24_STENCIL8_EXT: 3577117f1b4Smrg return GL_DEPTH_STENCIL_EXT; 3587117f1b4Smrg default: 3597117f1b4Smrg ; /* fallthrough */ 3607117f1b4Smrg } 3617117f1b4Smrg } 3627117f1b4Smrg 3637117f1b4Smrg#if FEATURE_EXT_texture_sRGB 3647117f1b4Smrg if (ctx->Extensions.EXT_texture_sRGB) { 3657117f1b4Smrg switch (internalFormat) { 3667117f1b4Smrg case GL_SRGB_EXT: 3677117f1b4Smrg case GL_SRGB8_EXT: 3687117f1b4Smrg case GL_COMPRESSED_SRGB_EXT: 3697117f1b4Smrg case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 3707117f1b4Smrg return GL_RGB; 3717117f1b4Smrg case GL_SRGB_ALPHA_EXT: 3727117f1b4Smrg case GL_SRGB8_ALPHA8_EXT: 3737117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_EXT: 3747117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 3757117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 3767117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 3777117f1b4Smrg return GL_RGBA; 3787117f1b4Smrg case GL_SLUMINANCE_ALPHA_EXT: 3797117f1b4Smrg case GL_SLUMINANCE8_ALPHA8_EXT: 3807117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_EXT: 3817117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 3827117f1b4Smrg return GL_LUMINANCE_ALPHA; 3837117f1b4Smrg case GL_SLUMINANCE_EXT: 3847117f1b4Smrg case GL_SLUMINANCE8_EXT: 3857117f1b4Smrg return GL_LUMINANCE; 3867117f1b4Smrg default: 3877117f1b4Smrg ; /* fallthrough */ 3887117f1b4Smrg } 3897117f1b4Smrg } 3907117f1b4Smrg 3917117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */ 3927117f1b4Smrg 3937117f1b4Smrg return -1; /* error */ 3947117f1b4Smrg} 3957117f1b4Smrg 3967117f1b4Smrg 3977117f1b4Smrg/** 3987117f1b4Smrg * Test if the given image format is a color/RGBA format (i.e., not color 3997117f1b4Smrg * index, depth, stencil, etc). 4007117f1b4Smrg * \param format the image format value (may by an internal texture format) 4017117f1b4Smrg * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. 402c1f859d4Smrg * XXX maybe move this func to image.c 4037117f1b4Smrg */ 404c1f859d4SmrgGLboolean 405c1f859d4Smrg_mesa_is_color_format(GLenum format) 4067117f1b4Smrg{ 4077117f1b4Smrg switch (format) { 4087117f1b4Smrg case GL_RED: 4097117f1b4Smrg case GL_GREEN: 4107117f1b4Smrg case GL_BLUE: 4117117f1b4Smrg case GL_ALPHA: 4127117f1b4Smrg case GL_ALPHA4: 4137117f1b4Smrg case GL_ALPHA8: 4147117f1b4Smrg case GL_ALPHA12: 4157117f1b4Smrg case GL_ALPHA16: 4167117f1b4Smrg case 1: 4177117f1b4Smrg case GL_LUMINANCE: 4187117f1b4Smrg case GL_LUMINANCE4: 4197117f1b4Smrg case GL_LUMINANCE8: 4207117f1b4Smrg case GL_LUMINANCE12: 4217117f1b4Smrg case GL_LUMINANCE16: 4227117f1b4Smrg case 2: 4237117f1b4Smrg case GL_LUMINANCE_ALPHA: 4247117f1b4Smrg case GL_LUMINANCE4_ALPHA4: 4257117f1b4Smrg case GL_LUMINANCE6_ALPHA2: 4267117f1b4Smrg case GL_LUMINANCE8_ALPHA8: 4277117f1b4Smrg case GL_LUMINANCE12_ALPHA4: 4287117f1b4Smrg case GL_LUMINANCE12_ALPHA12: 4297117f1b4Smrg case GL_LUMINANCE16_ALPHA16: 4307117f1b4Smrg case GL_INTENSITY: 4317117f1b4Smrg case GL_INTENSITY4: 4327117f1b4Smrg case GL_INTENSITY8: 4337117f1b4Smrg case GL_INTENSITY12: 4347117f1b4Smrg case GL_INTENSITY16: 4357117f1b4Smrg case 3: 4367117f1b4Smrg case GL_RGB: 4377117f1b4Smrg case GL_BGR: 4387117f1b4Smrg case GL_R3_G3_B2: 4397117f1b4Smrg case GL_RGB4: 4407117f1b4Smrg case GL_RGB5: 4417117f1b4Smrg case GL_RGB8: 4427117f1b4Smrg case GL_RGB10: 4437117f1b4Smrg case GL_RGB12: 4447117f1b4Smrg case GL_RGB16: 4457117f1b4Smrg case 4: 4467117f1b4Smrg case GL_ABGR_EXT: 4477117f1b4Smrg case GL_RGBA: 4487117f1b4Smrg case GL_BGRA: 4497117f1b4Smrg case GL_RGBA2: 4507117f1b4Smrg case GL_RGBA4: 4517117f1b4Smrg case GL_RGB5_A1: 4527117f1b4Smrg case GL_RGBA8: 4537117f1b4Smrg case GL_RGB10_A2: 4547117f1b4Smrg case GL_RGBA12: 4557117f1b4Smrg case GL_RGBA16: 4567117f1b4Smrg /* float texture formats */ 4577117f1b4Smrg case GL_ALPHA16F_ARB: 4587117f1b4Smrg case GL_ALPHA32F_ARB: 4597117f1b4Smrg case GL_LUMINANCE16F_ARB: 4607117f1b4Smrg case GL_LUMINANCE32F_ARB: 4617117f1b4Smrg case GL_LUMINANCE_ALPHA16F_ARB: 4627117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 4637117f1b4Smrg case GL_INTENSITY16F_ARB: 4647117f1b4Smrg case GL_INTENSITY32F_ARB: 4657117f1b4Smrg case GL_RGB16F_ARB: 4667117f1b4Smrg case GL_RGB32F_ARB: 4677117f1b4Smrg case GL_RGBA16F_ARB: 4687117f1b4Smrg case GL_RGBA32F_ARB: 4697117f1b4Smrg /* compressed formats */ 4707117f1b4Smrg case GL_COMPRESSED_ALPHA: 4717117f1b4Smrg case GL_COMPRESSED_LUMINANCE: 4727117f1b4Smrg case GL_COMPRESSED_LUMINANCE_ALPHA: 4737117f1b4Smrg case GL_COMPRESSED_INTENSITY: 4747117f1b4Smrg case GL_COMPRESSED_RGB: 4757117f1b4Smrg case GL_COMPRESSED_RGBA: 4767117f1b4Smrg case GL_RGB_S3TC: 4777117f1b4Smrg case GL_RGB4_S3TC: 4787117f1b4Smrg case GL_RGBA_S3TC: 4797117f1b4Smrg case GL_RGBA4_S3TC: 4807117f1b4Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 4817117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 4827117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 4837117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 4847117f1b4Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 4857117f1b4Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 4867117f1b4Smrg#if FEATURE_EXT_texture_sRGB 4877117f1b4Smrg case GL_SRGB_EXT: 4887117f1b4Smrg case GL_SRGB8_EXT: 4897117f1b4Smrg case GL_SRGB_ALPHA_EXT: 4907117f1b4Smrg case GL_SRGB8_ALPHA8_EXT: 4917117f1b4Smrg case GL_SLUMINANCE_ALPHA_EXT: 4927117f1b4Smrg case GL_SLUMINANCE8_ALPHA8_EXT: 4937117f1b4Smrg case GL_SLUMINANCE_EXT: 4947117f1b4Smrg case GL_SLUMINANCE8_EXT: 4957117f1b4Smrg case GL_COMPRESSED_SRGB_EXT: 4967117f1b4Smrg case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 4977117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_EXT: 4987117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 4997117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 5007117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 5017117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_EXT: 5027117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 5037117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */ 5047117f1b4Smrg return GL_TRUE; 5057117f1b4Smrg case GL_YCBCR_MESA: /* not considered to be RGB */ 506c1f859d4Smrg /* fall-through */ 5077117f1b4Smrg default: 5087117f1b4Smrg return GL_FALSE; 5097117f1b4Smrg } 5107117f1b4Smrg} 5117117f1b4Smrg 5127117f1b4Smrg 5137117f1b4Smrg/** 5147117f1b4Smrg * Test if the given image format is a color index format. 5157117f1b4Smrg */ 5167117f1b4Smrgstatic GLboolean 5177117f1b4Smrgis_index_format(GLenum format) 5187117f1b4Smrg{ 5197117f1b4Smrg switch (format) { 5207117f1b4Smrg case GL_COLOR_INDEX: 5217117f1b4Smrg case GL_COLOR_INDEX1_EXT: 5227117f1b4Smrg case GL_COLOR_INDEX2_EXT: 5237117f1b4Smrg case GL_COLOR_INDEX4_EXT: 5247117f1b4Smrg case GL_COLOR_INDEX8_EXT: 5257117f1b4Smrg case GL_COLOR_INDEX12_EXT: 5267117f1b4Smrg case GL_COLOR_INDEX16_EXT: 5277117f1b4Smrg return GL_TRUE; 5287117f1b4Smrg default: 5297117f1b4Smrg return GL_FALSE; 5307117f1b4Smrg } 5317117f1b4Smrg} 5327117f1b4Smrg 5337117f1b4Smrg 5347117f1b4Smrg/** 5357117f1b4Smrg * Test if the given image format is a depth component format. 5367117f1b4Smrg */ 5377117f1b4Smrgstatic GLboolean 5387117f1b4Smrgis_depth_format(GLenum format) 5397117f1b4Smrg{ 5407117f1b4Smrg switch (format) { 541c1f859d4Smrg case GL_DEPTH_COMPONENT16: 542c1f859d4Smrg case GL_DEPTH_COMPONENT24: 543c1f859d4Smrg case GL_DEPTH_COMPONENT32: 5447117f1b4Smrg case GL_DEPTH_COMPONENT: 5457117f1b4Smrg return GL_TRUE; 5467117f1b4Smrg default: 5477117f1b4Smrg return GL_FALSE; 5487117f1b4Smrg } 5497117f1b4Smrg} 5507117f1b4Smrg 5517117f1b4Smrg 5527117f1b4Smrg/** 5537117f1b4Smrg * Test if the given image format is a YCbCr format. 5547117f1b4Smrg */ 5557117f1b4Smrgstatic GLboolean 5567117f1b4Smrgis_ycbcr_format(GLenum format) 5577117f1b4Smrg{ 5587117f1b4Smrg switch (format) { 5597117f1b4Smrg case GL_YCBCR_MESA: 5607117f1b4Smrg return GL_TRUE; 5617117f1b4Smrg default: 5627117f1b4Smrg return GL_FALSE; 5637117f1b4Smrg } 5647117f1b4Smrg} 5657117f1b4Smrg 5667117f1b4Smrg 5677117f1b4Smrg/** 5687117f1b4Smrg * Test if the given image format is a Depth/Stencil format. 5697117f1b4Smrg */ 5707117f1b4Smrgstatic GLboolean 5717117f1b4Smrgis_depthstencil_format(GLenum format) 5727117f1b4Smrg{ 5737117f1b4Smrg switch (format) { 5747117f1b4Smrg case GL_DEPTH24_STENCIL8_EXT: 5757117f1b4Smrg case GL_DEPTH_STENCIL_EXT: 5767117f1b4Smrg return GL_TRUE; 5777117f1b4Smrg default: 5787117f1b4Smrg return GL_FALSE; 5797117f1b4Smrg } 5807117f1b4Smrg} 5817117f1b4Smrg 5827117f1b4Smrg 5837117f1b4Smrg 5847117f1b4Smrg/** 5857117f1b4Smrg * Test if it is a supported compressed format. 5867117f1b4Smrg * 5877117f1b4Smrg * \param internalFormat the internal format token provided by the user. 5887117f1b4Smrg * 5897117f1b4Smrg * \ret GL_TRUE if \p internalFormat is a supported compressed format, or 5907117f1b4Smrg * GL_FALSE otherwise. 5917117f1b4Smrg * 5927117f1b4Smrg * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX 5937117f1b4Smrg * are supported. 5947117f1b4Smrg */ 5957117f1b4Smrgstatic GLboolean 5967117f1b4Smrgis_compressed_format(GLcontext *ctx, GLenum internalFormat) 5977117f1b4Smrg{ 5987117f1b4Smrg GLint supported[100]; /* 100 should be plenty */ 5997117f1b4Smrg GLuint i, n; 6007117f1b4Smrg 6017117f1b4Smrg n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE); 6027117f1b4Smrg ASSERT(n < 100); 6037117f1b4Smrg for (i = 0; i < n; i++) { 6047117f1b4Smrg if ((GLint) internalFormat == supported[i]) { 6057117f1b4Smrg return GL_TRUE; 6067117f1b4Smrg } 6077117f1b4Smrg } 6087117f1b4Smrg return GL_FALSE; 6097117f1b4Smrg} 6107117f1b4Smrg 6117117f1b4Smrg 612c1f859d4Smrg/** 613c1f859d4Smrg * For cube map faces, return a face index in [0,5]. 614c1f859d4Smrg * For other targets return 0; 615c1f859d4Smrg */ 616c1f859d4SmrgGLuint 617c1f859d4Smrg_mesa_tex_target_to_face(GLenum target) 6187117f1b4Smrg{ 6197117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 6207117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 6217117f1b4Smrg return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 6227117f1b4Smrg else 6237117f1b4Smrg return 0; 6247117f1b4Smrg} 6257117f1b4Smrg 6267117f1b4Smrg 6277117f1b4Smrg 6287117f1b4Smrg/** 6297117f1b4Smrg * Store a gl_texture_image pointer in a gl_texture_object structure 6307117f1b4Smrg * according to the target and level parameters. 6317117f1b4Smrg * 6327117f1b4Smrg * \param tObj texture object. 6337117f1b4Smrg * \param target texture target. 6347117f1b4Smrg * \param level image level. 6357117f1b4Smrg * \param texImage texture image. 6367117f1b4Smrg * 6377117f1b4Smrg * This was basically prompted by the introduction of cube maps. 6387117f1b4Smrg */ 6397117f1b4Smrgvoid 6407117f1b4Smrg_mesa_set_tex_image(struct gl_texture_object *tObj, 6417117f1b4Smrg GLenum target, GLint level, 6427117f1b4Smrg struct gl_texture_image *texImage) 6437117f1b4Smrg{ 6447117f1b4Smrg ASSERT(tObj); 6457117f1b4Smrg ASSERT(texImage); 646c1f859d4Smrg /* XXX simplify this with _mesa_tex_target_to_face() */ 6477117f1b4Smrg switch (target) { 6487117f1b4Smrg case GL_TEXTURE_1D: 6497117f1b4Smrg case GL_TEXTURE_2D: 6507117f1b4Smrg case GL_TEXTURE_3D: 651c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 652c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 6537117f1b4Smrg tObj->Image[0][level] = texImage; 6547117f1b4Smrg break; 6557117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 6567117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 6577117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 6587117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 6597117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 6607117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 6617117f1b4Smrg { 6627117f1b4Smrg GLuint face = ((GLuint) target - 6637117f1b4Smrg (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); 6647117f1b4Smrg tObj->Image[face][level] = texImage; 6657117f1b4Smrg } 6667117f1b4Smrg break; 6677117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 6687117f1b4Smrg ASSERT(level == 0); 6697117f1b4Smrg tObj->Image[0][level] = texImage; 6707117f1b4Smrg break; 6717117f1b4Smrg default: 6727117f1b4Smrg _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); 6737117f1b4Smrg return; 6747117f1b4Smrg } 6757117f1b4Smrg /* Set the 'back' pointer */ 6767117f1b4Smrg texImage->TexObject = tObj; 6777117f1b4Smrg} 6787117f1b4Smrg 6797117f1b4Smrg 6807117f1b4Smrg/** 6817117f1b4Smrg * Allocate a texture image structure. 6827117f1b4Smrg * 6837117f1b4Smrg * Called via ctx->Driver.NewTextureImage() unless overriden by a device 6847117f1b4Smrg * driver. 6857117f1b4Smrg * 6867117f1b4Smrg * \return a pointer to gl_texture_image struct with all fields initialized to 6877117f1b4Smrg * zero. 6887117f1b4Smrg */ 6897117f1b4Smrgstruct gl_texture_image * 6907117f1b4Smrg_mesa_new_texture_image( GLcontext *ctx ) 6917117f1b4Smrg{ 6927117f1b4Smrg (void) ctx; 6937117f1b4Smrg return CALLOC_STRUCT(gl_texture_image); 6947117f1b4Smrg} 6957117f1b4Smrg 6967117f1b4Smrg 6977117f1b4Smrg/** 6987117f1b4Smrg * Free texture image data. 6997117f1b4Smrg * This function is a fallback called via ctx->Driver.FreeTexImageData(). 7007117f1b4Smrg * 7017117f1b4Smrg * \param teximage texture image. 7027117f1b4Smrg * 7037117f1b4Smrg * Free the texture image data if it's not marked as client data. 7047117f1b4Smrg */ 7057117f1b4Smrgvoid 7067117f1b4Smrg_mesa_free_texture_image_data(GLcontext *ctx, 7077117f1b4Smrg struct gl_texture_image *texImage) 7087117f1b4Smrg{ 7097117f1b4Smrg (void) ctx; 7107117f1b4Smrg 7117117f1b4Smrg if (texImage->Data && !texImage->IsClientData) { 7127117f1b4Smrg /* free the old texture data */ 7137117f1b4Smrg _mesa_free_texmemory(texImage->Data); 7147117f1b4Smrg } 7157117f1b4Smrg 7167117f1b4Smrg texImage->Data = NULL; 7177117f1b4Smrg} 7187117f1b4Smrg 7197117f1b4Smrg 7207117f1b4Smrg/** 7217117f1b4Smrg * Free texture image. 7227117f1b4Smrg * 7237117f1b4Smrg * \param teximage texture image. 7247117f1b4Smrg * 7257117f1b4Smrg * Free the texture image structure and the associated image data. 7267117f1b4Smrg */ 7277117f1b4Smrgvoid 7287117f1b4Smrg_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) 7297117f1b4Smrg{ 7307117f1b4Smrg /* Free texImage->Data and/or any other driver-specific texture 7317117f1b4Smrg * image storage. 7327117f1b4Smrg */ 7337117f1b4Smrg ASSERT(ctx->Driver.FreeTexImageData); 7347117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 7357117f1b4Smrg 7367117f1b4Smrg ASSERT(texImage->Data == NULL); 7377117f1b4Smrg if (texImage->ImageOffsets) 7387117f1b4Smrg _mesa_free(texImage->ImageOffsets); 7397117f1b4Smrg _mesa_free(texImage); 7407117f1b4Smrg} 7417117f1b4Smrg 7427117f1b4Smrg 7437117f1b4Smrg/** 7447117f1b4Smrg * Test if a target is a proxy target. 7457117f1b4Smrg * 7467117f1b4Smrg * \param target texture target. 7477117f1b4Smrg * 7487117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 7497117f1b4Smrg */ 7507117f1b4SmrgGLboolean 7517117f1b4Smrg_mesa_is_proxy_texture(GLenum target) 7527117f1b4Smrg{ 7537117f1b4Smrg return (target == GL_PROXY_TEXTURE_1D || 7547117f1b4Smrg target == GL_PROXY_TEXTURE_2D || 7557117f1b4Smrg target == GL_PROXY_TEXTURE_3D || 7567117f1b4Smrg target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 757c1f859d4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV || 758c1f859d4Smrg target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 759c1f859d4Smrg target == GL_PROXY_TEXTURE_2D_ARRAY_EXT); 7607117f1b4Smrg} 7617117f1b4Smrg 7627117f1b4Smrg 7637117f1b4Smrg/** 7647117f1b4Smrg * Get the texture object that corresponds to the target of the given texture unit. 7657117f1b4Smrg * 7667117f1b4Smrg * \param ctx GL context. 7677117f1b4Smrg * \param texUnit texture unit. 7687117f1b4Smrg * \param target texture target. 7697117f1b4Smrg * 7707117f1b4Smrg * \return pointer to the texture object on success, or NULL on failure. 7717117f1b4Smrg * 7727117f1b4Smrg * \sa gl_texture_unit. 7737117f1b4Smrg */ 7747117f1b4Smrgstruct gl_texture_object * 7757117f1b4Smrg_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 7767117f1b4Smrg GLenum target) 7777117f1b4Smrg{ 7787117f1b4Smrg switch (target) { 7797117f1b4Smrg case GL_TEXTURE_1D: 780c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 7817117f1b4Smrg case GL_PROXY_TEXTURE_1D: 782c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 7837117f1b4Smrg case GL_TEXTURE_2D: 784c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 7857117f1b4Smrg case GL_PROXY_TEXTURE_2D: 786c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 7877117f1b4Smrg case GL_TEXTURE_3D: 788c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 7897117f1b4Smrg case GL_PROXY_TEXTURE_3D: 790c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 7917117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 7927117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 7937117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 7947117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 7957117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 7967117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 7977117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 7987117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 799c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 8007117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 8017117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 802c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 8037117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 8047117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 805c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 8067117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 8077117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 808c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 809c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 810c1f859d4Smrg return ctx->Extensions.MESA_texture_array 811c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 812c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 813c1f859d4Smrg return ctx->Extensions.MESA_texture_array 814c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 815c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 816c1f859d4Smrg return ctx->Extensions.MESA_texture_array 817c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 818c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 819c1f859d4Smrg return ctx->Extensions.MESA_texture_array 820c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 8217117f1b4Smrg default: 8227117f1b4Smrg _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 8237117f1b4Smrg return NULL; 8247117f1b4Smrg } 8257117f1b4Smrg} 8267117f1b4Smrg 8277117f1b4Smrg 8287117f1b4Smrg/** 8297117f1b4Smrg * Get the texture image struct which corresponds to target and level 8307117f1b4Smrg * of the given texture unit. 8317117f1b4Smrg * 8327117f1b4Smrg * \param ctx GL context. 8337117f1b4Smrg * \param texUnit texture unit. 8347117f1b4Smrg * \param target texture target. 8357117f1b4Smrg * \param level image level. 8367117f1b4Smrg * 8377117f1b4Smrg * \return pointer to the texture image structure on success, or NULL on failure. 8387117f1b4Smrg * 8397117f1b4Smrg * \sa gl_texture_unit. 8407117f1b4Smrg */ 8417117f1b4Smrgstruct gl_texture_image * 8427117f1b4Smrg_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, 8437117f1b4Smrg GLenum target, GLint level) 8447117f1b4Smrg{ 8457117f1b4Smrg ASSERT(texObj); 8467117f1b4Smrg 8477117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) 8487117f1b4Smrg return NULL; 8497117f1b4Smrg 850c1f859d4Smrg /* XXX simplify this with _mesa_tex_target_to_face() */ 8517117f1b4Smrg switch (target) { 8527117f1b4Smrg case GL_TEXTURE_1D: 8537117f1b4Smrg case GL_PROXY_TEXTURE_1D: 8547117f1b4Smrg case GL_TEXTURE_2D: 8557117f1b4Smrg case GL_PROXY_TEXTURE_2D: 8567117f1b4Smrg case GL_TEXTURE_3D: 8577117f1b4Smrg case GL_PROXY_TEXTURE_3D: 8587117f1b4Smrg return texObj->Image[0][level]; 8597117f1b4Smrg 8607117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 8617117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 8627117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 8637117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 8647117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 8657117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 8667117f1b4Smrg if (ctx->Extensions.ARB_texture_cube_map) { 8677117f1b4Smrg GLuint face = ((GLuint) target - 8687117f1b4Smrg (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); 8697117f1b4Smrg return texObj->Image[face][level]; 8707117f1b4Smrg } 8717117f1b4Smrg else 8727117f1b4Smrg return NULL; 8737117f1b4Smrg 8747117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 8757117f1b4Smrg if (ctx->Extensions.ARB_texture_cube_map) 8767117f1b4Smrg return texObj->Image[0][level]; 8777117f1b4Smrg else 8787117f1b4Smrg return NULL; 8797117f1b4Smrg 8807117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 8817117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 8827117f1b4Smrg if (ctx->Extensions.NV_texture_rectangle && level == 0) 8837117f1b4Smrg return texObj->Image[0][level]; 8847117f1b4Smrg else 8857117f1b4Smrg return NULL; 8867117f1b4Smrg 887c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 888c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 889c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 890c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 891c1f859d4Smrg return (ctx->Extensions.MESA_texture_array) 892c1f859d4Smrg ? texObj->Image[0][level] : NULL; 893c1f859d4Smrg 8947117f1b4Smrg default: 8957117f1b4Smrg return NULL; 8967117f1b4Smrg } 8977117f1b4Smrg} 8987117f1b4Smrg 8997117f1b4Smrg 9007117f1b4Smrg/** 9017117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 9027117f1b4Smrg * it and install it. Only return NULL if passed a bad parameter or run 9037117f1b4Smrg * out of memory. 9047117f1b4Smrg */ 9057117f1b4Smrgstruct gl_texture_image * 9067117f1b4Smrg_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj, 9077117f1b4Smrg GLenum target, GLint level) 9087117f1b4Smrg{ 9097117f1b4Smrg struct gl_texture_image *texImage; 9107117f1b4Smrg 9117117f1b4Smrg if (!texObj) 9127117f1b4Smrg return NULL; 9137117f1b4Smrg 9147117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 9157117f1b4Smrg if (!texImage) { 9167117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9177117f1b4Smrg if (!texImage) { 9187117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 9197117f1b4Smrg return NULL; 9207117f1b4Smrg } 9217117f1b4Smrg 9227117f1b4Smrg _mesa_set_tex_image(texObj, target, level, texImage); 9237117f1b4Smrg } 9247117f1b4Smrg 9257117f1b4Smrg return texImage; 9267117f1b4Smrg} 9277117f1b4Smrg 9287117f1b4Smrg 9297117f1b4Smrg/** 9307117f1b4Smrg * Return pointer to the specified proxy texture image. 9317117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit. 9327117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid 9337117f1b4Smrg * level, or out of memory. 9347117f1b4Smrg */ 9357117f1b4Smrgstruct gl_texture_image * 9367117f1b4Smrg_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) 9377117f1b4Smrg{ 9387117f1b4Smrg struct gl_texture_image *texImage; 9397117f1b4Smrg 9407117f1b4Smrg if (level < 0 ) 9417117f1b4Smrg return NULL; 9427117f1b4Smrg 9437117f1b4Smrg switch (target) { 9447117f1b4Smrg case GL_PROXY_TEXTURE_1D: 9457117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 9467117f1b4Smrg return NULL; 947c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level]; 9487117f1b4Smrg if (!texImage) { 9497117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9507117f1b4Smrg if (!texImage) { 9517117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9527117f1b4Smrg return NULL; 9537117f1b4Smrg } 954c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level] = texImage; 9557117f1b4Smrg /* Set the 'back' pointer */ 956c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 9577117f1b4Smrg } 9587117f1b4Smrg return texImage; 9597117f1b4Smrg case GL_PROXY_TEXTURE_2D: 9607117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 9617117f1b4Smrg return NULL; 962c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level]; 9637117f1b4Smrg if (!texImage) { 9647117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9657117f1b4Smrg if (!texImage) { 9667117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9677117f1b4Smrg return NULL; 9687117f1b4Smrg } 969c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level] = texImage; 9707117f1b4Smrg /* Set the 'back' pointer */ 971c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 9727117f1b4Smrg } 9737117f1b4Smrg return texImage; 9747117f1b4Smrg case GL_PROXY_TEXTURE_3D: 9757117f1b4Smrg if (level >= ctx->Const.Max3DTextureLevels) 9767117f1b4Smrg return NULL; 977c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level]; 9787117f1b4Smrg if (!texImage) { 9797117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9807117f1b4Smrg if (!texImage) { 9817117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9827117f1b4Smrg return NULL; 9837117f1b4Smrg } 984c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level] = texImage; 9857117f1b4Smrg /* Set the 'back' pointer */ 986c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 9877117f1b4Smrg } 9887117f1b4Smrg return texImage; 9897117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP: 9907117f1b4Smrg if (level >= ctx->Const.MaxCubeTextureLevels) 9917117f1b4Smrg return NULL; 992c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level]; 9937117f1b4Smrg if (!texImage) { 9947117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 9957117f1b4Smrg if (!texImage) { 9967117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9977117f1b4Smrg return NULL; 9987117f1b4Smrg } 999c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level] = texImage; 10007117f1b4Smrg /* Set the 'back' pointer */ 1001c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]; 10027117f1b4Smrg } 10037117f1b4Smrg return texImage; 10047117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 10057117f1b4Smrg if (level > 0) 10067117f1b4Smrg return NULL; 1007c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level]; 1008c1f859d4Smrg if (!texImage) { 1009c1f859d4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 1010c1f859d4Smrg if (!texImage) { 1011c1f859d4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 1012c1f859d4Smrg return NULL; 1013c1f859d4Smrg } 1014c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level] = texImage; 1015c1f859d4Smrg /* Set the 'back' pointer */ 1016c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]; 1017c1f859d4Smrg } 1018c1f859d4Smrg return texImage; 1019c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1020c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 1021c1f859d4Smrg return NULL; 1022c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level]; 10237117f1b4Smrg if (!texImage) { 10247117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 10257117f1b4Smrg if (!texImage) { 10267117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 10277117f1b4Smrg return NULL; 10287117f1b4Smrg } 1029c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level] = texImage; 10307117f1b4Smrg /* Set the 'back' pointer */ 1031c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]; 1032c1f859d4Smrg } 1033c1f859d4Smrg return texImage; 1034c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1035c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 1036c1f859d4Smrg return NULL; 1037c1f859d4Smrg texImage = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level]; 1038c1f859d4Smrg if (!texImage) { 1039c1f859d4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 1040c1f859d4Smrg if (!texImage) { 1041c1f859d4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 1042c1f859d4Smrg return NULL; 1043c1f859d4Smrg } 1044c1f859d4Smrg ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level] = texImage; 1045c1f859d4Smrg /* Set the 'back' pointer */ 1046c1f859d4Smrg texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]; 10477117f1b4Smrg } 10487117f1b4Smrg return texImage; 10497117f1b4Smrg default: 10507117f1b4Smrg return NULL; 10517117f1b4Smrg } 10527117f1b4Smrg} 10537117f1b4Smrg 10547117f1b4Smrg 10557117f1b4Smrg/** 10567117f1b4Smrg * Get the maximum number of allowed mipmap levels. 10577117f1b4Smrg * 10587117f1b4Smrg * \param ctx GL context. 10597117f1b4Smrg * \param target texture target. 10607117f1b4Smrg * 10617117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given 10627117f1b4Smrg * texture target, or zero if passed a bad target. 10637117f1b4Smrg * 10647117f1b4Smrg * \sa gl_constants. 10657117f1b4Smrg */ 10667117f1b4SmrgGLint 10677117f1b4Smrg_mesa_max_texture_levels(GLcontext *ctx, GLenum target) 10687117f1b4Smrg{ 10697117f1b4Smrg switch (target) { 10707117f1b4Smrg case GL_TEXTURE_1D: 10717117f1b4Smrg case GL_PROXY_TEXTURE_1D: 10727117f1b4Smrg case GL_TEXTURE_2D: 10737117f1b4Smrg case GL_PROXY_TEXTURE_2D: 1074c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 1075c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1076c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 1077c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 10787117f1b4Smrg return ctx->Const.MaxTextureLevels; 10797117f1b4Smrg case GL_TEXTURE_3D: 10807117f1b4Smrg case GL_PROXY_TEXTURE_3D: 10817117f1b4Smrg return ctx->Const.Max3DTextureLevels; 10827117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 10837117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 10847117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 10857117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 10867117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 10877117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 10887117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 10897117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 10907117f1b4Smrg return ctx->Const.MaxCubeTextureLevels; 10917117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 10927117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 10937117f1b4Smrg return 1; 10947117f1b4Smrg default: 10957117f1b4Smrg return 0; /* bad target */ 10967117f1b4Smrg } 10977117f1b4Smrg} 10987117f1b4Smrg 10997117f1b4Smrg 11007117f1b4Smrg 11017117f1b4Smrg#if 000 /* not used anymore */ 11027117f1b4Smrg/* 11037117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer. In this case we 11047117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL 11057117f1b4Smrg * spec. 11067117f1b4Smrg */ 11077117f1b4Smrgstatic GLubyte * 11087117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format) 11097117f1b4Smrg{ 11107117f1b4Smrg const GLint components = _mesa_components_in_format(format); 11117117f1b4Smrg const GLint numPixels = width * height * depth; 11127117f1b4Smrg GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 11137117f1b4Smrg 11147117f1b4Smrg#ifdef DEBUG 11157117f1b4Smrg /* 11167117f1b4Smrg * Let's see if anyone finds this. If glTexImage2D() is called with 11177117f1b4Smrg * a NULL image pointer then load the texture image with something 11187117f1b4Smrg * interesting instead of leaving it indeterminate. 11197117f1b4Smrg */ 11207117f1b4Smrg if (data) { 11217117f1b4Smrg static const char message[8][32] = { 11227117f1b4Smrg " X X XXXXX XXX X ", 11237117f1b4Smrg " XX XX X X X X X ", 11247117f1b4Smrg " X X X X X X X ", 11257117f1b4Smrg " X X XXXX XXX XXXXX ", 11267117f1b4Smrg " X X X X X X ", 11277117f1b4Smrg " X X X X X X X ", 11287117f1b4Smrg " X X XXXXX XXX X X ", 11297117f1b4Smrg " " 11307117f1b4Smrg }; 11317117f1b4Smrg 11327117f1b4Smrg GLubyte *imgPtr = data; 11337117f1b4Smrg GLint h, i, j, k; 11347117f1b4Smrg for (h = 0; h < depth; h++) { 11357117f1b4Smrg for (i = 0; i < height; i++) { 11367117f1b4Smrg GLint srcRow = 7 - (i % 8); 11377117f1b4Smrg for (j = 0; j < width; j++) { 11387117f1b4Smrg GLint srcCol = j % 32; 11397117f1b4Smrg GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 11407117f1b4Smrg for (k = 0; k < components; k++) { 11417117f1b4Smrg *imgPtr++ = texel; 11427117f1b4Smrg } 11437117f1b4Smrg } 11447117f1b4Smrg } 11457117f1b4Smrg } 11467117f1b4Smrg } 11477117f1b4Smrg#endif 11487117f1b4Smrg 11497117f1b4Smrg return data; 11507117f1b4Smrg} 11517117f1b4Smrg#endif 11527117f1b4Smrg 11537117f1b4Smrg 11547117f1b4Smrg 11557117f1b4Smrg/** 11567117f1b4Smrg * Reset the fields of a gl_texture_image struct to zero. 11577117f1b4Smrg * 11587117f1b4Smrg * \param img texture image structure. 11597117f1b4Smrg * 11607117f1b4Smrg * This is called when a proxy texture test fails, we set all the 11617117f1b4Smrg * image members (except DriverData) to zero. 11627117f1b4Smrg * It's also used in glTexImage[123]D as a safeguard to be sure all 11637117f1b4Smrg * required fields get initialized properly by the Driver.TexImage[123]D 11647117f1b4Smrg * functions. 11657117f1b4Smrg */ 11667117f1b4Smrgstatic void 11677117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img) 11687117f1b4Smrg{ 11697117f1b4Smrg ASSERT(img); 11707117f1b4Smrg img->_BaseFormat = 0; 11717117f1b4Smrg img->InternalFormat = 0; 11727117f1b4Smrg img->Border = 0; 11737117f1b4Smrg img->Width = 0; 11747117f1b4Smrg img->Height = 0; 11757117f1b4Smrg img->Depth = 0; 11767117f1b4Smrg img->RowStride = 0; 11777117f1b4Smrg if (img->ImageOffsets) { 11787117f1b4Smrg _mesa_free(img->ImageOffsets); 11797117f1b4Smrg img->ImageOffsets = NULL; 11807117f1b4Smrg } 11817117f1b4Smrg img->Width2 = 0; 11827117f1b4Smrg img->Height2 = 0; 11837117f1b4Smrg img->Depth2 = 0; 11847117f1b4Smrg img->WidthLog2 = 0; 11857117f1b4Smrg img->HeightLog2 = 0; 11867117f1b4Smrg img->DepthLog2 = 0; 11877117f1b4Smrg img->Data = NULL; 11887117f1b4Smrg img->TexFormat = &_mesa_null_texformat; 11897117f1b4Smrg img->FetchTexelc = NULL; 11907117f1b4Smrg img->FetchTexelf = NULL; 11917117f1b4Smrg img->IsCompressed = 0; 11927117f1b4Smrg img->CompressedSize = 0; 11937117f1b4Smrg} 11947117f1b4Smrg 11957117f1b4Smrg 11967117f1b4Smrg/** 11977117f1b4Smrg * Initialize basic fields of the gl_texture_image struct. 11987117f1b4Smrg * 11997117f1b4Smrg * \param ctx GL context. 12007117f1b4Smrg * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 12017117f1b4Smrg * \param img texture image structure to be initialized. 12027117f1b4Smrg * \param width image width. 12037117f1b4Smrg * \param height image height. 12047117f1b4Smrg * \param depth image depth. 12057117f1b4Smrg * \param border image border. 12067117f1b4Smrg * \param internalFormat internal format. 12077117f1b4Smrg * 12087117f1b4Smrg * Fills in the fields of \p img with the given information. 12097117f1b4Smrg * Note: width, height and depth include the border. 12107117f1b4Smrg */ 12117117f1b4Smrgvoid 12127117f1b4Smrg_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, 12137117f1b4Smrg struct gl_texture_image *img, 12147117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 12157117f1b4Smrg GLint border, GLenum internalFormat) 12167117f1b4Smrg{ 12177117f1b4Smrg GLint i; 12187117f1b4Smrg 12197117f1b4Smrg ASSERT(img); 12207117f1b4Smrg ASSERT(width >= 0); 12217117f1b4Smrg ASSERT(height >= 0); 12227117f1b4Smrg ASSERT(depth >= 0); 12237117f1b4Smrg 12247117f1b4Smrg img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 12257117f1b4Smrg ASSERT(img->_BaseFormat > 0); 12267117f1b4Smrg img->InternalFormat = internalFormat; 12277117f1b4Smrg img->Border = border; 12287117f1b4Smrg img->Width = width; 12297117f1b4Smrg img->Height = height; 12307117f1b4Smrg img->Depth = depth; 12317117f1b4Smrg img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 12327117f1b4Smrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 12337117f1b4Smrg img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 12347117f1b4Smrg img->WidthLog2 = logbase2(img->Width2); 12357117f1b4Smrg if (height == 1) /* 1-D texture */ 12367117f1b4Smrg img->HeightLog2 = 0; 12377117f1b4Smrg else 12387117f1b4Smrg img->HeightLog2 = logbase2(img->Height2); 12397117f1b4Smrg if (depth == 1) /* 2-D texture */ 12407117f1b4Smrg img->DepthLog2 = 0; 12417117f1b4Smrg else 12427117f1b4Smrg img->DepthLog2 = logbase2(img->Depth2); 12437117f1b4Smrg img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 12447117f1b4Smrg img->IsCompressed = GL_FALSE; 12457117f1b4Smrg img->CompressedSize = 0; 12467117f1b4Smrg 1247c1f859d4Smrg if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 1248c1f859d4Smrg (height == 1 || _mesa_is_pow_two(img->Height2)) && 1249c1f859d4Smrg (depth == 1 || _mesa_is_pow_two(img->Depth2))) 12507117f1b4Smrg img->_IsPowerOfTwo = GL_TRUE; 12517117f1b4Smrg else 12527117f1b4Smrg img->_IsPowerOfTwo = GL_FALSE; 12537117f1b4Smrg 12547117f1b4Smrg /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 12557117f1b4Smrg img->RowStride = width; 12567117f1b4Smrg /* Allocate the ImageOffsets array and initialize to typical values. 12577117f1b4Smrg * We allocate the array for 1D/2D textures too in order to avoid special- 12587117f1b4Smrg * case code in the texstore routines. 12597117f1b4Smrg */ 12607117f1b4Smrg img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint)); 12617117f1b4Smrg for (i = 0; i < depth; i++) { 12627117f1b4Smrg img->ImageOffsets[i] = i * width * height; 12637117f1b4Smrg } 12647117f1b4Smrg 12657117f1b4Smrg /* Compute Width/Height/DepthScale for mipmap lod computation */ 12667117f1b4Smrg if (target == GL_TEXTURE_RECTANGLE_NV) { 12677117f1b4Smrg /* scale = 1.0 since texture coords directly map to texels */ 12687117f1b4Smrg img->WidthScale = 1.0; 12697117f1b4Smrg img->HeightScale = 1.0; 12707117f1b4Smrg img->DepthScale = 1.0; 12717117f1b4Smrg } 12727117f1b4Smrg else { 12737117f1b4Smrg img->WidthScale = (GLfloat) img->Width; 12747117f1b4Smrg img->HeightScale = (GLfloat) img->Height; 12757117f1b4Smrg img->DepthScale = (GLfloat) img->Depth; 12767117f1b4Smrg } 12777117f1b4Smrg} 12787117f1b4Smrg 12797117f1b4Smrg 12807117f1b4Smrg/** 12817117f1b4Smrg * This is the fallback for Driver.TestProxyTexImage(). Test the texture 12827117f1b4Smrg * level, width, height and depth against the ctx->Const limits for textures. 12837117f1b4Smrg * 12847117f1b4Smrg * A hardware driver might override this function if, for example, the 12857117f1b4Smrg * max 3D texture size is 512x512x64 (i.e. not a cube). 12867117f1b4Smrg * 12877117f1b4Smrg * Note that width, height, depth == 0 is not an error. However, a 12887117f1b4Smrg * texture with zero width/height/depth will be considered "incomplete" 12897117f1b4Smrg * and texturing will effectively be disabled. 12907117f1b4Smrg * 12917117f1b4Smrg * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 12927117f1b4Smrg * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 12937117f1b4Smrg * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 12947117f1b4Smrg * \param level as passed to glTexImage 12957117f1b4Smrg * \param internalFormat as passed to glTexImage 12967117f1b4Smrg * \param format as passed to glTexImage 12977117f1b4Smrg * \param type as passed to glTexImage 12987117f1b4Smrg * \param width as passed to glTexImage 12997117f1b4Smrg * \param height as passed to glTexImage 13007117f1b4Smrg * \param depth as passed to glTexImage 13017117f1b4Smrg * \param border as passed to glTexImage 13027117f1b4Smrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 13037117f1b4Smrg */ 13047117f1b4SmrgGLboolean 13057117f1b4Smrg_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 13067117f1b4Smrg GLint internalFormat, GLenum format, GLenum type, 13077117f1b4Smrg GLint width, GLint height, GLint depth, GLint border) 13087117f1b4Smrg{ 13097117f1b4Smrg GLint maxSize; 13107117f1b4Smrg 13117117f1b4Smrg (void) internalFormat; 13127117f1b4Smrg (void) format; 13137117f1b4Smrg (void) type; 13147117f1b4Smrg 13157117f1b4Smrg switch (target) { 13167117f1b4Smrg case GL_PROXY_TEXTURE_1D: 13177117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 13187117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 13197117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1320c1f859d4Smrg width >0 && !_mesa_is_pow_two(width - 2 * border)) || 13217117f1b4Smrg level >= ctx->Const.MaxTextureLevels) { 13227117f1b4Smrg /* bad width or level */ 13237117f1b4Smrg return GL_FALSE; 13247117f1b4Smrg } 13257117f1b4Smrg return GL_TRUE; 13267117f1b4Smrg case GL_PROXY_TEXTURE_2D: 13277117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 13287117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 13297117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1330c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 13317117f1b4Smrg height < 2 * border || height > 2 + maxSize || 13327117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1333c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 13347117f1b4Smrg level >= ctx->Const.MaxTextureLevels) { 13357117f1b4Smrg /* bad width or height or level */ 13367117f1b4Smrg return GL_FALSE; 13377117f1b4Smrg } 13387117f1b4Smrg return GL_TRUE; 13397117f1b4Smrg case GL_PROXY_TEXTURE_3D: 13407117f1b4Smrg maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 13417117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 13427117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1343c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 13447117f1b4Smrg height < 2 * border || height > 2 + maxSize || 13457117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1346c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 13477117f1b4Smrg depth < 2 * border || depth > 2 + maxSize || 13487117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1349c1f859d4Smrg depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) || 13507117f1b4Smrg level >= ctx->Const.Max3DTextureLevels) { 13517117f1b4Smrg /* bad width or height or depth or level */ 13527117f1b4Smrg return GL_FALSE; 13537117f1b4Smrg } 13547117f1b4Smrg return GL_TRUE; 13557117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 13567117f1b4Smrg if (width < 0 || width > ctx->Const.MaxTextureRectSize || 13577117f1b4Smrg height < 0 || height > ctx->Const.MaxTextureRectSize || 13587117f1b4Smrg level != 0) { 13597117f1b4Smrg /* bad width or height or level */ 13607117f1b4Smrg return GL_FALSE; 13617117f1b4Smrg } 13627117f1b4Smrg return GL_TRUE; 13637117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 13647117f1b4Smrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 13657117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 13667117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1367c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 13687117f1b4Smrg height < 2 * border || height > 2 + maxSize || 13697117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1370c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 13717117f1b4Smrg level >= ctx->Const.MaxCubeTextureLevels) { 13727117f1b4Smrg /* bad width or height */ 13737117f1b4Smrg return GL_FALSE; 13747117f1b4Smrg } 13757117f1b4Smrg return GL_TRUE; 1376c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1377c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1378c1f859d4Smrg if (width < 2 * border || width > 2 + maxSize || 1379c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1380c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1381c1f859d4Smrg level >= ctx->Const.MaxTextureLevels) { 1382c1f859d4Smrg /* bad width or level */ 1383c1f859d4Smrg return GL_FALSE; 1384c1f859d4Smrg } 1385c1f859d4Smrg 1386c1f859d4Smrg if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) { 1387c1f859d4Smrg return GL_FALSE; 1388c1f859d4Smrg } 1389c1f859d4Smrg return GL_TRUE; 1390c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1391c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1392c1f859d4Smrg if (width < 2 * border || width > 2 + maxSize || 1393c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1394c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1395c1f859d4Smrg height < 2 * border || height > 2 + maxSize || 1396c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1397c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1398c1f859d4Smrg level >= ctx->Const.MaxTextureLevels) { 1399c1f859d4Smrg /* bad width or height or level */ 1400c1f859d4Smrg return GL_FALSE; 1401c1f859d4Smrg } 1402c1f859d4Smrg if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) { 1403c1f859d4Smrg return GL_FALSE; 1404c1f859d4Smrg } 1405c1f859d4Smrg return GL_TRUE; 14067117f1b4Smrg default: 14077117f1b4Smrg _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 14087117f1b4Smrg return GL_FALSE; 14097117f1b4Smrg } 14107117f1b4Smrg} 14117117f1b4Smrg 14127117f1b4Smrg 14137117f1b4Smrg/** 14147117f1b4Smrg * Helper function to determine whether a target supports compressed textures 14157117f1b4Smrg */ 14167117f1b4Smrgstatic GLboolean 14177117f1b4Smrgtarget_can_be_compressed(GLcontext *ctx, GLenum target) 14187117f1b4Smrg{ 14197117f1b4Smrg return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 14207117f1b4Smrg || ((ctx->Extensions.ARB_texture_cube_map && 14217117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP || 14227117f1b4Smrg (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 1423c1f859d4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)))) 1424c1f859d4Smrg || ((ctx->Extensions.MESA_texture_array && 1425c1f859d4Smrg ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) || 1426c1f859d4Smrg (target == GL_TEXTURE_2D_ARRAY_EXT))))); 14277117f1b4Smrg} 14287117f1b4Smrg 14297117f1b4Smrg 14307117f1b4Smrg/** 14317117f1b4Smrg * Test the glTexImage[123]D() parameters for errors. 14327117f1b4Smrg * 14337117f1b4Smrg * \param ctx GL context. 14347117f1b4Smrg * \param target texture target given by the user. 14357117f1b4Smrg * \param level image level given by the user. 14367117f1b4Smrg * \param internalFormat internal format given by the user. 14377117f1b4Smrg * \param format pixel data format given by the user. 14387117f1b4Smrg * \param type pixel data type given by the user. 14397117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 14407117f1b4Smrg * \param width image width given by the user. 14417117f1b4Smrg * \param height image height given by the user. 14427117f1b4Smrg * \param depth image depth given by the user. 14437117f1b4Smrg * \param border image border given by the user. 14447117f1b4Smrg * 14457117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 14467117f1b4Smrg * 14477117f1b4Smrg * Verifies each of the parameters against the constants specified in 14487117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 14497117f1b4Smrg * OpenGL specification. 14507117f1b4Smrg */ 14517117f1b4Smrgstatic GLboolean 14527117f1b4Smrgtexture_error_check( GLcontext *ctx, GLenum target, 14537117f1b4Smrg GLint level, GLint internalFormat, 14547117f1b4Smrg GLenum format, GLenum type, 14557117f1b4Smrg GLuint dimensions, 14567117f1b4Smrg GLint width, GLint height, 14577117f1b4Smrg GLint depth, GLint border ) 14587117f1b4Smrg{ 14597117f1b4Smrg const GLboolean isProxy = _mesa_is_proxy_texture(target); 14607117f1b4Smrg GLboolean sizeOK = GL_TRUE; 14617117f1b4Smrg GLboolean colorFormat, indexFormat; 14627117f1b4Smrg GLenum proxy_target; 14637117f1b4Smrg 14647117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 14657117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 14667117f1b4Smrg if (!isProxy) { 14677117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14687117f1b4Smrg "glTexImage%dD(level=%d)", dimensions, level); 14697117f1b4Smrg } 14707117f1b4Smrg return GL_TRUE; 14717117f1b4Smrg } 14727117f1b4Smrg 14737117f1b4Smrg /* Check border */ 14747117f1b4Smrg if (border < 0 || border > 1 || 14757117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 14767117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 14777117f1b4Smrg if (!isProxy) { 14787117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14797117f1b4Smrg "glTexImage%dD(border=%d)", dimensions, border); 14807117f1b4Smrg } 14817117f1b4Smrg return GL_TRUE; 14827117f1b4Smrg } 14837117f1b4Smrg 14847117f1b4Smrg if (width < 0 || height < 0 || depth < 0) { 14857117f1b4Smrg if (!isProxy) { 14867117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14877117f1b4Smrg "glTexImage%dD(width, height or depth < 0)", dimensions); 14887117f1b4Smrg } 14897117f1b4Smrg return GL_TRUE; 14907117f1b4Smrg } 14917117f1b4Smrg 14927117f1b4Smrg /* Check target and call ctx->Driver.TestProxyTexImage() to check the 14937117f1b4Smrg * level, width, height and depth. 14947117f1b4Smrg */ 14957117f1b4Smrg if (dimensions == 1) { 14967117f1b4Smrg if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 14977117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_1D; 14987117f1b4Smrg height = 1; 14997117f1b4Smrg depth = 1; 15007117f1b4Smrg } 15017117f1b4Smrg else { 15027117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 15037117f1b4Smrg return GL_TRUE; 15047117f1b4Smrg } 15057117f1b4Smrg } 15067117f1b4Smrg else if (dimensions == 2) { 15077117f1b4Smrg depth = 1; 15087117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 15097117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_2D; 15107117f1b4Smrg } 15117117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 15127117f1b4Smrg (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 15137117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 15147117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 15157117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 15167117f1b4Smrg return GL_TRUE; 15177117f1b4Smrg } 15187117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 15197117f1b4Smrg sizeOK = (width == height); 15207117f1b4Smrg } 15217117f1b4Smrg else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 15227117f1b4Smrg target == GL_TEXTURE_RECTANGLE_NV) { 15237117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 15247117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 15257117f1b4Smrg return GL_TRUE; 15267117f1b4Smrg } 15277117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 15287117f1b4Smrg } 1529c1f859d4Smrg else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 1530c1f859d4Smrg target == GL_TEXTURE_1D_ARRAY_EXT) { 1531c1f859d4Smrg proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; 1532c1f859d4Smrg } 15337117f1b4Smrg else { 15347117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 15357117f1b4Smrg return GL_TRUE; 15367117f1b4Smrg } 15377117f1b4Smrg } 15387117f1b4Smrg else if (dimensions == 3) { 15397117f1b4Smrg if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 15407117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_3D; 15417117f1b4Smrg } 1542c1f859d4Smrg else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT || 1543c1f859d4Smrg target == GL_TEXTURE_2D_ARRAY_EXT) { 1544c1f859d4Smrg proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; 1545c1f859d4Smrg } 15467117f1b4Smrg else { 15477117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 15487117f1b4Smrg return GL_TRUE; 15497117f1b4Smrg } 15507117f1b4Smrg } 15517117f1b4Smrg else { 15527117f1b4Smrg _mesa_problem( ctx, "bad dims in texture_error_check" ); 15537117f1b4Smrg return GL_TRUE; 15547117f1b4Smrg } 15557117f1b4Smrg 15567117f1b4Smrg sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 15577117f1b4Smrg internalFormat, format, 15587117f1b4Smrg type, width, height, 15597117f1b4Smrg depth, border); 15607117f1b4Smrg if (!sizeOK) { 15617117f1b4Smrg if (!isProxy) { 15627117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 15637117f1b4Smrg "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 15647117f1b4Smrg dimensions, level, width, height, depth); 15657117f1b4Smrg } 15667117f1b4Smrg return GL_TRUE; 15677117f1b4Smrg } 15687117f1b4Smrg 15697117f1b4Smrg /* Check internalFormat */ 15707117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 15717117f1b4Smrg if (!isProxy) { 15727117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 15737117f1b4Smrg "glTexImage%dD(internalFormat=0x%x)", 15747117f1b4Smrg dimensions, internalFormat); 15757117f1b4Smrg } 15767117f1b4Smrg return GL_TRUE; 15777117f1b4Smrg } 15787117f1b4Smrg 15797117f1b4Smrg /* Check incoming image format and type */ 15807117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 15817117f1b4Smrg /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 15827117f1b4Smrg * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 15837117f1b4Smrg */ 15847117f1b4Smrg if (!isProxy) { 15857117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 15867117f1b4Smrg "glTexImage%dD(format or type)", dimensions); 15877117f1b4Smrg } 15887117f1b4Smrg return GL_TRUE; 15897117f1b4Smrg } 15907117f1b4Smrg 15917117f1b4Smrg /* make sure internal format and format basically agree */ 1592c1f859d4Smrg colorFormat = _mesa_is_color_format(format); 15937117f1b4Smrg indexFormat = is_index_format(format); 1594c1f859d4Smrg if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 15957117f1b4Smrg (is_index_format(internalFormat) && !indexFormat) || 15967117f1b4Smrg (is_depth_format(internalFormat) != is_depth_format(format)) || 15977117f1b4Smrg (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || 15987117f1b4Smrg (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) { 15997117f1b4Smrg if (!isProxy) 16007117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 16017117f1b4Smrg "glTexImage(internalFormat/format)"); 16027117f1b4Smrg return GL_TRUE; 16037117f1b4Smrg } 16047117f1b4Smrg 16057117f1b4Smrg /* additional checks for ycbcr textures */ 16067117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) { 16077117f1b4Smrg ASSERT(ctx->Extensions.MESA_ycbcr_texture); 16087117f1b4Smrg if (type != GL_UNSIGNED_SHORT_8_8_MESA && 16097117f1b4Smrg type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 16107117f1b4Smrg char message[100]; 16117117f1b4Smrg _mesa_sprintf(message, 16127117f1b4Smrg "glTexImage%d(format/type YCBCR mismatch", dimensions); 16137117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, message); 16147117f1b4Smrg return GL_TRUE; /* error */ 16157117f1b4Smrg } 16167117f1b4Smrg if (target != GL_TEXTURE_2D && 16177117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 16187117f1b4Smrg target != GL_TEXTURE_RECTANGLE_NV && 16197117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 16207117f1b4Smrg if (!isProxy) 16217117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 16227117f1b4Smrg return GL_TRUE; 16237117f1b4Smrg } 16247117f1b4Smrg if (border != 0) { 16257117f1b4Smrg if (!isProxy) { 16267117f1b4Smrg char message[100]; 16277117f1b4Smrg _mesa_sprintf(message, 16287117f1b4Smrg "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 16297117f1b4Smrg dimensions, border); 16307117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, message); 16317117f1b4Smrg } 16327117f1b4Smrg return GL_TRUE; 16337117f1b4Smrg } 16347117f1b4Smrg } 16357117f1b4Smrg 16367117f1b4Smrg /* additional checks for depth textures */ 16377117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 16387117f1b4Smrg /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 16397117f1b4Smrg if (target != GL_TEXTURE_1D && 16407117f1b4Smrg target != GL_PROXY_TEXTURE_1D && 16417117f1b4Smrg target != GL_TEXTURE_2D && 16427117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 16437117f1b4Smrg target != GL_TEXTURE_RECTANGLE_ARB && 16447117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 16457117f1b4Smrg if (!isProxy) 16467117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 16477117f1b4Smrg "glTexImage(target/internalFormat)"); 16487117f1b4Smrg return GL_TRUE; 16497117f1b4Smrg } 16507117f1b4Smrg } 16517117f1b4Smrg 16527117f1b4Smrg /* additional checks for compressed textures */ 16537117f1b4Smrg if (is_compressed_format(ctx, internalFormat)) { 16547117f1b4Smrg if (!target_can_be_compressed(ctx, target) && !isProxy) { 16557117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 16567117f1b4Smrg "glTexImage%d(target)", dimensions); 16577117f1b4Smrg return GL_TRUE; 16587117f1b4Smrg } 16597117f1b4Smrg if (border != 0) { 16607117f1b4Smrg if (!isProxy) { 16617117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 16627117f1b4Smrg "glTexImage%D(border!=0)", dimensions); 16637117f1b4Smrg } 16647117f1b4Smrg return GL_TRUE; 16657117f1b4Smrg } 16667117f1b4Smrg } 16677117f1b4Smrg 16687117f1b4Smrg /* if we get here, the parameters are OK */ 16697117f1b4Smrg return GL_FALSE; 16707117f1b4Smrg} 16717117f1b4Smrg 16727117f1b4Smrg 16737117f1b4Smrg/** 16747117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors. 16757117f1b4Smrg * 16767117f1b4Smrg * \param ctx GL context. 16777117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 16787117f1b4Smrg * \param target texture target given by the user. 16797117f1b4Smrg * \param level image level given by the user. 16807117f1b4Smrg * \param xoffset sub-image x offset given by the user. 16817117f1b4Smrg * \param yoffset sub-image y offset given by the user. 16827117f1b4Smrg * \param zoffset sub-image z offset given by the user. 16837117f1b4Smrg * \param format pixel data format given by the user. 16847117f1b4Smrg * \param type pixel data type given by the user. 16857117f1b4Smrg * \param width image width given by the user. 16867117f1b4Smrg * \param height image height given by the user. 16877117f1b4Smrg * \param depth image depth given by the user. 16887117f1b4Smrg * 16897117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 16907117f1b4Smrg * 16917117f1b4Smrg * Verifies each of the parameters against the constants specified in 16927117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 16937117f1b4Smrg * OpenGL specification. 16947117f1b4Smrg */ 16957117f1b4Smrgstatic GLboolean 16967117f1b4Smrgsubtexture_error_check( GLcontext *ctx, GLuint dimensions, 16977117f1b4Smrg GLenum target, GLint level, 16987117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 16997117f1b4Smrg GLint width, GLint height, GLint depth, 17007117f1b4Smrg GLenum format, GLenum type ) 17017117f1b4Smrg{ 17027117f1b4Smrg /* Check target */ 17037117f1b4Smrg if (dimensions == 1) { 17047117f1b4Smrg if (target != GL_TEXTURE_1D) { 17057117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 17067117f1b4Smrg return GL_TRUE; 17077117f1b4Smrg } 17087117f1b4Smrg } 17097117f1b4Smrg else if (dimensions == 2) { 17107117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 17117117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 17127117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 17137117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 17147117f1b4Smrg return GL_TRUE; 17157117f1b4Smrg } 17167117f1b4Smrg } 17177117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 17187117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 17197117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 17207117f1b4Smrg return GL_TRUE; 17217117f1b4Smrg } 17227117f1b4Smrg } 1723c1f859d4Smrg else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1724c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1725c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1726c1f859d4Smrg return GL_TRUE; 1727c1f859d4Smrg } 1728c1f859d4Smrg } 17297117f1b4Smrg else if (target != GL_TEXTURE_2D) { 17307117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 17317117f1b4Smrg return GL_TRUE; 17327117f1b4Smrg } 17337117f1b4Smrg } 17347117f1b4Smrg else if (dimensions == 3) { 1735c1f859d4Smrg if (target == GL_TEXTURE_2D_ARRAY_EXT) { 1736c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1737c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1738c1f859d4Smrg return GL_TRUE; 1739c1f859d4Smrg } 1740c1f859d4Smrg } 1741c1f859d4Smrg else if (target != GL_TEXTURE_3D) { 17427117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 17437117f1b4Smrg return GL_TRUE; 17447117f1b4Smrg } 17457117f1b4Smrg } 17467117f1b4Smrg else { 17477117f1b4Smrg _mesa_problem( ctx, "invalid dims in texture_error_check" ); 17487117f1b4Smrg return GL_TRUE; 17497117f1b4Smrg } 17507117f1b4Smrg 17517117f1b4Smrg /* Basic level check */ 17527117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 17537117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 17547117f1b4Smrg return GL_TRUE; 17557117f1b4Smrg } 17567117f1b4Smrg 17577117f1b4Smrg if (width < 0) { 17587117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17597117f1b4Smrg "glTexSubImage%dD(width=%d)", dimensions, width); 17607117f1b4Smrg return GL_TRUE; 17617117f1b4Smrg } 17627117f1b4Smrg if (height < 0 && dimensions > 1) { 17637117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17647117f1b4Smrg "glTexSubImage%dD(height=%d)", dimensions, height); 17657117f1b4Smrg return GL_TRUE; 17667117f1b4Smrg } 17677117f1b4Smrg if (depth < 0 && dimensions > 2) { 17687117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17697117f1b4Smrg "glTexSubImage%dD(depth=%d)", dimensions, depth); 17707117f1b4Smrg return GL_TRUE; 17717117f1b4Smrg } 17727117f1b4Smrg 17737117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 17747117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 17757117f1b4Smrg "glTexSubImage%dD(format or type)", dimensions); 17767117f1b4Smrg return GL_TRUE; 17777117f1b4Smrg } 17787117f1b4Smrg 17797117f1b4Smrg return GL_FALSE; 17807117f1b4Smrg} 17817117f1b4Smrg 17827117f1b4Smrgstatic GLboolean 17837117f1b4Smrgsubtexture_error_check2( GLcontext *ctx, GLuint dimensions, 17847117f1b4Smrg GLenum target, GLint level, 17857117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 17867117f1b4Smrg GLint width, GLint height, GLint depth, 17877117f1b4Smrg GLenum format, GLenum type, 17887117f1b4Smrg const struct gl_texture_image *destTex ) 17897117f1b4Smrg{ 17907117f1b4Smrg if (!destTex) { 17917117f1b4Smrg /* undefined image level */ 17927117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 17937117f1b4Smrg return GL_TRUE; 17947117f1b4Smrg } 17957117f1b4Smrg 17967117f1b4Smrg if (xoffset < -((GLint)destTex->Border)) { 17977117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 17987117f1b4Smrg dimensions); 17997117f1b4Smrg return GL_TRUE; 18007117f1b4Smrg } 18017117f1b4Smrg if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 18027117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 18037117f1b4Smrg dimensions); 18047117f1b4Smrg return GL_TRUE; 18057117f1b4Smrg } 18067117f1b4Smrg if (dimensions > 1) { 18077117f1b4Smrg if (yoffset < -((GLint)destTex->Border)) { 18087117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 18097117f1b4Smrg dimensions); 18107117f1b4Smrg return GL_TRUE; 18117117f1b4Smrg } 18127117f1b4Smrg if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 18137117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 18147117f1b4Smrg dimensions); 18157117f1b4Smrg return GL_TRUE; 18167117f1b4Smrg } 18177117f1b4Smrg } 18187117f1b4Smrg if (dimensions > 2) { 18197117f1b4Smrg if (zoffset < -((GLint)destTex->Border)) { 18207117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 18217117f1b4Smrg return GL_TRUE; 18227117f1b4Smrg } 18237117f1b4Smrg if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 18247117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 18257117f1b4Smrg return GL_TRUE; 18267117f1b4Smrg } 18277117f1b4Smrg } 18287117f1b4Smrg 18297117f1b4Smrg#if FEATURE_EXT_texture_sRGB 18307117f1b4Smrg if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 18317117f1b4Smrg destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 18327117f1b4Smrg destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 18337117f1b4Smrg destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { 18347117f1b4Smrg if ((width & 0x3) || (height & 0x3) || 18357117f1b4Smrg (xoffset & 0x3) || (yoffset & 0x3)) 18367117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18377117f1b4Smrg "glTexSubImage%dD(size or offset not multiple of 4)", 18387117f1b4Smrg dimensions); 18397117f1b4Smrg return GL_TRUE; 18407117f1b4Smrg } 18417117f1b4Smrg#endif 18427117f1b4Smrg 18437117f1b4Smrg if (destTex->IsCompressed) { 18447117f1b4Smrg if (!target_can_be_compressed(ctx, target)) { 18457117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 18467117f1b4Smrg "glTexSubImage%D(target)", dimensions); 18477117f1b4Smrg return GL_TRUE; 18487117f1b4Smrg } 18497117f1b4Smrg /* offset must be multiple of 4 */ 18507117f1b4Smrg if ((xoffset & 3) || (yoffset & 3)) { 18517117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18527117f1b4Smrg "glTexSubImage%D(xoffset or yoffset)", dimensions); 18537117f1b4Smrg return GL_TRUE; 18547117f1b4Smrg } 18557117f1b4Smrg /* size must be multiple of 4 or equal to whole texture size */ 18567117f1b4Smrg if ((width & 3) && (GLuint) width != destTex->Width) { 18577117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18587117f1b4Smrg "glTexSubImage%D(width)", dimensions); 18597117f1b4Smrg return GL_TRUE; 18607117f1b4Smrg } 18617117f1b4Smrg if ((height & 3) && (GLuint) height != destTex->Height) { 18627117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18637117f1b4Smrg "glTexSubImage%D(width)", dimensions); 18647117f1b4Smrg return GL_TRUE; 18657117f1b4Smrg } 18667117f1b4Smrg } 18677117f1b4Smrg 18687117f1b4Smrg return GL_FALSE; 18697117f1b4Smrg} 18707117f1b4Smrg 18717117f1b4Smrg 18727117f1b4Smrg/** 18737117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors. 18747117f1b4Smrg * 18757117f1b4Smrg * \param ctx GL context. 18767117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 18777117f1b4Smrg * \param target texture target given by the user. 18787117f1b4Smrg * \param level image level given by the user. 18797117f1b4Smrg * \param internalFormat internal format given by the user. 18807117f1b4Smrg * \param width image width given by the user. 18817117f1b4Smrg * \param height image height given by the user. 18827117f1b4Smrg * \param depth image depth given by the user. 18837117f1b4Smrg * \param border texture border. 18847117f1b4Smrg * 18857117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 18867117f1b4Smrg * 18877117f1b4Smrg * Verifies each of the parameters against the constants specified in 18887117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 18897117f1b4Smrg * OpenGL specification. 18907117f1b4Smrg */ 18917117f1b4Smrgstatic GLboolean 18927117f1b4Smrgcopytexture_error_check( GLcontext *ctx, GLuint dimensions, 18937117f1b4Smrg GLenum target, GLint level, GLint internalFormat, 18947117f1b4Smrg GLint width, GLint height, GLint border ) 18957117f1b4Smrg{ 18967117f1b4Smrg GLenum type; 18977117f1b4Smrg GLboolean sizeOK; 18987117f1b4Smrg GLint format; 18997117f1b4Smrg 19007117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 19017117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 19027117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19037117f1b4Smrg "glCopyTexImage%dD(level=%d)", dimensions, level); 19047117f1b4Smrg return GL_TRUE; 19057117f1b4Smrg } 19067117f1b4Smrg 19077117f1b4Smrg /* Check that the source buffer is complete */ 19087117f1b4Smrg if (ctx->ReadBuffer->Name) { 19097117f1b4Smrg _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 19107117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 19117117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 19127117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 19137117f1b4Smrg return GL_TRUE; 19147117f1b4Smrg } 19157117f1b4Smrg } 19167117f1b4Smrg 19177117f1b4Smrg /* Check border */ 19187117f1b4Smrg if (border < 0 || border > 1 || 19197117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 19207117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 19217117f1b4Smrg return GL_TRUE; 19227117f1b4Smrg } 19237117f1b4Smrg 19247117f1b4Smrg format = _mesa_base_tex_format(ctx, internalFormat); 19257117f1b4Smrg if (format < 0) { 19267117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19277117f1b4Smrg "glCopyTexImage%dD(internalFormat)", dimensions); 19287117f1b4Smrg return GL_TRUE; 19297117f1b4Smrg } 19307117f1b4Smrg 19317117f1b4Smrg /* NOTE: the format and type aren't really significant for 19327117f1b4Smrg * TestProxyTexImage(). Only the internalformat really matters. 19337117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, format)) { 19347117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 19357117f1b4Smrg "glCopyTexImage%dD(missing readbuffer)", dimensions); 19367117f1b4Smrg return GL_TRUE; 19377117f1b4Smrg } 19387117f1b4Smrg 19397117f1b4Smrg */ 19407117f1b4Smrg type = GL_FLOAT; 19417117f1b4Smrg 19427117f1b4Smrg /* Check target and call ctx->Driver.TestProxyTexImage() to check the 19437117f1b4Smrg * level, width, height and depth. 19447117f1b4Smrg */ 19457117f1b4Smrg if (dimensions == 1) { 19467117f1b4Smrg if (target == GL_TEXTURE_1D) { 19477117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 19487117f1b4Smrg level, internalFormat, 19497117f1b4Smrg format, type, 19507117f1b4Smrg width, 1, 1, border); 19517117f1b4Smrg } 19527117f1b4Smrg else { 19537117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 19547117f1b4Smrg return GL_TRUE; 19557117f1b4Smrg } 19567117f1b4Smrg } 19577117f1b4Smrg else if (dimensions == 2) { 19587117f1b4Smrg if (target == GL_TEXTURE_2D) { 19597117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 19607117f1b4Smrg level, internalFormat, 19617117f1b4Smrg format, type, 19627117f1b4Smrg width, height, 1, border); 19637117f1b4Smrg } 19647117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 19657117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 19667117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 19677117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 19687117f1b4Smrg return GL_TRUE; 19697117f1b4Smrg } 19707117f1b4Smrg sizeOK = (width == height) && 19717117f1b4Smrg ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 19727117f1b4Smrg level, internalFormat, format, type, 19737117f1b4Smrg width, height, 1, border); 19747117f1b4Smrg } 19757117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 19767117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 19777117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 19787117f1b4Smrg return GL_TRUE; 19797117f1b4Smrg } 19807117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, 19817117f1b4Smrg GL_PROXY_TEXTURE_RECTANGLE_NV, 19827117f1b4Smrg level, internalFormat, 19837117f1b4Smrg format, type, 19847117f1b4Smrg width, height, 1, border); 19857117f1b4Smrg } 1986c1f859d4Smrg else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1987c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1988c1f859d4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)"); 1989c1f859d4Smrg return GL_TRUE; 1990c1f859d4Smrg } 1991c1f859d4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1992c1f859d4Smrg GL_PROXY_TEXTURE_1D_ARRAY_EXT, 1993c1f859d4Smrg level, internalFormat, 1994c1f859d4Smrg format, type, 1995c1f859d4Smrg width, height, 1, border); 1996c1f859d4Smrg } 19977117f1b4Smrg else { 19987117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 19997117f1b4Smrg return GL_TRUE; 20007117f1b4Smrg } 20017117f1b4Smrg } 20027117f1b4Smrg else { 20037117f1b4Smrg _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 20047117f1b4Smrg return GL_TRUE; 20057117f1b4Smrg } 20067117f1b4Smrg 20077117f1b4Smrg if (!sizeOK) { 20087117f1b4Smrg if (dimensions == 1) { 20097117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20107117f1b4Smrg "glCopyTexImage1D(width=%d)", width); 20117117f1b4Smrg } 20127117f1b4Smrg else { 20137117f1b4Smrg ASSERT(dimensions == 2); 20147117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20157117f1b4Smrg "glCopyTexImage2D(width=%d, height=%d)", width, height); 20167117f1b4Smrg } 20177117f1b4Smrg return GL_TRUE; 20187117f1b4Smrg } 20197117f1b4Smrg 20207117f1b4Smrg if (is_compressed_format(ctx, internalFormat)) { 2021c1f859d4Smrg if (!target_can_be_compressed(ctx, target)) { 20227117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 20237117f1b4Smrg "glCopyTexImage%d(target)", dimensions); 20247117f1b4Smrg return GL_TRUE; 20257117f1b4Smrg } 20267117f1b4Smrg if (border != 0) { 20277117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20287117f1b4Smrg "glCopyTexImage%D(border!=0)", dimensions); 20297117f1b4Smrg return GL_TRUE; 20307117f1b4Smrg } 20317117f1b4Smrg } 20327117f1b4Smrg else if (is_depth_format(internalFormat)) { 20337117f1b4Smrg /* make sure we have depth/stencil buffers */ 20347117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 20357117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20367117f1b4Smrg "glCopyTexImage%D(no depth)", dimensions); 20377117f1b4Smrg return GL_TRUE; 20387117f1b4Smrg } 20397117f1b4Smrg } 20407117f1b4Smrg else if (is_depthstencil_format(internalFormat)) { 20417117f1b4Smrg /* make sure we have depth/stencil buffers */ 20427117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 20437117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20447117f1b4Smrg "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 20457117f1b4Smrg return GL_TRUE; 20467117f1b4Smrg } 20477117f1b4Smrg } 20487117f1b4Smrg 20497117f1b4Smrg /* if we get here, the parameters are OK */ 20507117f1b4Smrg return GL_FALSE; 20517117f1b4Smrg} 20527117f1b4Smrg 20537117f1b4Smrg 20547117f1b4Smrg/** 20557117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors. 2056c1f859d4Smrg * Note that this is the first part of error checking. 2057c1f859d4Smrg * See also copytexsubimage_error_check2() below for the second part. 20587117f1b4Smrg * 20597117f1b4Smrg * \param ctx GL context. 20607117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 20617117f1b4Smrg * \param target texture target given by the user. 20627117f1b4Smrg * \param level image level given by the user. 20637117f1b4Smrg * 20647117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 20657117f1b4Smrg */ 20667117f1b4Smrgstatic GLboolean 2067c1f859d4Smrgcopytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions, 2068c1f859d4Smrg GLenum target, GLint level) 20697117f1b4Smrg{ 20707117f1b4Smrg /* Check that the source buffer is complete */ 20717117f1b4Smrg if (ctx->ReadBuffer->Name) { 20727117f1b4Smrg _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 20737117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 20747117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 20757117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 20767117f1b4Smrg return GL_TRUE; 20777117f1b4Smrg } 20787117f1b4Smrg } 20797117f1b4Smrg 2080c1f859d4Smrg /* Check target */ 20817117f1b4Smrg if (dimensions == 1) { 20827117f1b4Smrg if (target != GL_TEXTURE_1D) { 20837117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 20847117f1b4Smrg return GL_TRUE; 20857117f1b4Smrg } 20867117f1b4Smrg } 20877117f1b4Smrg else if (dimensions == 2) { 20887117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 20897117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 20907117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 20917117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 20927117f1b4Smrg return GL_TRUE; 20937117f1b4Smrg } 20947117f1b4Smrg } 20957117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 20967117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 20977117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 20987117f1b4Smrg return GL_TRUE; 20997117f1b4Smrg } 21007117f1b4Smrg } 2101c1f859d4Smrg else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 2102c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 2103c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 2104c1f859d4Smrg return GL_TRUE; 2105c1f859d4Smrg } 2106c1f859d4Smrg } 21077117f1b4Smrg else if (target != GL_TEXTURE_2D) { 21087117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 21097117f1b4Smrg return GL_TRUE; 21107117f1b4Smrg } 21117117f1b4Smrg } 21127117f1b4Smrg else if (dimensions == 3) { 2113c1f859d4Smrg if (((target != GL_TEXTURE_2D_ARRAY_EXT) || 2114c1f859d4Smrg (!ctx->Extensions.MESA_texture_array)) 2115c1f859d4Smrg && (target != GL_TEXTURE_3D)) { 2116c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 2117c1f859d4Smrg return GL_TRUE; 21187117f1b4Smrg } 21197117f1b4Smrg } 21207117f1b4Smrg 21217117f1b4Smrg /* Check level */ 21227117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 21237117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21247117f1b4Smrg "glCopyTexSubImage%dD(level=%d)", dimensions, level); 21257117f1b4Smrg return GL_TRUE; 21267117f1b4Smrg } 21277117f1b4Smrg 21287117f1b4Smrg return GL_FALSE; 21297117f1b4Smrg} 21307117f1b4Smrg 2131c1f859d4Smrg 2132c1f859d4Smrg/** 2133c1f859d4Smrg * Second part of error checking for glCopyTexSubImage[12]D(). 2134c1f859d4Smrg * \param xoffset sub-image x offset given by the user. 2135c1f859d4Smrg * \param yoffset sub-image y offset given by the user. 2136c1f859d4Smrg * \param zoffset sub-image z offset given by the user. 2137c1f859d4Smrg * \param width image width given by the user. 2138c1f859d4Smrg * \param height image height given by the user. 2139c1f859d4Smrg */ 21407117f1b4Smrgstatic GLboolean 21417117f1b4Smrgcopytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 21427117f1b4Smrg GLenum target, GLint level, 21437117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 21447117f1b4Smrg GLsizei width, GLsizei height, 21457117f1b4Smrg const struct gl_texture_image *teximage ) 21467117f1b4Smrg{ 2147c1f859d4Smrg /* check that dest tex image exists */ 21487117f1b4Smrg if (!teximage) { 21497117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 21507117f1b4Smrg "glCopyTexSubImage%dD(undefined texture level: %d)", 21517117f1b4Smrg dimensions, level); 21527117f1b4Smrg return GL_TRUE; 21537117f1b4Smrg } 21547117f1b4Smrg 2155c1f859d4Smrg /* Check size */ 2156c1f859d4Smrg if (width < 0) { 2157c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 2158c1f859d4Smrg "glCopyTexSubImage%dD(width=%d)", dimensions, width); 2159c1f859d4Smrg return GL_TRUE; 2160c1f859d4Smrg } 2161c1f859d4Smrg if (dimensions > 1 && height < 0) { 2162c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 2163c1f859d4Smrg "glCopyTexSubImage%dD(height=%d)", dimensions, height); 2164c1f859d4Smrg return GL_TRUE; 2165c1f859d4Smrg } 2166c1f859d4Smrg 2167c1f859d4Smrg /* check x/y offsets */ 21687117f1b4Smrg if (xoffset < -((GLint)teximage->Border)) { 21697117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21707117f1b4Smrg "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 21717117f1b4Smrg return GL_TRUE; 21727117f1b4Smrg } 21737117f1b4Smrg if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 21747117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21757117f1b4Smrg "glCopyTexSubImage%dD(xoffset+width)", dimensions); 21767117f1b4Smrg return GL_TRUE; 21777117f1b4Smrg } 21787117f1b4Smrg if (dimensions > 1) { 21797117f1b4Smrg if (yoffset < -((GLint)teximage->Border)) { 21807117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21817117f1b4Smrg "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 21827117f1b4Smrg return GL_TRUE; 21837117f1b4Smrg } 21847117f1b4Smrg /* NOTE: we're adding the border here, not subtracting! */ 21857117f1b4Smrg if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 21867117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21877117f1b4Smrg "glCopyTexSubImage%dD(yoffset+height)", dimensions); 21887117f1b4Smrg return GL_TRUE; 21897117f1b4Smrg } 21907117f1b4Smrg } 21917117f1b4Smrg 2192c1f859d4Smrg /* check z offset */ 21937117f1b4Smrg if (dimensions > 2) { 21947117f1b4Smrg if (zoffset < -((GLint)teximage->Border)) { 21957117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21967117f1b4Smrg "glCopyTexSubImage%dD(zoffset)", dimensions); 21977117f1b4Smrg return GL_TRUE; 21987117f1b4Smrg } 21997117f1b4Smrg if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 22007117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 22017117f1b4Smrg "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 22027117f1b4Smrg return GL_TRUE; 22037117f1b4Smrg } 22047117f1b4Smrg } 22057117f1b4Smrg 22067117f1b4Smrg if (teximage->IsCompressed) { 2207c1f859d4Smrg if (!target_can_be_compressed(ctx, target)) { 22087117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 22097117f1b4Smrg "glCopyTexSubImage%d(target)", dimensions); 22107117f1b4Smrg return GL_TRUE; 22117117f1b4Smrg } 22127117f1b4Smrg /* offset must be multiple of 4 */ 22137117f1b4Smrg if ((xoffset & 3) || (yoffset & 3)) { 22147117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 22157117f1b4Smrg "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 22167117f1b4Smrg return GL_TRUE; 22177117f1b4Smrg } 22187117f1b4Smrg /* size must be multiple of 4 */ 22197117f1b4Smrg if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 22207117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 22217117f1b4Smrg "glCopyTexSubImage%D(width)", dimensions); 22227117f1b4Smrg return GL_TRUE; 22237117f1b4Smrg } 22247117f1b4Smrg if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 22257117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 22267117f1b4Smrg "glCopyTexSubImage%D(height)", dimensions); 22277117f1b4Smrg return GL_TRUE; 22287117f1b4Smrg } 22297117f1b4Smrg } 22307117f1b4Smrg 22317117f1b4Smrg if (teximage->InternalFormat == GL_YCBCR_MESA) { 22327117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 22337117f1b4Smrg return GL_TRUE; 22347117f1b4Smrg } 22357117f1b4Smrg 22367117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 22377117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2238c1f859d4Smrg "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 2239c1f859d4Smrg dimensions, teximage->_BaseFormat); 22407117f1b4Smrg return GL_TRUE; 22417117f1b4Smrg } 22427117f1b4Smrg 22437117f1b4Smrg if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 22447117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 22457117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 22467117f1b4Smrg "glCopyTexSubImage%D(no depth buffer)", 22477117f1b4Smrg dimensions); 22487117f1b4Smrg return GL_TRUE; 22497117f1b4Smrg } 22507117f1b4Smrg } 22517117f1b4Smrg else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 22527117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 22537117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 22547117f1b4Smrg "glCopyTexSubImage%D(no depth/stencil buffer)", 22557117f1b4Smrg dimensions); 22567117f1b4Smrg return GL_TRUE; 22577117f1b4Smrg } 22587117f1b4Smrg } 22597117f1b4Smrg 22607117f1b4Smrg /* if we get here, the parameters are OK */ 22617117f1b4Smrg return GL_FALSE; 22627117f1b4Smrg} 22637117f1b4Smrg 22647117f1b4Smrg 22657117f1b4Smrg/** 22667117f1b4Smrg * Get texture image. Called by glGetTexImage. 22677117f1b4Smrg * 22687117f1b4Smrg * \param target texture target. 22697117f1b4Smrg * \param level image level. 22707117f1b4Smrg * \param format pixel data format for returned image. 22717117f1b4Smrg * \param type pixel data type for returned image. 22727117f1b4Smrg * \param pixels returned pixel data. 22737117f1b4Smrg */ 22747117f1b4Smrgvoid GLAPIENTRY 22757117f1b4Smrg_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 22767117f1b4Smrg GLenum type, GLvoid *pixels ) 22777117f1b4Smrg{ 22787117f1b4Smrg const struct gl_texture_unit *texUnit; 22797117f1b4Smrg struct gl_texture_object *texObj; 22807117f1b4Smrg struct gl_texture_image *texImage; 22817117f1b4Smrg GLint maxLevels = 0; 22827117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 22837117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 22847117f1b4Smrg 22857117f1b4Smrg texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 22867117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 22877117f1b4Smrg if (!texObj || _mesa_is_proxy_texture(target)) { 22887117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 22897117f1b4Smrg return; 22907117f1b4Smrg } 22917117f1b4Smrg 22927117f1b4Smrg maxLevels = _mesa_max_texture_levels(ctx, target); 22937117f1b4Smrg ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 22947117f1b4Smrg 22957117f1b4Smrg if (level < 0 || level >= maxLevels) { 22967117f1b4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 22977117f1b4Smrg return; 22987117f1b4Smrg } 22997117f1b4Smrg 23007117f1b4Smrg if (_mesa_sizeof_packed_type(type) <= 0) { 23017117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 23027117f1b4Smrg return; 23037117f1b4Smrg } 23047117f1b4Smrg 23057117f1b4Smrg if (_mesa_components_in_format(format) <= 0 || 23067117f1b4Smrg format == GL_STENCIL_INDEX) { 23077117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 23087117f1b4Smrg return; 23097117f1b4Smrg } 23107117f1b4Smrg 23117117f1b4Smrg if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { 23127117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 23137117f1b4Smrg return; 23147117f1b4Smrg } 23157117f1b4Smrg 2316c1f859d4Smrg if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { 23177117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 23187117f1b4Smrg return; 23197117f1b4Smrg } 23207117f1b4Smrg 23217117f1b4Smrg if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { 23227117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 23237117f1b4Smrg return; 23247117f1b4Smrg } 23257117f1b4Smrg 23267117f1b4Smrg if (!ctx->Extensions.EXT_packed_depth_stencil 23277117f1b4Smrg && is_depthstencil_format(format)) { 23287117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 23297117f1b4Smrg return; 23307117f1b4Smrg } 23317117f1b4Smrg 23327117f1b4Smrg _mesa_lock_texture(ctx, texObj); 23337117f1b4Smrg { 23347117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 23357117f1b4Smrg if (!texImage) { 23367117f1b4Smrg /* invalid mipmap level, not an error */ 23377117f1b4Smrg goto out; 23387117f1b4Smrg } 23397117f1b4Smrg 23407117f1b4Smrg 23417117f1b4Smrg /* Make sure the requested image format is compatible with the 23427117f1b4Smrg * texture's format. Note that a color index texture can be converted 23437117f1b4Smrg * to RGBA so that combo is allowed. 23447117f1b4Smrg */ 2345c1f859d4Smrg if (_mesa_is_color_format(format) 2346c1f859d4Smrg && !_mesa_is_color_format(texImage->TexFormat->BaseFormat) 23477117f1b4Smrg && !is_index_format(texImage->TexFormat->BaseFormat)) { 23487117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 23497117f1b4Smrg goto out; 23507117f1b4Smrg } 23517117f1b4Smrg else if (is_index_format(format) 23527117f1b4Smrg && !is_index_format(texImage->TexFormat->BaseFormat)) { 23537117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 23547117f1b4Smrg goto out; 23557117f1b4Smrg } 23567117f1b4Smrg else if (is_depth_format(format) 23577117f1b4Smrg && !is_depth_format(texImage->TexFormat->BaseFormat) 23587117f1b4Smrg && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 23597117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 23607117f1b4Smrg goto out; 23617117f1b4Smrg } 23627117f1b4Smrg else if (is_ycbcr_format(format) 23637117f1b4Smrg && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 23647117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 23657117f1b4Smrg goto out; 23667117f1b4Smrg } 23677117f1b4Smrg else if (is_depthstencil_format(format) 23687117f1b4Smrg && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 23697117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 23707117f1b4Smrg goto out; 23717117f1b4Smrg } 23727117f1b4Smrg 23737117f1b4Smrg if (ctx->Pack.BufferObj->Name) { 23747117f1b4Smrg /* packing texture image into a PBO */ 23757117f1b4Smrg const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 23767117f1b4Smrg if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 23777117f1b4Smrg texImage->Height, texImage->Depth, 23787117f1b4Smrg format, type, pixels)) { 23797117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 23807117f1b4Smrg "glGetTexImage(invalid PBO access)"); 23817117f1b4Smrg goto out; 23827117f1b4Smrg } 23837117f1b4Smrg } 23847117f1b4Smrg 23857117f1b4Smrg /* typically, this will call _mesa_get_teximage() */ 23867117f1b4Smrg ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 23877117f1b4Smrg texObj, texImage); 23887117f1b4Smrg 23897117f1b4Smrg } 23907117f1b4Smrg out: 23917117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 23927117f1b4Smrg} 23937117f1b4Smrg 23947117f1b4Smrg 23957117f1b4Smrg 23967117f1b4Smrg/** 23977117f1b4Smrg * Check if the given texture image is bound to any framebuffer objects 23987117f1b4Smrg * and update/invalidate them. 23997117f1b4Smrg * XXX We're only checking the currently bound framebuffer object for now. 24007117f1b4Smrg * In the future, perhaps struct gl_texture_image should have a pointer (or 24017117f1b4Smrg * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to. 24027117f1b4Smrg */ 24037117f1b4Smrgstatic void 24047117f1b4Smrgupdate_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 24057117f1b4Smrg GLuint face, GLuint level) 24067117f1b4Smrg{ 24077117f1b4Smrg if (ctx->DrawBuffer->Name) { 24087117f1b4Smrg GLuint i; 24097117f1b4Smrg for (i = 0; i < BUFFER_COUNT; i++) { 24107117f1b4Smrg struct gl_renderbuffer_attachment *att = 24117117f1b4Smrg ctx->DrawBuffer->Attachment + i; 24127117f1b4Smrg if (att->Type == GL_TEXTURE && 24137117f1b4Smrg att->Texture == texObj && 24147117f1b4Smrg att->TextureLevel == level && 24157117f1b4Smrg att->CubeMapFace == face) { 24167117f1b4Smrg ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 24177117f1b4Smrg /* Tell driver about the new renderbuffer texture */ 24187117f1b4Smrg ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 24197117f1b4Smrg } 24207117f1b4Smrg } 24217117f1b4Smrg } 24227117f1b4Smrg} 24237117f1b4Smrg 24247117f1b4Smrg 24257117f1b4Smrg 24267117f1b4Smrg/* 24277117f1b4Smrg * Called from the API. Note that width includes the border. 24287117f1b4Smrg */ 24297117f1b4Smrgvoid GLAPIENTRY 24307117f1b4Smrg_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 24317117f1b4Smrg GLsizei width, GLint border, GLenum format, 24327117f1b4Smrg GLenum type, const GLvoid *pixels ) 24337117f1b4Smrg{ 24347117f1b4Smrg GLsizei postConvWidth = width; 24357117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 24367117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 24377117f1b4Smrg 2438c1f859d4Smrg#if FEATURE_convolve 2439c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 24407117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 24417117f1b4Smrg } 2442c1f859d4Smrg#endif 24437117f1b4Smrg 24447117f1b4Smrg if (target == GL_TEXTURE_1D) { 24457117f1b4Smrg /* non-proxy target */ 24467117f1b4Smrg struct gl_texture_unit *texUnit; 24477117f1b4Smrg struct gl_texture_object *texObj; 24487117f1b4Smrg struct gl_texture_image *texImage; 2449c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 24507117f1b4Smrg 24517117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 24527117f1b4Smrg format, type, 1, postConvWidth, 1, 1, border)) { 24537117f1b4Smrg return; /* error was recorded */ 24547117f1b4Smrg } 24557117f1b4Smrg 24567117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 24577117f1b4Smrg _mesa_update_state(ctx); 24587117f1b4Smrg 24597117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 24607117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 24617117f1b4Smrg _mesa_lock_texture(ctx, texObj); 24627117f1b4Smrg { 24637117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 24647117f1b4Smrg if (!texImage) { 24657117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 24667117f1b4Smrg goto out; 24677117f1b4Smrg } 24687117f1b4Smrg 24697117f1b4Smrg if (texImage->Data) { 24707117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 24717117f1b4Smrg } 24727117f1b4Smrg 24737117f1b4Smrg ASSERT(texImage->Data == NULL); 24747117f1b4Smrg 24757117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 24767117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 24777117f1b4Smrg postConvWidth, 1, 1, 24787117f1b4Smrg border, internalFormat); 24797117f1b4Smrg 24807117f1b4Smrg ASSERT(ctx->Driver.TexImage1D); 24817117f1b4Smrg 24827117f1b4Smrg /* Give the texture to the driver! <pixels> may be null! */ 24837117f1b4Smrg (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 24847117f1b4Smrg width, border, format, type, pixels, 24857117f1b4Smrg &ctx->Unpack, texObj, texImage); 24867117f1b4Smrg 24877117f1b4Smrg ASSERT(texImage->TexFormat); 24887117f1b4Smrg 24897117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 24907117f1b4Smrg 24917117f1b4Smrg /* state update */ 2492c1f859d4Smrg texObj->_Complete = GL_FALSE; 24937117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 24947117f1b4Smrg } 24957117f1b4Smrg out: 24967117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 24977117f1b4Smrg } 24987117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 24997117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 25007117f1b4Smrg struct gl_texture_image *texImage; 25017117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 25027117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 25037117f1b4Smrg format, type, 1, postConvWidth, 1, 1, border)) { 25047117f1b4Smrg /* when error, clear all proxy texture image parameters */ 25057117f1b4Smrg if (texImage) 25067117f1b4Smrg clear_teximage_fields(texImage); 25077117f1b4Smrg } 25087117f1b4Smrg else { 25097117f1b4Smrg /* no error, set the tex image parameters */ 25107117f1b4Smrg ASSERT(texImage); 25117117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 25127117f1b4Smrg postConvWidth, 1, 1, 25137117f1b4Smrg border, internalFormat); 25147117f1b4Smrg texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 25157117f1b4Smrg internalFormat, format, type); 25167117f1b4Smrg } 25177117f1b4Smrg } 25187117f1b4Smrg else { 25197117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 25207117f1b4Smrg return; 25217117f1b4Smrg } 25227117f1b4Smrg} 25237117f1b4Smrg 25247117f1b4Smrg 25257117f1b4Smrgvoid GLAPIENTRY 25267117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 25277117f1b4Smrg GLsizei width, GLsizei height, GLint border, 25287117f1b4Smrg GLenum format, GLenum type, 25297117f1b4Smrg const GLvoid *pixels ) 25307117f1b4Smrg{ 25317117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 25327117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25337117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 25347117f1b4Smrg 2535c1f859d4Smrg#if FEATURE_convolve 2536c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 25377117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 25387117f1b4Smrg &postConvHeight); 25397117f1b4Smrg } 2540c1f859d4Smrg#endif 25417117f1b4Smrg 25427117f1b4Smrg if (target == GL_TEXTURE_2D || 25437117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 25447117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 25457117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 25467117f1b4Smrg (ctx->Extensions.NV_texture_rectangle && 2547c1f859d4Smrg target == GL_TEXTURE_RECTANGLE_NV) || 2548c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2549c1f859d4Smrg target == GL_TEXTURE_1D_ARRAY_EXT)) { 25507117f1b4Smrg /* non-proxy target */ 25517117f1b4Smrg struct gl_texture_unit *texUnit; 25527117f1b4Smrg struct gl_texture_object *texObj; 25537117f1b4Smrg struct gl_texture_image *texImage; 2554c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 25557117f1b4Smrg 25567117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 25577117f1b4Smrg format, type, 2, postConvWidth, postConvHeight, 25587117f1b4Smrg 1, border)) { 25597117f1b4Smrg return; /* error was recorded */ 25607117f1b4Smrg } 25617117f1b4Smrg 25627117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 25637117f1b4Smrg _mesa_update_state(ctx); 25647117f1b4Smrg 25657117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 25667117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 25677117f1b4Smrg _mesa_lock_texture(ctx, texObj); 25687117f1b4Smrg { 25697117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 25707117f1b4Smrg if (!texImage) { 25717117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 25727117f1b4Smrg goto out; 25737117f1b4Smrg } 25747117f1b4Smrg 25757117f1b4Smrg if (texImage->Data) { 25767117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 25777117f1b4Smrg } 25787117f1b4Smrg 25797117f1b4Smrg ASSERT(texImage->Data == NULL); 25807117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 25817117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 25827117f1b4Smrg postConvWidth, postConvHeight, 1, 25837117f1b4Smrg border, internalFormat); 25847117f1b4Smrg 25857117f1b4Smrg ASSERT(ctx->Driver.TexImage2D); 25867117f1b4Smrg 25877117f1b4Smrg /* Give the texture to the driver! <pixels> may be null! */ 25887117f1b4Smrg (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 25897117f1b4Smrg width, height, border, format, type, pixels, 25907117f1b4Smrg &ctx->Unpack, texObj, texImage); 25917117f1b4Smrg 25927117f1b4Smrg ASSERT(texImage->TexFormat); 25937117f1b4Smrg 25947117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 25957117f1b4Smrg 25967117f1b4Smrg /* state update */ 2597c1f859d4Smrg texObj->_Complete = GL_FALSE; 25987117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 25997117f1b4Smrg } 26007117f1b4Smrg out: 26017117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 26027117f1b4Smrg } 26037117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 26047117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 26057117f1b4Smrg ctx->Extensions.ARB_texture_cube_map) || 26067117f1b4Smrg (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 2607c1f859d4Smrg ctx->Extensions.NV_texture_rectangle) || 2608c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2609c1f859d4Smrg target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { 26107117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 26117117f1b4Smrg struct gl_texture_image *texImage; 26127117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 26137117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 26147117f1b4Smrg format, type, 2, postConvWidth, postConvHeight, 26157117f1b4Smrg 1, border)) { 26167117f1b4Smrg /* when error, clear all proxy texture image parameters */ 26177117f1b4Smrg if (texImage) 2618c1f859d4Smrg clear_teximage_fields(texImage); 26197117f1b4Smrg } 26207117f1b4Smrg else { 26217117f1b4Smrg /* no error, set the tex image parameters */ 26227117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 26237117f1b4Smrg postConvWidth, postConvHeight, 1, 26247117f1b4Smrg border, internalFormat); 26257117f1b4Smrg texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 26267117f1b4Smrg internalFormat, format, type); 26277117f1b4Smrg } 26287117f1b4Smrg } 26297117f1b4Smrg else { 26307117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 26317117f1b4Smrg return; 26327117f1b4Smrg } 26337117f1b4Smrg} 26347117f1b4Smrg 26357117f1b4Smrg 26367117f1b4Smrg/* 26377117f1b4Smrg * Called by the API or display list executor. 26387117f1b4Smrg * Note that width and height include the border. 26397117f1b4Smrg */ 26407117f1b4Smrgvoid GLAPIENTRY 26417117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 26427117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 26437117f1b4Smrg GLint border, GLenum format, GLenum type, 26447117f1b4Smrg const GLvoid *pixels ) 26457117f1b4Smrg{ 26467117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 26477117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 26487117f1b4Smrg 2649c1f859d4Smrg if (target == GL_TEXTURE_3D || 2650c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2651c1f859d4Smrg target == GL_TEXTURE_2D_ARRAY_EXT)) { 26527117f1b4Smrg /* non-proxy target */ 26537117f1b4Smrg struct gl_texture_unit *texUnit; 26547117f1b4Smrg struct gl_texture_object *texObj; 26557117f1b4Smrg struct gl_texture_image *texImage; 2656c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 26577117f1b4Smrg 26587117f1b4Smrg if (texture_error_check(ctx, target, level, (GLint) internalFormat, 26597117f1b4Smrg format, type, 3, width, height, depth, border)) { 26607117f1b4Smrg return; /* error was recorded */ 26617117f1b4Smrg } 26627117f1b4Smrg 26637117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 26647117f1b4Smrg _mesa_update_state(ctx); 26657117f1b4Smrg 26667117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 26677117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 26687117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26697117f1b4Smrg { 26707117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 26717117f1b4Smrg if (!texImage) { 26727117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 26737117f1b4Smrg goto out; 26747117f1b4Smrg } 26757117f1b4Smrg 26767117f1b4Smrg if (texImage->Data) { 26777117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 26787117f1b4Smrg } 26797117f1b4Smrg 26807117f1b4Smrg ASSERT(texImage->Data == NULL); 26817117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 26827117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 26837117f1b4Smrg width, height, depth, 26847117f1b4Smrg border, internalFormat); 26857117f1b4Smrg 26867117f1b4Smrg ASSERT(ctx->Driver.TexImage3D); 26877117f1b4Smrg 26887117f1b4Smrg /* Give the texture to the driver! <pixels> may be null! */ 26897117f1b4Smrg (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, 26907117f1b4Smrg width, height, depth, border, format, type, 26917117f1b4Smrg pixels, &ctx->Unpack, texObj, texImage); 26927117f1b4Smrg 26937117f1b4Smrg ASSERT(texImage->TexFormat); 26947117f1b4Smrg 26957117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 26967117f1b4Smrg 26977117f1b4Smrg /* state update */ 2698c1f859d4Smrg texObj->_Complete = GL_FALSE; 26997117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 27007117f1b4Smrg } 27017117f1b4Smrg out: 27027117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 27037117f1b4Smrg } 2704c1f859d4Smrg else if (target == GL_PROXY_TEXTURE_3D || 2705c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2706c1f859d4Smrg target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { 27077117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 27087117f1b4Smrg struct gl_texture_image *texImage; 27097117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 27107117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 27117117f1b4Smrg format, type, 3, width, height, depth, border)) { 27127117f1b4Smrg /* when error, clear all proxy texture image parameters */ 27137117f1b4Smrg if (texImage) 27147117f1b4Smrg clear_teximage_fields(texImage); 27157117f1b4Smrg } 27167117f1b4Smrg else { 27177117f1b4Smrg /* no error, set the tex image parameters */ 27187117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 27197117f1b4Smrg depth, border, internalFormat); 27207117f1b4Smrg texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 27217117f1b4Smrg internalFormat, format, type); 27227117f1b4Smrg } 27237117f1b4Smrg } 27247117f1b4Smrg else { 27257117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 27267117f1b4Smrg return; 27277117f1b4Smrg } 27287117f1b4Smrg} 27297117f1b4Smrg 27307117f1b4Smrg 27317117f1b4Smrgvoid GLAPIENTRY 27327117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 27337117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 27347117f1b4Smrg GLint border, GLenum format, GLenum type, 27357117f1b4Smrg const GLvoid *pixels ) 27367117f1b4Smrg{ 27377117f1b4Smrg _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 27387117f1b4Smrg depth, border, format, type, pixels); 27397117f1b4Smrg} 27407117f1b4Smrg 27417117f1b4Smrg 27427117f1b4Smrg 27437117f1b4Smrgvoid GLAPIENTRY 27447117f1b4Smrg_mesa_TexSubImage1D( GLenum target, GLint level, 27457117f1b4Smrg GLint xoffset, GLsizei width, 27467117f1b4Smrg GLenum format, GLenum type, 27477117f1b4Smrg const GLvoid *pixels ) 27487117f1b4Smrg{ 27497117f1b4Smrg GLsizei postConvWidth = width; 27507117f1b4Smrg struct gl_texture_unit *texUnit; 27517117f1b4Smrg struct gl_texture_object *texObj; 27527117f1b4Smrg struct gl_texture_image *texImage = NULL; 27537117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27547117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 27557117f1b4Smrg 27567117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 27577117f1b4Smrg _mesa_update_state(ctx); 27587117f1b4Smrg 2759c1f859d4Smrg#if FEATURE_convolve 27607117f1b4Smrg /* XXX should test internal format */ 2761c1f859d4Smrg if (_mesa_is_color_format(format)) { 27627117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 27637117f1b4Smrg } 2764c1f859d4Smrg#endif 27657117f1b4Smrg 27667117f1b4Smrg if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 27677117f1b4Smrg postConvWidth, 1, 1, format, type)) { 27687117f1b4Smrg return; /* error was detected */ 27697117f1b4Smrg } 27707117f1b4Smrg 27717117f1b4Smrg 27727117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 27737117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 27747117f1b4Smrg assert(texObj); 27757117f1b4Smrg 27767117f1b4Smrg _mesa_lock_texture(ctx, texObj); 27777117f1b4Smrg { 27787117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 27797117f1b4Smrg 27807117f1b4Smrg if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 27817117f1b4Smrg postConvWidth, 1, 1, format, type, texImage)) { 27827117f1b4Smrg goto out; /* error was detected */ 27837117f1b4Smrg } 27847117f1b4Smrg 27857117f1b4Smrg if (width == 0) 27867117f1b4Smrg goto out; /* no-op, not an error */ 27877117f1b4Smrg 27887117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 27897117f1b4Smrg xoffset += texImage->Border; 27907117f1b4Smrg 27917117f1b4Smrg ASSERT(ctx->Driver.TexSubImage1D); 27927117f1b4Smrg (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 27937117f1b4Smrg format, type, pixels, &ctx->Unpack, 27947117f1b4Smrg texObj, texImage); 27957117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 27967117f1b4Smrg } 27977117f1b4Smrg out: 27987117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 27997117f1b4Smrg} 28007117f1b4Smrg 28017117f1b4Smrg 28027117f1b4Smrgvoid GLAPIENTRY 28037117f1b4Smrg_mesa_TexSubImage2D( GLenum target, GLint level, 28047117f1b4Smrg GLint xoffset, GLint yoffset, 28057117f1b4Smrg GLsizei width, GLsizei height, 28067117f1b4Smrg GLenum format, GLenum type, 28077117f1b4Smrg const GLvoid *pixels ) 28087117f1b4Smrg{ 28097117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 28107117f1b4Smrg struct gl_texture_unit *texUnit; 28117117f1b4Smrg struct gl_texture_object *texObj; 28127117f1b4Smrg struct gl_texture_image *texImage; 28137117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28147117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28157117f1b4Smrg 28167117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 28177117f1b4Smrg _mesa_update_state(ctx); 28187117f1b4Smrg 2819c1f859d4Smrg#if FEATURE_convolve 28207117f1b4Smrg /* XXX should test internal format */ 2821c1f859d4Smrg if (_mesa_is_color_format(format)) { 28227117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 28237117f1b4Smrg &postConvHeight); 28247117f1b4Smrg } 2825c1f859d4Smrg#endif 28267117f1b4Smrg 28277117f1b4Smrg if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 28287117f1b4Smrg postConvWidth, postConvHeight, 1, format, type)) { 28297117f1b4Smrg return; /* error was detected */ 28307117f1b4Smrg } 28317117f1b4Smrg 28327117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 28337117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 28347117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28357117f1b4Smrg { 28367117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 28377117f1b4Smrg 28387117f1b4Smrg if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 28397117f1b4Smrg postConvWidth, postConvHeight, 1, format, type, 28407117f1b4Smrg texImage)) { 28417117f1b4Smrg goto out; /* error was detected */ 28427117f1b4Smrg } 28437117f1b4Smrg 28447117f1b4Smrg if (width == 0 || height == 0) 28457117f1b4Smrg goto out; /* no-op, not an error */ 28467117f1b4Smrg 28477117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 28487117f1b4Smrg xoffset += texImage->Border; 28497117f1b4Smrg yoffset += texImage->Border; 28507117f1b4Smrg 28517117f1b4Smrg ASSERT(ctx->Driver.TexSubImage2D); 28527117f1b4Smrg (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 28537117f1b4Smrg width, height, format, type, pixels, 28547117f1b4Smrg &ctx->Unpack, texObj, texImage); 28557117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 28567117f1b4Smrg } 28577117f1b4Smrg out: 28587117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28597117f1b4Smrg} 28607117f1b4Smrg 28617117f1b4Smrg 28627117f1b4Smrg 28637117f1b4Smrgvoid GLAPIENTRY 28647117f1b4Smrg_mesa_TexSubImage3D( GLenum target, GLint level, 28657117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 28667117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 28677117f1b4Smrg GLenum format, GLenum type, 28687117f1b4Smrg const GLvoid *pixels ) 28697117f1b4Smrg{ 28707117f1b4Smrg struct gl_texture_unit *texUnit; 28717117f1b4Smrg struct gl_texture_object *texObj; 28727117f1b4Smrg struct gl_texture_image *texImage; 28737117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28747117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28757117f1b4Smrg 28767117f1b4Smrg if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 28777117f1b4Smrg _mesa_update_state(ctx); 28787117f1b4Smrg 28797117f1b4Smrg if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 28807117f1b4Smrg width, height, depth, format, type)) { 28817117f1b4Smrg return; /* error was detected */ 28827117f1b4Smrg } 28837117f1b4Smrg 28847117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 28857117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 28867117f1b4Smrg 28877117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28887117f1b4Smrg { 28897117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 28907117f1b4Smrg 28917117f1b4Smrg if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, 28927117f1b4Smrg width, height, depth, format, type, texImage)) { 28937117f1b4Smrg goto out; /* error was detected */ 28947117f1b4Smrg } 28957117f1b4Smrg 28967117f1b4Smrg if (width == 0 || height == 0 || height == 0) 28977117f1b4Smrg goto out; /* no-op, not an error */ 28987117f1b4Smrg 28997117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 29007117f1b4Smrg xoffset += texImage->Border; 29017117f1b4Smrg yoffset += texImage->Border; 29027117f1b4Smrg zoffset += texImage->Border; 29037117f1b4Smrg 29047117f1b4Smrg ASSERT(ctx->Driver.TexSubImage3D); 29057117f1b4Smrg (*ctx->Driver.TexSubImage3D)(ctx, target, level, 29067117f1b4Smrg xoffset, yoffset, zoffset, 29077117f1b4Smrg width, height, depth, 29087117f1b4Smrg format, type, pixels, 29097117f1b4Smrg &ctx->Unpack, texObj, texImage ); 29107117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 29117117f1b4Smrg } 29127117f1b4Smrg out: 29137117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29147117f1b4Smrg} 29157117f1b4Smrg 29167117f1b4Smrg 29177117f1b4Smrg 29187117f1b4Smrgvoid GLAPIENTRY 29197117f1b4Smrg_mesa_CopyTexImage1D( GLenum target, GLint level, 29207117f1b4Smrg GLenum internalFormat, 29217117f1b4Smrg GLint x, GLint y, 29227117f1b4Smrg GLsizei width, GLint border ) 29237117f1b4Smrg{ 29247117f1b4Smrg struct gl_texture_unit *texUnit; 29257117f1b4Smrg struct gl_texture_object *texObj; 29267117f1b4Smrg struct gl_texture_image *texImage; 29277117f1b4Smrg GLsizei postConvWidth = width; 2928c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 29297117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29307117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29317117f1b4Smrg 2932c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 29337117f1b4Smrg _mesa_update_state(ctx); 29347117f1b4Smrg 2935c1f859d4Smrg#if FEATURE_convolve 2936c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 29377117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 29387117f1b4Smrg } 2939c1f859d4Smrg#endif 29407117f1b4Smrg 29417117f1b4Smrg if (copytexture_error_check(ctx, 1, target, level, internalFormat, 29427117f1b4Smrg postConvWidth, 1, border)) 29437117f1b4Smrg return; 29447117f1b4Smrg 29457117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 29467117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 29477117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29487117f1b4Smrg { 29497117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 29507117f1b4Smrg if (!texImage) { 29517117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 29527117f1b4Smrg goto out; 29537117f1b4Smrg } 29547117f1b4Smrg 29557117f1b4Smrg if (texImage->Data) { 29567117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 29577117f1b4Smrg } 29587117f1b4Smrg 29597117f1b4Smrg ASSERT(texImage->Data == NULL); 29607117f1b4Smrg 29617117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 29627117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 29637117f1b4Smrg border, internalFormat); 29647117f1b4Smrg 29657117f1b4Smrg 29667117f1b4Smrg ASSERT(ctx->Driver.CopyTexImage1D); 29677117f1b4Smrg (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 29687117f1b4Smrg x, y, width, border); 29697117f1b4Smrg 29707117f1b4Smrg ASSERT(texImage->TexFormat); 29717117f1b4Smrg 29727117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 29737117f1b4Smrg 29747117f1b4Smrg /* state update */ 2975c1f859d4Smrg texObj->_Complete = GL_FALSE; 29767117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 29777117f1b4Smrg } 29787117f1b4Smrg out: 29797117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29807117f1b4Smrg} 29817117f1b4Smrg 29827117f1b4Smrg 29837117f1b4Smrg 29847117f1b4Smrgvoid GLAPIENTRY 29857117f1b4Smrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 29867117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height, 29877117f1b4Smrg GLint border ) 29887117f1b4Smrg{ 29897117f1b4Smrg struct gl_texture_unit *texUnit; 29907117f1b4Smrg struct gl_texture_object *texObj; 29917117f1b4Smrg struct gl_texture_image *texImage; 29927117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 2993c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 29947117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29957117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29967117f1b4Smrg 2997c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 29987117f1b4Smrg _mesa_update_state(ctx); 29997117f1b4Smrg 3000c1f859d4Smrg#if FEATURE_convolve 3001c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 30027117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 30037117f1b4Smrg &postConvHeight); 30047117f1b4Smrg } 3005c1f859d4Smrg#endif 30067117f1b4Smrg 30077117f1b4Smrg if (copytexture_error_check(ctx, 2, target, level, internalFormat, 30087117f1b4Smrg postConvWidth, postConvHeight, border)) 30097117f1b4Smrg return; 30107117f1b4Smrg 30117117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 30127117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 30137117f1b4Smrg 30147117f1b4Smrg _mesa_lock_texture(ctx, texObj); 30157117f1b4Smrg { 30167117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 30177117f1b4Smrg 30187117f1b4Smrg if (!texImage) { 30197117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 30207117f1b4Smrg goto out; 30217117f1b4Smrg } 30227117f1b4Smrg 30237117f1b4Smrg if (texImage->Data) { 30247117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 30257117f1b4Smrg } 30267117f1b4Smrg 30277117f1b4Smrg ASSERT(texImage->Data == NULL); 30287117f1b4Smrg 30297117f1b4Smrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 30307117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 30317117f1b4Smrg postConvWidth, postConvHeight, 1, 30327117f1b4Smrg border, internalFormat); 30337117f1b4Smrg 30347117f1b4Smrg ASSERT(ctx->Driver.CopyTexImage2D); 30357117f1b4Smrg (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 30367117f1b4Smrg x, y, width, height, border); 30377117f1b4Smrg 30387117f1b4Smrg ASSERT(texImage->TexFormat); 30397117f1b4Smrg 30407117f1b4Smrg update_fbo_texture(ctx, texObj, face, level); 30417117f1b4Smrg 30427117f1b4Smrg /* state update */ 3043c1f859d4Smrg texObj->_Complete = GL_FALSE; 30447117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 30457117f1b4Smrg } 30467117f1b4Smrg out: 30477117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 30487117f1b4Smrg} 30497117f1b4Smrg 30507117f1b4Smrg 30517117f1b4Smrgvoid GLAPIENTRY 30527117f1b4Smrg_mesa_CopyTexSubImage1D( GLenum target, GLint level, 30537117f1b4Smrg GLint xoffset, GLint x, GLint y, GLsizei width ) 30547117f1b4Smrg{ 30557117f1b4Smrg struct gl_texture_unit *texUnit; 30567117f1b4Smrg struct gl_texture_object *texObj; 30577117f1b4Smrg struct gl_texture_image *texImage; 30587117f1b4Smrg GLsizei postConvWidth = width; 3059c1f859d4Smrg GLint yoffset = 0; 3060c1f859d4Smrg GLsizei height = 1; 3061c1f859d4Smrg 30627117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 30637117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 30647117f1b4Smrg 3065c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 30667117f1b4Smrg _mesa_update_state(ctx); 30677117f1b4Smrg 3068c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 1, target, level)) 30697117f1b4Smrg return; 30707117f1b4Smrg 30717117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 30727117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 30737117f1b4Smrg 30747117f1b4Smrg _mesa_lock_texture(ctx, texObj); 30757117f1b4Smrg { 30767117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 30777117f1b4Smrg 3078c1f859d4Smrg#if FEATURE_convolve 3079c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3080c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 3081c1f859d4Smrg } 3082c1f859d4Smrg#endif 3083c1f859d4Smrg 30847117f1b4Smrg if (copytexsubimage_error_check2(ctx, 1, target, level, 30857117f1b4Smrg xoffset, 0, 0, postConvWidth, 1, 30867117f1b4Smrg texImage)) 30877117f1b4Smrg goto out; 30887117f1b4Smrg 30897117f1b4Smrg 30907117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 30917117f1b4Smrg xoffset += texImage->Border; 30927117f1b4Smrg 3093c1f859d4Smrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3094c1f859d4Smrg &width, &height)) { 3095c1f859d4Smrg ASSERT(ctx->Driver.CopyTexSubImage1D); 3096c1f859d4Smrg ctx->Driver.CopyTexSubImage1D(ctx, target, level, 3097c1f859d4Smrg xoffset, x, y, width); 3098c1f859d4Smrg } 3099c1f859d4Smrg 31007117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 31017117f1b4Smrg } 31027117f1b4Smrg out: 31037117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 31047117f1b4Smrg} 31057117f1b4Smrg 31067117f1b4Smrg 31077117f1b4Smrg 31087117f1b4Smrgvoid GLAPIENTRY 31097117f1b4Smrg_mesa_CopyTexSubImage2D( GLenum target, GLint level, 31107117f1b4Smrg GLint xoffset, GLint yoffset, 31117117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 31127117f1b4Smrg{ 31137117f1b4Smrg struct gl_texture_unit *texUnit; 31147117f1b4Smrg struct gl_texture_object *texObj; 31157117f1b4Smrg struct gl_texture_image *texImage; 31167117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 31177117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 31187117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 31197117f1b4Smrg 3120c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 31217117f1b4Smrg _mesa_update_state(ctx); 31227117f1b4Smrg 3123c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 2, target, level)) 31247117f1b4Smrg return; 31257117f1b4Smrg 31267117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 31277117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 31287117f1b4Smrg 31297117f1b4Smrg _mesa_lock_texture(ctx, texObj); 31307117f1b4Smrg { 31317117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 31327117f1b4Smrg 3133c1f859d4Smrg#if FEATURE_convolve 3134c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3135c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 2, 3136c1f859d4Smrg &postConvWidth, &postConvHeight); 3137c1f859d4Smrg } 3138c1f859d4Smrg#endif 3139c1f859d4Smrg 31407117f1b4Smrg if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 31417117f1b4Smrg postConvWidth, postConvHeight, texImage)) 31427117f1b4Smrg goto out; 31437117f1b4Smrg 31447117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 31457117f1b4Smrg xoffset += texImage->Border; 31467117f1b4Smrg yoffset += texImage->Border; 3147c1f859d4Smrg 3148c1f859d4Smrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3149c1f859d4Smrg &width, &height)) { 3150c1f859d4Smrg ASSERT(ctx->Driver.CopyTexSubImage2D); 3151c1f859d4Smrg ctx->Driver.CopyTexSubImage2D(ctx, target, level, 31527117f1b4Smrg xoffset, yoffset, x, y, width, height); 3153c1f859d4Smrg } 3154c1f859d4Smrg 31557117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 31567117f1b4Smrg } 31577117f1b4Smrg out: 31587117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 31597117f1b4Smrg} 31607117f1b4Smrg 31617117f1b4Smrg 31627117f1b4Smrg 31637117f1b4Smrgvoid GLAPIENTRY 31647117f1b4Smrg_mesa_CopyTexSubImage3D( GLenum target, GLint level, 31657117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 31667117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 31677117f1b4Smrg{ 31687117f1b4Smrg struct gl_texture_unit *texUnit; 31697117f1b4Smrg struct gl_texture_object *texObj; 31707117f1b4Smrg struct gl_texture_image *texImage; 31717117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 31727117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 31737117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 31747117f1b4Smrg 3175c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 31767117f1b4Smrg _mesa_update_state(ctx); 31777117f1b4Smrg 3178c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 3, target, level)) 31797117f1b4Smrg return; 31807117f1b4Smrg 31817117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 31827117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 31837117f1b4Smrg 31847117f1b4Smrg _mesa_lock_texture(ctx, texObj); 31857117f1b4Smrg { 31867117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 31877117f1b4Smrg 3188c1f859d4Smrg#if FEATURE_convolve 3189c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3190c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 2, 3191c1f859d4Smrg &postConvWidth, &postConvHeight); 3192c1f859d4Smrg } 3193c1f859d4Smrg#endif 3194c1f859d4Smrg 31957117f1b4Smrg if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 31967117f1b4Smrg zoffset, postConvWidth, postConvHeight, 31977117f1b4Smrg texImage)) 31987117f1b4Smrg goto out; 31997117f1b4Smrg 32007117f1b4Smrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 32017117f1b4Smrg xoffset += texImage->Border; 32027117f1b4Smrg yoffset += texImage->Border; 32037117f1b4Smrg zoffset += texImage->Border; 32047117f1b4Smrg 3205c1f859d4Smrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3206c1f859d4Smrg &width, &height)) { 3207c1f859d4Smrg ASSERT(ctx->Driver.CopyTexSubImage3D); 3208c1f859d4Smrg ctx->Driver.CopyTexSubImage3D(ctx, target, level, 32097117f1b4Smrg xoffset, yoffset, zoffset, 32107117f1b4Smrg x, y, width, height); 3211c1f859d4Smrg } 3212c1f859d4Smrg 32137117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 32147117f1b4Smrg } 32157117f1b4Smrg out: 32167117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 32177117f1b4Smrg} 32187117f1b4Smrg 32197117f1b4Smrg 32207117f1b4Smrg 32217117f1b4Smrg 32227117f1b4Smrg/**********************************************************************/ 32237117f1b4Smrg/****** Compressed Textures ******/ 32247117f1b4Smrg/**********************************************************************/ 32257117f1b4Smrg 32267117f1b4Smrg 32277117f1b4Smrg/** 32287117f1b4Smrg * Error checking for glCompressedTexImage[123]D(). 32297117f1b4Smrg * \return error code or GL_NO_ERROR. 32307117f1b4Smrg */ 32317117f1b4Smrgstatic GLenum 32327117f1b4Smrgcompressed_texture_error_check(GLcontext *ctx, GLint dimensions, 32337117f1b4Smrg GLenum target, GLint level, 32347117f1b4Smrg GLenum internalFormat, GLsizei width, 32357117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 32367117f1b4Smrg GLsizei imageSize) 32377117f1b4Smrg{ 32387117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 32397117f1b4Smrg 32407117f1b4Smrg if (dimensions == 1) { 32417117f1b4Smrg /* 1D compressed textures not allowed */ 32427117f1b4Smrg return GL_INVALID_ENUM; 32437117f1b4Smrg } 32447117f1b4Smrg else if (dimensions == 2) { 32457117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 32467117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 32477117f1b4Smrg } 32487117f1b4Smrg else if (target == GL_TEXTURE_2D) { 32497117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 32507117f1b4Smrg } 32517117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 32527117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 32537117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32547117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 32557117f1b4Smrg } 32567117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 32577117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 32587117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 32597117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32607117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 32617117f1b4Smrg } 32627117f1b4Smrg else { 32637117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32647117f1b4Smrg } 32657117f1b4Smrg } 32667117f1b4Smrg else if (dimensions == 3) { 32677117f1b4Smrg /* 3D compressed textures not allowed */ 32687117f1b4Smrg return GL_INVALID_ENUM; 32697117f1b4Smrg } 32707117f1b4Smrg 32717117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 32727117f1b4Smrg 32737117f1b4Smrg /* This will detect any invalid internalFormat value */ 32747117f1b4Smrg if (!is_compressed_format(ctx, internalFormat)) 32757117f1b4Smrg return GL_INVALID_ENUM; 32767117f1b4Smrg 32777117f1b4Smrg /* This should really never fail */ 32787117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) 32797117f1b4Smrg return GL_INVALID_ENUM; 32807117f1b4Smrg 32817117f1b4Smrg if (border != 0) 32827117f1b4Smrg return GL_INVALID_VALUE; 32837117f1b4Smrg 32847117f1b4Smrg /* 32857117f1b4Smrg * XXX We should probably use the proxy texture error check function here. 32867117f1b4Smrg */ 32877117f1b4Smrg if (width < 1 || width > maxTextureSize || 3288c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) 32897117f1b4Smrg return GL_INVALID_VALUE; 32907117f1b4Smrg 32917117f1b4Smrg if ((height < 1 || height > maxTextureSize || 3292c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) 32937117f1b4Smrg && dimensions > 1) 32947117f1b4Smrg return GL_INVALID_VALUE; 32957117f1b4Smrg 32967117f1b4Smrg if ((depth < 1 || depth > maxTextureSize || 3297c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) 32987117f1b4Smrg && dimensions > 2) 32997117f1b4Smrg return GL_INVALID_VALUE; 33007117f1b4Smrg 33017117f1b4Smrg /* For cube map, width must equal height */ 33027117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 33037117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 33047117f1b4Smrg return GL_INVALID_VALUE; 33057117f1b4Smrg 33067117f1b4Smrg if (level < 0 || level >= maxLevels) 33077117f1b4Smrg return GL_INVALID_VALUE; 33087117f1b4Smrg 33097117f1b4Smrg expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 33107117f1b4Smrg depth, internalFormat); 33117117f1b4Smrg if (expectedSize != imageSize) 33127117f1b4Smrg return GL_INVALID_VALUE; 33137117f1b4Smrg 33147117f1b4Smrg#if FEATURE_EXT_texture_sRGB 33157117f1b4Smrg if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 33167117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 33177117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 33187117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 33197117f1b4Smrg && border != 0) { 33207117f1b4Smrg return GL_INVALID_OPERATION; 33217117f1b4Smrg } 33227117f1b4Smrg#endif 33237117f1b4Smrg 33247117f1b4Smrg return GL_NO_ERROR; 33257117f1b4Smrg} 33267117f1b4Smrg 33277117f1b4Smrg 33287117f1b4Smrg/** 33297117f1b4Smrg * Error checking for glCompressedTexSubImage[123]D(). 33307117f1b4Smrg * \warning There are some bad assumptions here about the size of compressed 33317117f1b4Smrg * texture tiles (multiple of 4) used to test the validity of the 33327117f1b4Smrg * offset and size parameters. 33337117f1b4Smrg * \return error code or GL_NO_ERROR. 33347117f1b4Smrg */ 33357117f1b4Smrgstatic GLenum 33367117f1b4Smrgcompressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 33377117f1b4Smrg GLenum target, GLint level, 33387117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 33397117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 33407117f1b4Smrg GLenum format, GLsizei imageSize) 33417117f1b4Smrg{ 33427117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 33437117f1b4Smrg (void) zoffset; 33447117f1b4Smrg 33457117f1b4Smrg if (dimensions == 1) { 33467117f1b4Smrg /* 1D compressed textures not allowed */ 33477117f1b4Smrg return GL_INVALID_ENUM; 33487117f1b4Smrg } 33497117f1b4Smrg else if (dimensions == 2) { 33507117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 33517117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 33527117f1b4Smrg } 33537117f1b4Smrg else if (target == GL_TEXTURE_2D) { 33547117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 33557117f1b4Smrg } 33567117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 33577117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 33587117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 33597117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 33607117f1b4Smrg } 33617117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 33627117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 33637117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 33647117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 33657117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 33667117f1b4Smrg } 33677117f1b4Smrg else { 33687117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 33697117f1b4Smrg } 33707117f1b4Smrg } 33717117f1b4Smrg else if (dimensions == 3) { 33727117f1b4Smrg /* 3D compressed textures not allowed */ 33737117f1b4Smrg return GL_INVALID_ENUM; 33747117f1b4Smrg } 33757117f1b4Smrg 33767117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 33777117f1b4Smrg 33787117f1b4Smrg /* this will catch any invalid compressed format token */ 33797117f1b4Smrg if (!is_compressed_format(ctx, format)) 33807117f1b4Smrg return GL_INVALID_ENUM; 33817117f1b4Smrg 33827117f1b4Smrg if (width < 1 || width > maxTextureSize) 33837117f1b4Smrg return GL_INVALID_VALUE; 33847117f1b4Smrg 33857117f1b4Smrg if ((height < 1 || height > maxTextureSize) 33867117f1b4Smrg && dimensions > 1) 33877117f1b4Smrg return GL_INVALID_VALUE; 33887117f1b4Smrg 33897117f1b4Smrg if (level < 0 || level >= maxLevels) 33907117f1b4Smrg return GL_INVALID_VALUE; 33917117f1b4Smrg 33927117f1b4Smrg /* XXX these tests are specific to the compressed format. 33937117f1b4Smrg * this code should be generalized in some way. 33947117f1b4Smrg */ 33957117f1b4Smrg if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 33967117f1b4Smrg return GL_INVALID_VALUE; 33977117f1b4Smrg 33987117f1b4Smrg if ((width & 3) != 0 && width != 2 && width != 1) 33997117f1b4Smrg return GL_INVALID_VALUE; 34007117f1b4Smrg 34017117f1b4Smrg if ((height & 3) != 0 && height != 2 && height != 1) 34027117f1b4Smrg return GL_INVALID_VALUE; 34037117f1b4Smrg 34047117f1b4Smrg expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 34057117f1b4Smrg depth, format); 34067117f1b4Smrg if (expectedSize != imageSize) 34077117f1b4Smrg return GL_INVALID_VALUE; 34087117f1b4Smrg 34097117f1b4Smrg return GL_NO_ERROR; 34107117f1b4Smrg} 34117117f1b4Smrg 34127117f1b4Smrg 34137117f1b4Smrg 34147117f1b4Smrgvoid GLAPIENTRY 34157117f1b4Smrg_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 34167117f1b4Smrg GLenum internalFormat, GLsizei width, 34177117f1b4Smrg GLint border, GLsizei imageSize, 34187117f1b4Smrg const GLvoid *data) 34197117f1b4Smrg{ 34207117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 34217117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 34227117f1b4Smrg 34237117f1b4Smrg if (target == GL_TEXTURE_1D) { 34247117f1b4Smrg /* non-proxy target */ 34257117f1b4Smrg struct gl_texture_unit *texUnit; 34267117f1b4Smrg struct gl_texture_object *texObj; 34277117f1b4Smrg struct gl_texture_image *texImage; 34287117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 34297117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 34307117f1b4Smrg if (error) { 34317117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage1D"); 34327117f1b4Smrg return; 34337117f1b4Smrg } 34347117f1b4Smrg 34357117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 34367117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 34377117f1b4Smrg 34387117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34397117f1b4Smrg { 34407117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 34417117f1b4Smrg if (!texImage) { 34427117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 34437117f1b4Smrg goto out; 34447117f1b4Smrg } 34457117f1b4Smrg 34467117f1b4Smrg if (texImage->Data) { 34477117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 34487117f1b4Smrg } 34497117f1b4Smrg ASSERT(texImage->Data == NULL); 34507117f1b4Smrg 34517117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 34527117f1b4Smrg border, internalFormat); 34537117f1b4Smrg 34547117f1b4Smrg ASSERT(ctx->Driver.CompressedTexImage1D); 34557117f1b4Smrg (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 34567117f1b4Smrg internalFormat, width, border, 34577117f1b4Smrg imageSize, data, 34587117f1b4Smrg texObj, texImage); 34597117f1b4Smrg 34607117f1b4Smrg /* state update */ 3461c1f859d4Smrg texObj->_Complete = GL_FALSE; 34627117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 34637117f1b4Smrg } 34647117f1b4Smrg out: 34657117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34667117f1b4Smrg } 34677117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 34687117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 34697117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 34707117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 34717117f1b4Smrg if (!error) { 34727117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 34737117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 34747117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 34757117f1b4Smrg width, 1, 1, border); 34767117f1b4Smrg } 34777117f1b4Smrg if (error) { 34787117f1b4Smrg /* if error, clear all proxy texture image parameters */ 34797117f1b4Smrg struct gl_texture_image *texImage; 34807117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 34817117f1b4Smrg if (texImage) 34827117f1b4Smrg clear_teximage_fields(texImage); 34837117f1b4Smrg } 34847117f1b4Smrg else { 34857117f1b4Smrg /* store the teximage parameters */ 34867117f1b4Smrg struct gl_texture_unit *texUnit; 34877117f1b4Smrg struct gl_texture_object *texObj; 34887117f1b4Smrg struct gl_texture_image *texImage; 34897117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 34907117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 34917117f1b4Smrg 34927117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34937117f1b4Smrg { 34947117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 34957117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 34967117f1b4Smrg border, internalFormat); 34977117f1b4Smrg } 34987117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34997117f1b4Smrg } 35007117f1b4Smrg } 35017117f1b4Smrg else { 35027117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 35037117f1b4Smrg return; 35047117f1b4Smrg } 35057117f1b4Smrg} 35067117f1b4Smrg 35077117f1b4Smrg 35087117f1b4Smrgvoid GLAPIENTRY 35097117f1b4Smrg_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 35107117f1b4Smrg GLenum internalFormat, GLsizei width, 35117117f1b4Smrg GLsizei height, GLint border, GLsizei imageSize, 35127117f1b4Smrg const GLvoid *data) 35137117f1b4Smrg{ 35147117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35157117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 35167117f1b4Smrg 35177117f1b4Smrg if (target == GL_TEXTURE_2D || 35187117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 35197117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 35207117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 35217117f1b4Smrg /* non-proxy target */ 35227117f1b4Smrg struct gl_texture_unit *texUnit; 35237117f1b4Smrg struct gl_texture_object *texObj; 35247117f1b4Smrg struct gl_texture_image *texImage; 35257117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 35267117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 35277117f1b4Smrg if (error) { 35287117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage2D"); 35297117f1b4Smrg return; 35307117f1b4Smrg } 35317117f1b4Smrg 35327117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 35337117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 35347117f1b4Smrg 35357117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35367117f1b4Smrg { 35377117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 35387117f1b4Smrg if (!texImage) { 35397117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 35407117f1b4Smrg goto out; 35417117f1b4Smrg } 35427117f1b4Smrg 35437117f1b4Smrg if (texImage->Data) { 35447117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 35457117f1b4Smrg } 35467117f1b4Smrg ASSERT(texImage->Data == NULL); 35477117f1b4Smrg 35487117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 35497117f1b4Smrg border, internalFormat); 35507117f1b4Smrg 35517117f1b4Smrg ASSERT(ctx->Driver.CompressedTexImage2D); 35527117f1b4Smrg (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 35537117f1b4Smrg internalFormat, width, height, 35547117f1b4Smrg border, imageSize, data, 35557117f1b4Smrg texObj, texImage); 35567117f1b4Smrg 35577117f1b4Smrg /* state update */ 3558c1f859d4Smrg texObj->_Complete = GL_FALSE; 35597117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 35607117f1b4Smrg } 35617117f1b4Smrg out: 35627117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35637117f1b4Smrg } 35647117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 35657117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 35667117f1b4Smrg ctx->Extensions.ARB_texture_cube_map)) { 35677117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 35687117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 35697117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 35707117f1b4Smrg if (!error) { 35717117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 35727117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 35737117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 35747117f1b4Smrg width, height, 1, border); 35757117f1b4Smrg } 35767117f1b4Smrg if (error) { 35777117f1b4Smrg /* if error, clear all proxy texture image parameters */ 35787117f1b4Smrg struct gl_texture_image *texImage; 35797117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 35807117f1b4Smrg if (texImage) 35817117f1b4Smrg clear_teximage_fields(texImage); 35827117f1b4Smrg } 35837117f1b4Smrg else { 35847117f1b4Smrg /* store the teximage parameters */ 35857117f1b4Smrg struct gl_texture_unit *texUnit; 35867117f1b4Smrg struct gl_texture_object *texObj; 35877117f1b4Smrg struct gl_texture_image *texImage; 35887117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 35897117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 35907117f1b4Smrg 35917117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35927117f1b4Smrg { 35937117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 35947117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 35957117f1b4Smrg border, internalFormat); 35967117f1b4Smrg } 35977117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35987117f1b4Smrg } 35997117f1b4Smrg } 36007117f1b4Smrg else { 36017117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 36027117f1b4Smrg return; 36037117f1b4Smrg } 36047117f1b4Smrg} 36057117f1b4Smrg 36067117f1b4Smrg 36077117f1b4Smrgvoid GLAPIENTRY 36087117f1b4Smrg_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 36097117f1b4Smrg GLenum internalFormat, GLsizei width, 36107117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 36117117f1b4Smrg GLsizei imageSize, const GLvoid *data) 36127117f1b4Smrg{ 36137117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 36147117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 36157117f1b4Smrg 36167117f1b4Smrg if (target == GL_TEXTURE_3D) { 36177117f1b4Smrg /* non-proxy target */ 36187117f1b4Smrg struct gl_texture_unit *texUnit; 36197117f1b4Smrg struct gl_texture_object *texObj; 36207117f1b4Smrg struct gl_texture_image *texImage; 36217117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 36227117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 36237117f1b4Smrg if (error) { 36247117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage3D"); 36257117f1b4Smrg return; 36267117f1b4Smrg } 36277117f1b4Smrg 36287117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 36297117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 36307117f1b4Smrg _mesa_lock_texture(ctx, texObj); 36317117f1b4Smrg { 36327117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 36337117f1b4Smrg if (!texImage) { 36347117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 36357117f1b4Smrg goto out; 36367117f1b4Smrg } 36377117f1b4Smrg 36387117f1b4Smrg if (texImage->Data) { 36397117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 36407117f1b4Smrg } 36417117f1b4Smrg ASSERT(texImage->Data == NULL); 36427117f1b4Smrg 36437117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, 36447117f1b4Smrg border, internalFormat); 36457117f1b4Smrg 36467117f1b4Smrg ASSERT(ctx->Driver.CompressedTexImage3D); 36477117f1b4Smrg (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 36487117f1b4Smrg internalFormat, 36497117f1b4Smrg width, height, depth, 36507117f1b4Smrg border, imageSize, data, 36517117f1b4Smrg texObj, texImage); 36527117f1b4Smrg 36537117f1b4Smrg /* state update */ 3654c1f859d4Smrg texObj->_Complete = GL_FALSE; 36557117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 36567117f1b4Smrg } 36577117f1b4Smrg out: 36587117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36597117f1b4Smrg } 36607117f1b4Smrg else if (target == GL_PROXY_TEXTURE_3D) { 36617117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 36627117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 36637117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 36647117f1b4Smrg if (!error) { 36657117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 36667117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 36677117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 36687117f1b4Smrg width, height, depth, border); 36697117f1b4Smrg } 36707117f1b4Smrg if (error) { 36717117f1b4Smrg /* if error, clear all proxy texture image parameters */ 36727117f1b4Smrg struct gl_texture_image *texImage; 36737117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 36747117f1b4Smrg if (texImage) 36757117f1b4Smrg clear_teximage_fields(texImage); 36767117f1b4Smrg } 36777117f1b4Smrg else { 36787117f1b4Smrg /* store the teximage parameters */ 36797117f1b4Smrg struct gl_texture_unit *texUnit; 36807117f1b4Smrg struct gl_texture_object *texObj; 36817117f1b4Smrg struct gl_texture_image *texImage; 36827117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 36837117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 36847117f1b4Smrg _mesa_lock_texture(ctx, texObj); 36857117f1b4Smrg { 36867117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 36877117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 36887117f1b4Smrg depth, border, internalFormat); 36897117f1b4Smrg } 36907117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36917117f1b4Smrg } 36927117f1b4Smrg } 36937117f1b4Smrg else { 36947117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 36957117f1b4Smrg return; 36967117f1b4Smrg } 36977117f1b4Smrg} 36987117f1b4Smrg 36997117f1b4Smrg 37007117f1b4Smrgvoid GLAPIENTRY 37017117f1b4Smrg_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 37027117f1b4Smrg GLsizei width, GLenum format, 37037117f1b4Smrg GLsizei imageSize, const GLvoid *data) 37047117f1b4Smrg{ 37057117f1b4Smrg struct gl_texture_unit *texUnit; 37067117f1b4Smrg struct gl_texture_object *texObj; 37077117f1b4Smrg struct gl_texture_image *texImage; 37087117f1b4Smrg GLenum error; 37097117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 37107117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 37117117f1b4Smrg 37127117f1b4Smrg error = compressed_subtexture_error_check(ctx, 1, target, level, 37137117f1b4Smrg xoffset, 0, 0, /* pos */ 37147117f1b4Smrg width, 1, 1, /* size */ 37157117f1b4Smrg format, imageSize); 37167117f1b4Smrg if (error) { 37177117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 37187117f1b4Smrg return; 37197117f1b4Smrg } 37207117f1b4Smrg 37217117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 37227117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 37237117f1b4Smrg _mesa_lock_texture(ctx, texObj); 37247117f1b4Smrg { 37257117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 37267117f1b4Smrg assert(texImage); 37277117f1b4Smrg 37287117f1b4Smrg if ((GLint) format != texImage->InternalFormat) { 37297117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 37307117f1b4Smrg "glCompressedTexSubImage1D(format)"); 37317117f1b4Smrg goto out; 37327117f1b4Smrg } 37337117f1b4Smrg 37347117f1b4Smrg if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { 37357117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); 37367117f1b4Smrg goto out; 37377117f1b4Smrg } 37387117f1b4Smrg 37397117f1b4Smrg if (width == 0) 37407117f1b4Smrg goto out; /* no-op, not an error */ 37417117f1b4Smrg 37427117f1b4Smrg if (ctx->Driver.CompressedTexSubImage1D) { 37437117f1b4Smrg (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 37447117f1b4Smrg xoffset, width, 37457117f1b4Smrg format, imageSize, data, 37467117f1b4Smrg texObj, texImage); 37477117f1b4Smrg } 37487117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 37497117f1b4Smrg } 37507117f1b4Smrg out: 37517117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 37527117f1b4Smrg} 37537117f1b4Smrg 37547117f1b4Smrg 37557117f1b4Smrgvoid GLAPIENTRY 37567117f1b4Smrg_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 37577117f1b4Smrg GLint yoffset, GLsizei width, GLsizei height, 37587117f1b4Smrg GLenum format, GLsizei imageSize, 37597117f1b4Smrg const GLvoid *data) 37607117f1b4Smrg{ 37617117f1b4Smrg struct gl_texture_unit *texUnit; 37627117f1b4Smrg struct gl_texture_object *texObj; 37637117f1b4Smrg struct gl_texture_image *texImage; 37647117f1b4Smrg GLenum error; 37657117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 37667117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 37677117f1b4Smrg 37687117f1b4Smrg error = compressed_subtexture_error_check(ctx, 2, target, level, 37697117f1b4Smrg xoffset, yoffset, 0, /* pos */ 37707117f1b4Smrg width, height, 1, /* size */ 37717117f1b4Smrg format, imageSize); 37727117f1b4Smrg if (error) { 37737117f1b4Smrg /* XXX proxy target? */ 37747117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 37757117f1b4Smrg return; 37767117f1b4Smrg } 37777117f1b4Smrg 37787117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 37797117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 37807117f1b4Smrg _mesa_lock_texture(ctx, texObj); 37817117f1b4Smrg { 37827117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 37837117f1b4Smrg assert(texImage); 37847117f1b4Smrg 37857117f1b4Smrg if ((GLint) format != texImage->InternalFormat) { 37867117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 37877117f1b4Smrg "glCompressedTexSubImage2D(format)"); 37887117f1b4Smrg goto out; 37897117f1b4Smrg } 37907117f1b4Smrg 37917117f1b4Smrg if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 37927117f1b4Smrg ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { 37937117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 37947117f1b4Smrg goto out; 37957117f1b4Smrg } 37967117f1b4Smrg 37977117f1b4Smrg if (width == 0 || height == 0) 37987117f1b4Smrg goto out; /* no-op, not an error */ 37997117f1b4Smrg 38007117f1b4Smrg if (ctx->Driver.CompressedTexSubImage2D) { 38017117f1b4Smrg (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 38027117f1b4Smrg xoffset, yoffset, width, height, 38037117f1b4Smrg format, imageSize, data, 38047117f1b4Smrg texObj, texImage); 38057117f1b4Smrg } 38067117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 38077117f1b4Smrg } 38087117f1b4Smrg out: 38097117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 38107117f1b4Smrg} 38117117f1b4Smrg 38127117f1b4Smrg 38137117f1b4Smrgvoid GLAPIENTRY 38147117f1b4Smrg_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 38157117f1b4Smrg GLint yoffset, GLint zoffset, GLsizei width, 38167117f1b4Smrg GLsizei height, GLsizei depth, GLenum format, 38177117f1b4Smrg GLsizei imageSize, const GLvoid *data) 38187117f1b4Smrg{ 38197117f1b4Smrg struct gl_texture_unit *texUnit; 38207117f1b4Smrg struct gl_texture_object *texObj; 38217117f1b4Smrg struct gl_texture_image *texImage; 38227117f1b4Smrg GLenum error; 38237117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 38247117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 38257117f1b4Smrg 38267117f1b4Smrg error = compressed_subtexture_error_check(ctx, 3, target, level, 38277117f1b4Smrg xoffset, yoffset, zoffset,/*pos*/ 38287117f1b4Smrg width, height, depth, /*size*/ 38297117f1b4Smrg format, imageSize); 38307117f1b4Smrg if (error) { 3831c1f859d4Smrg _mesa_error(ctx, error, "glCompressedTexSubImage3D"); 38327117f1b4Smrg return; 38337117f1b4Smrg } 38347117f1b4Smrg 38357117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 38367117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 38377117f1b4Smrg _mesa_lock_texture(ctx, texObj); 38387117f1b4Smrg { 38397117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 38407117f1b4Smrg assert(texImage); 38417117f1b4Smrg 38427117f1b4Smrg if ((GLint) format != texImage->InternalFormat) { 38437117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 38447117f1b4Smrg "glCompressedTexSubImage3D(format)"); 38457117f1b4Smrg goto out; 38467117f1b4Smrg } 38477117f1b4Smrg 38487117f1b4Smrg if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 38497117f1b4Smrg ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || 38507117f1b4Smrg ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { 38517117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 38527117f1b4Smrg goto out; 38537117f1b4Smrg } 38547117f1b4Smrg 38557117f1b4Smrg if (width == 0 || height == 0 || depth == 0) 38567117f1b4Smrg goto out; /* no-op, not an error */ 38577117f1b4Smrg 38587117f1b4Smrg if (ctx->Driver.CompressedTexSubImage3D) { 38597117f1b4Smrg (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 38607117f1b4Smrg xoffset, yoffset, zoffset, 38617117f1b4Smrg width, height, depth, 38627117f1b4Smrg format, imageSize, data, 38637117f1b4Smrg texObj, texImage); 38647117f1b4Smrg } 38657117f1b4Smrg ctx->NewState |= _NEW_TEXTURE; 38667117f1b4Smrg } 38677117f1b4Smrg out: 38687117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 38697117f1b4Smrg} 38707117f1b4Smrg 38717117f1b4Smrg 38727117f1b4Smrgvoid GLAPIENTRY 38737117f1b4Smrg_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 38747117f1b4Smrg{ 38757117f1b4Smrg const struct gl_texture_unit *texUnit; 38767117f1b4Smrg struct gl_texture_object *texObj; 38777117f1b4Smrg struct gl_texture_image *texImage; 38787117f1b4Smrg GLint maxLevels; 38797117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 38807117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 38817117f1b4Smrg 38827117f1b4Smrg texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 38837117f1b4Smrg texObj = _mesa_select_tex_object(ctx, texUnit, target); 38847117f1b4Smrg if (!texObj) { 38857117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 38867117f1b4Smrg return; 38877117f1b4Smrg } 38887117f1b4Smrg 38897117f1b4Smrg maxLevels = _mesa_max_texture_levels(ctx, target); 38907117f1b4Smrg ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 38917117f1b4Smrg 38927117f1b4Smrg if (level < 0 || level >= maxLevels) { 38937117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 38947117f1b4Smrg return; 38957117f1b4Smrg } 38967117f1b4Smrg 38977117f1b4Smrg if (_mesa_is_proxy_texture(target)) { 38987117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 38997117f1b4Smrg return; 39007117f1b4Smrg } 39017117f1b4Smrg 39027117f1b4Smrg _mesa_lock_texture(ctx, texObj); 39037117f1b4Smrg { 39047117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3905c1f859d4Smrg if (texImage) { 3906c1f859d4Smrg if (texImage->IsCompressed) { 3907c1f859d4Smrg /* this typically calls _mesa_get_compressed_teximage() */ 3908c1f859d4Smrg ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 3909c1f859d4Smrg texObj, texImage); 3910c1f859d4Smrg } 3911c1f859d4Smrg else { 3912c1f859d4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 3913c1f859d4Smrg "glGetCompressedTexImageARB"); 3914c1f859d4Smrg } 39157117f1b4Smrg } 3916c1f859d4Smrg else { 3917c1f859d4Smrg /* probably invalid mipmap level */ 3918c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 3919c1f859d4Smrg "glGetCompressedTexImageARB(level)"); 39207117f1b4Smrg } 39217117f1b4Smrg } 39227117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 39237117f1b4Smrg} 3924