teximage.c revision 4a49301e
17117f1b4Smrg/* 2c1f859d4Smrg * mesa 3-D graphics library 34a49301eSmrg * Version: 7.6 47117f1b4Smrg * 57117f1b4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 64a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 77117f1b4Smrg * 87117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 97117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 107117f1b4Smrg * to deal in the Software without restriction, including without limitation 117117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 127117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 137117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 147117f1b4Smrg * 157117f1b4Smrg * The above copyright notice and this permission notice shall be included 167117f1b4Smrg * in all copies or substantial portions of the Software. 177117f1b4Smrg * 187117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 197117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 207117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 217117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 227117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 237117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 247117f1b4Smrg */ 257117f1b4Smrg 267117f1b4Smrg 277117f1b4Smrg/** 287117f1b4Smrg * \file teximage.c 297117f1b4Smrg * Texture image-related functions. 307117f1b4Smrg */ 317117f1b4Smrg 327117f1b4Smrg 337117f1b4Smrg#include "glheader.h" 347117f1b4Smrg#include "bufferobj.h" 357117f1b4Smrg#include "context.h" 367117f1b4Smrg#include "convolve.h" 374a49301eSmrg#include "enums.h" 387117f1b4Smrg#include "fbobject.h" 397117f1b4Smrg#include "framebuffer.h" 404a49301eSmrg#include "hash.h" 417117f1b4Smrg#include "image.h" 427117f1b4Smrg#include "imports.h" 437117f1b4Smrg#include "macros.h" 447117f1b4Smrg#include "state.h" 457117f1b4Smrg#include "texcompress.h" 464a49301eSmrg#include "texfetch.h" 477117f1b4Smrg#include "teximage.h" 487117f1b4Smrg#include "texstate.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 */ 574a49301eSmrg#define NEW_COPY_TEX_STATE (_MESA_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 * Compute floor(log_base_2(n)). 867117f1b4Smrg * If n < 0 return -1. 877117f1b4Smrg */ 887117f1b4Smrgstatic int 897117f1b4Smrglogbase2( int n ) 907117f1b4Smrg{ 917117f1b4Smrg GLint i = 1; 927117f1b4Smrg GLint log2 = 0; 937117f1b4Smrg 947117f1b4Smrg if (n < 0) 957117f1b4Smrg return -1; 967117f1b4Smrg 977117f1b4Smrg if (n == 0) 987117f1b4Smrg return 0; 997117f1b4Smrg 1007117f1b4Smrg while ( n > i ) { 1017117f1b4Smrg i *= 2; 1027117f1b4Smrg log2++; 1037117f1b4Smrg } 1047117f1b4Smrg if (i != n) { 1057117f1b4Smrg return log2 - 1; 1067117f1b4Smrg } 1077117f1b4Smrg else { 1087117f1b4Smrg return log2; 1097117f1b4Smrg } 1107117f1b4Smrg} 1117117f1b4Smrg 1127117f1b4Smrg 1137117f1b4Smrg 1147117f1b4Smrg/** 1157117f1b4Smrg * Return the simple base format for a given internal texture format. 1167117f1b4Smrg * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. 1177117f1b4Smrg * 1187117f1b4Smrg * \param ctx GL context. 1197117f1b4Smrg * \param internalFormat the internal texture format token or 1, 2, 3, or 4. 1207117f1b4Smrg * 1217117f1b4Smrg * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, 1227117f1b4Smrg * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. 1237117f1b4Smrg * 1247117f1b4Smrg * This is the format which is used during texture application (i.e. the 1257117f1b4Smrg * texture format and env mode determine the arithmetic used. 1264a49301eSmrg * 1274a49301eSmrg * XXX this could be static 1287117f1b4Smrg */ 1297117f1b4SmrgGLint 1307117f1b4Smrg_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) 1317117f1b4Smrg{ 1327117f1b4Smrg switch (internalFormat) { 1337117f1b4Smrg case GL_ALPHA: 1347117f1b4Smrg case GL_ALPHA4: 1357117f1b4Smrg case GL_ALPHA8: 1367117f1b4Smrg case GL_ALPHA12: 1377117f1b4Smrg case GL_ALPHA16: 1387117f1b4Smrg return GL_ALPHA; 1397117f1b4Smrg case 1: 1407117f1b4Smrg case GL_LUMINANCE: 1417117f1b4Smrg case GL_LUMINANCE4: 1427117f1b4Smrg case GL_LUMINANCE8: 1437117f1b4Smrg case GL_LUMINANCE12: 1447117f1b4Smrg case GL_LUMINANCE16: 1457117f1b4Smrg return GL_LUMINANCE; 1467117f1b4Smrg case 2: 1477117f1b4Smrg case GL_LUMINANCE_ALPHA: 1487117f1b4Smrg case GL_LUMINANCE4_ALPHA4: 1497117f1b4Smrg case GL_LUMINANCE6_ALPHA2: 1507117f1b4Smrg case GL_LUMINANCE8_ALPHA8: 1517117f1b4Smrg case GL_LUMINANCE12_ALPHA4: 1527117f1b4Smrg case GL_LUMINANCE12_ALPHA12: 1537117f1b4Smrg case GL_LUMINANCE16_ALPHA16: 1547117f1b4Smrg return GL_LUMINANCE_ALPHA; 1557117f1b4Smrg case GL_INTENSITY: 1567117f1b4Smrg case GL_INTENSITY4: 1577117f1b4Smrg case GL_INTENSITY8: 1587117f1b4Smrg case GL_INTENSITY12: 1597117f1b4Smrg case GL_INTENSITY16: 1607117f1b4Smrg return GL_INTENSITY; 1617117f1b4Smrg case 3: 1627117f1b4Smrg case GL_RGB: 1637117f1b4Smrg case GL_R3_G3_B2: 1647117f1b4Smrg case GL_RGB4: 1657117f1b4Smrg case GL_RGB5: 1667117f1b4Smrg case GL_RGB8: 1677117f1b4Smrg case GL_RGB10: 1687117f1b4Smrg case GL_RGB12: 1697117f1b4Smrg case GL_RGB16: 1707117f1b4Smrg return GL_RGB; 1717117f1b4Smrg case 4: 1727117f1b4Smrg case GL_RGBA: 1737117f1b4Smrg case GL_RGBA2: 1747117f1b4Smrg case GL_RGBA4: 1757117f1b4Smrg case GL_RGB5_A1: 1767117f1b4Smrg case GL_RGBA8: 1777117f1b4Smrg case GL_RGB10_A2: 1787117f1b4Smrg case GL_RGBA12: 1797117f1b4Smrg case GL_RGBA16: 1807117f1b4Smrg return GL_RGBA; 1817117f1b4Smrg default: 1827117f1b4Smrg ; /* fallthrough */ 1837117f1b4Smrg } 1847117f1b4Smrg 1857117f1b4Smrg if (ctx->Extensions.EXT_paletted_texture) { 1867117f1b4Smrg switch (internalFormat) { 1877117f1b4Smrg case GL_COLOR_INDEX: 1887117f1b4Smrg case GL_COLOR_INDEX1_EXT: 1897117f1b4Smrg case GL_COLOR_INDEX2_EXT: 1907117f1b4Smrg case GL_COLOR_INDEX4_EXT: 1917117f1b4Smrg case GL_COLOR_INDEX8_EXT: 1927117f1b4Smrg case GL_COLOR_INDEX12_EXT: 1937117f1b4Smrg case GL_COLOR_INDEX16_EXT: 1947117f1b4Smrg return GL_COLOR_INDEX; 1957117f1b4Smrg default: 1967117f1b4Smrg ; /* fallthrough */ 1977117f1b4Smrg } 1987117f1b4Smrg } 1997117f1b4Smrg 200c1f859d4Smrg if (ctx->Extensions.ARB_depth_texture) { 2017117f1b4Smrg switch (internalFormat) { 2027117f1b4Smrg case GL_DEPTH_COMPONENT: 203c1f859d4Smrg case GL_DEPTH_COMPONENT16: 204c1f859d4Smrg case GL_DEPTH_COMPONENT24: 205c1f859d4Smrg case GL_DEPTH_COMPONENT32: 2067117f1b4Smrg return GL_DEPTH_COMPONENT; 2077117f1b4Smrg default: 2087117f1b4Smrg ; /* fallthrough */ 2097117f1b4Smrg } 2107117f1b4Smrg } 2117117f1b4Smrg 2124a49301eSmrg switch (internalFormat) { 2134a49301eSmrg case GL_COMPRESSED_ALPHA: 2144a49301eSmrg return GL_ALPHA; 2154a49301eSmrg case GL_COMPRESSED_LUMINANCE: 2164a49301eSmrg return GL_LUMINANCE; 2174a49301eSmrg case GL_COMPRESSED_LUMINANCE_ALPHA: 2184a49301eSmrg return GL_LUMINANCE_ALPHA; 2194a49301eSmrg case GL_COMPRESSED_INTENSITY: 2204a49301eSmrg return GL_INTENSITY; 2214a49301eSmrg case GL_COMPRESSED_RGB: 2224a49301eSmrg return GL_RGB; 2234a49301eSmrg case GL_COMPRESSED_RGBA: 2244a49301eSmrg return GL_RGBA; 2254a49301eSmrg default: 2264a49301eSmrg ; /* fallthrough */ 2277117f1b4Smrg } 2287117f1b4Smrg 2297117f1b4Smrg if (ctx->Extensions.TDFX_texture_compression_FXT1) { 2307117f1b4Smrg switch (internalFormat) { 2317117f1b4Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 2327117f1b4Smrg return GL_RGB; 2337117f1b4Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 2347117f1b4Smrg return GL_RGBA; 2357117f1b4Smrg default: 2367117f1b4Smrg ; /* fallthrough */ 2377117f1b4Smrg } 2387117f1b4Smrg } 2397117f1b4Smrg 2407117f1b4Smrg if (ctx->Extensions.EXT_texture_compression_s3tc) { 2417117f1b4Smrg switch (internalFormat) { 2427117f1b4Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 2437117f1b4Smrg return GL_RGB; 2447117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 2457117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 2467117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 2477117f1b4Smrg return GL_RGBA; 2487117f1b4Smrg default: 2497117f1b4Smrg ; /* fallthrough */ 2507117f1b4Smrg } 2517117f1b4Smrg } 2527117f1b4Smrg 2537117f1b4Smrg if (ctx->Extensions.S3_s3tc) { 2547117f1b4Smrg switch (internalFormat) { 2557117f1b4Smrg case GL_RGB_S3TC: 2567117f1b4Smrg case GL_RGB4_S3TC: 2577117f1b4Smrg return GL_RGB; 2587117f1b4Smrg case GL_RGBA_S3TC: 2597117f1b4Smrg case GL_RGBA4_S3TC: 2607117f1b4Smrg return GL_RGBA; 2617117f1b4Smrg default: 2627117f1b4Smrg ; /* fallthrough */ 2637117f1b4Smrg } 2647117f1b4Smrg } 2657117f1b4Smrg 2667117f1b4Smrg if (ctx->Extensions.MESA_ycbcr_texture) { 2677117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) 2687117f1b4Smrg return GL_YCBCR_MESA; 2697117f1b4Smrg } 2707117f1b4Smrg 2717117f1b4Smrg if (ctx->Extensions.ARB_texture_float) { 2727117f1b4Smrg switch (internalFormat) { 2737117f1b4Smrg case GL_ALPHA16F_ARB: 2747117f1b4Smrg case GL_ALPHA32F_ARB: 2757117f1b4Smrg return GL_ALPHA; 2767117f1b4Smrg case GL_RGBA16F_ARB: 2777117f1b4Smrg case GL_RGBA32F_ARB: 2787117f1b4Smrg return GL_RGBA; 2797117f1b4Smrg case GL_RGB16F_ARB: 2807117f1b4Smrg case GL_RGB32F_ARB: 2817117f1b4Smrg return GL_RGB; 2827117f1b4Smrg case GL_INTENSITY16F_ARB: 2837117f1b4Smrg case GL_INTENSITY32F_ARB: 2847117f1b4Smrg return GL_INTENSITY; 2857117f1b4Smrg case GL_LUMINANCE16F_ARB: 2867117f1b4Smrg case GL_LUMINANCE32F_ARB: 2877117f1b4Smrg return GL_LUMINANCE; 2887117f1b4Smrg case GL_LUMINANCE_ALPHA16F_ARB: 2897117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 2907117f1b4Smrg return GL_LUMINANCE_ALPHA; 2917117f1b4Smrg default: 2927117f1b4Smrg ; /* fallthrough */ 2937117f1b4Smrg } 2947117f1b4Smrg } 2957117f1b4Smrg 2964a49301eSmrg if (ctx->Extensions.ATI_envmap_bumpmap) { 2974a49301eSmrg switch (internalFormat) { 2984a49301eSmrg case GL_DUDV_ATI: 2994a49301eSmrg case GL_DU8DV8_ATI: 3004a49301eSmrg return GL_DUDV_ATI; 3014a49301eSmrg default: 3024a49301eSmrg ; /* fallthrough */ 3034a49301eSmrg } 3044a49301eSmrg } 3054a49301eSmrg 3064a49301eSmrg if (ctx->Extensions.MESA_texture_signed_rgba) { 3074a49301eSmrg switch (internalFormat) { 3084a49301eSmrg case GL_RGBA_SNORM: 3094a49301eSmrg case GL_RGBA8_SNORM: 3104a49301eSmrg return GL_RGBA; 3114a49301eSmrg default: 3124a49301eSmrg ; /* fallthrough */ 3134a49301eSmrg } 3144a49301eSmrg } 3154a49301eSmrg 3167117f1b4Smrg if (ctx->Extensions.EXT_packed_depth_stencil) { 3177117f1b4Smrg switch (internalFormat) { 3187117f1b4Smrg case GL_DEPTH_STENCIL_EXT: 3197117f1b4Smrg case GL_DEPTH24_STENCIL8_EXT: 3207117f1b4Smrg return GL_DEPTH_STENCIL_EXT; 3217117f1b4Smrg default: 3227117f1b4Smrg ; /* fallthrough */ 3237117f1b4Smrg } 3247117f1b4Smrg } 3257117f1b4Smrg 3267117f1b4Smrg#if FEATURE_EXT_texture_sRGB 3277117f1b4Smrg if (ctx->Extensions.EXT_texture_sRGB) { 3287117f1b4Smrg switch (internalFormat) { 3297117f1b4Smrg case GL_SRGB_EXT: 3307117f1b4Smrg case GL_SRGB8_EXT: 3317117f1b4Smrg case GL_COMPRESSED_SRGB_EXT: 3327117f1b4Smrg case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 3337117f1b4Smrg return GL_RGB; 3347117f1b4Smrg case GL_SRGB_ALPHA_EXT: 3357117f1b4Smrg case GL_SRGB8_ALPHA8_EXT: 3367117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_EXT: 3377117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 3387117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 3397117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 3407117f1b4Smrg return GL_RGBA; 3417117f1b4Smrg case GL_SLUMINANCE_ALPHA_EXT: 3427117f1b4Smrg case GL_SLUMINANCE8_ALPHA8_EXT: 3437117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_EXT: 3447117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 3457117f1b4Smrg return GL_LUMINANCE_ALPHA; 3467117f1b4Smrg case GL_SLUMINANCE_EXT: 3477117f1b4Smrg case GL_SLUMINANCE8_EXT: 3487117f1b4Smrg return GL_LUMINANCE; 3497117f1b4Smrg default: 3507117f1b4Smrg ; /* fallthrough */ 3517117f1b4Smrg } 3527117f1b4Smrg } 3537117f1b4Smrg 3547117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */ 3557117f1b4Smrg 3567117f1b4Smrg return -1; /* error */ 3577117f1b4Smrg} 3587117f1b4Smrg 3597117f1b4Smrg 3607117f1b4Smrg/** 3617117f1b4Smrg * Test if it is a supported compressed format. 3627117f1b4Smrg * 3637117f1b4Smrg * \param internalFormat the internal format token provided by the user. 3647117f1b4Smrg * 3657117f1b4Smrg * \ret GL_TRUE if \p internalFormat is a supported compressed format, or 3667117f1b4Smrg * GL_FALSE otherwise. 3677117f1b4Smrg * 3687117f1b4Smrg * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX 3697117f1b4Smrg * are supported. 3707117f1b4Smrg */ 3717117f1b4Smrgstatic GLboolean 3727117f1b4Smrgis_compressed_format(GLcontext *ctx, GLenum internalFormat) 3737117f1b4Smrg{ 3747117f1b4Smrg GLint supported[100]; /* 100 should be plenty */ 3757117f1b4Smrg GLuint i, n; 3767117f1b4Smrg 3777117f1b4Smrg n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE); 3787117f1b4Smrg ASSERT(n < 100); 3797117f1b4Smrg for (i = 0; i < n; i++) { 3807117f1b4Smrg if ((GLint) internalFormat == supported[i]) { 3817117f1b4Smrg return GL_TRUE; 3827117f1b4Smrg } 3837117f1b4Smrg } 3847117f1b4Smrg return GL_FALSE; 3857117f1b4Smrg} 3867117f1b4Smrg 3877117f1b4Smrg 388c1f859d4Smrg/** 389c1f859d4Smrg * For cube map faces, return a face index in [0,5]. 390c1f859d4Smrg * For other targets return 0; 391c1f859d4Smrg */ 392c1f859d4SmrgGLuint 393c1f859d4Smrg_mesa_tex_target_to_face(GLenum target) 3947117f1b4Smrg{ 3957117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3967117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 3977117f1b4Smrg return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 3987117f1b4Smrg else 3997117f1b4Smrg return 0; 4007117f1b4Smrg} 4017117f1b4Smrg 4027117f1b4Smrg 4037117f1b4Smrg 4047117f1b4Smrg/** 4057117f1b4Smrg * Store a gl_texture_image pointer in a gl_texture_object structure 4067117f1b4Smrg * according to the target and level parameters. 4077117f1b4Smrg * 4087117f1b4Smrg * \param tObj texture object. 4097117f1b4Smrg * \param target texture target. 4107117f1b4Smrg * \param level image level. 4117117f1b4Smrg * \param texImage texture image. 4127117f1b4Smrg * 4137117f1b4Smrg * This was basically prompted by the introduction of cube maps. 4147117f1b4Smrg */ 4157117f1b4Smrgvoid 4167117f1b4Smrg_mesa_set_tex_image(struct gl_texture_object *tObj, 4177117f1b4Smrg GLenum target, GLint level, 4187117f1b4Smrg struct gl_texture_image *texImage) 4197117f1b4Smrg{ 4204a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 4214a49301eSmrg 4227117f1b4Smrg ASSERT(tObj); 4237117f1b4Smrg ASSERT(texImage); 4244a49301eSmrg ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0); 4254a49301eSmrg 4264a49301eSmrg tObj->Image[face][level] = texImage; 4274a49301eSmrg 4287117f1b4Smrg /* Set the 'back' pointer */ 4297117f1b4Smrg texImage->TexObject = tObj; 4307117f1b4Smrg} 4317117f1b4Smrg 4327117f1b4Smrg 4337117f1b4Smrg/** 4347117f1b4Smrg * Allocate a texture image structure. 4357117f1b4Smrg * 4367117f1b4Smrg * Called via ctx->Driver.NewTextureImage() unless overriden by a device 4377117f1b4Smrg * driver. 4387117f1b4Smrg * 4397117f1b4Smrg * \return a pointer to gl_texture_image struct with all fields initialized to 4407117f1b4Smrg * zero. 4417117f1b4Smrg */ 4427117f1b4Smrgstruct gl_texture_image * 4437117f1b4Smrg_mesa_new_texture_image( GLcontext *ctx ) 4447117f1b4Smrg{ 4457117f1b4Smrg (void) ctx; 4467117f1b4Smrg return CALLOC_STRUCT(gl_texture_image); 4477117f1b4Smrg} 4487117f1b4Smrg 4497117f1b4Smrg 4507117f1b4Smrg/** 4517117f1b4Smrg * Free texture image data. 4527117f1b4Smrg * This function is a fallback called via ctx->Driver.FreeTexImageData(). 4537117f1b4Smrg * 4544a49301eSmrg * \param texImage texture image. 4557117f1b4Smrg * 4567117f1b4Smrg * Free the texture image data if it's not marked as client data. 4577117f1b4Smrg */ 4587117f1b4Smrgvoid 4597117f1b4Smrg_mesa_free_texture_image_data(GLcontext *ctx, 4607117f1b4Smrg struct gl_texture_image *texImage) 4617117f1b4Smrg{ 4627117f1b4Smrg (void) ctx; 4637117f1b4Smrg 4647117f1b4Smrg if (texImage->Data && !texImage->IsClientData) { 4657117f1b4Smrg /* free the old texture data */ 4667117f1b4Smrg _mesa_free_texmemory(texImage->Data); 4677117f1b4Smrg } 4687117f1b4Smrg 4697117f1b4Smrg texImage->Data = NULL; 4707117f1b4Smrg} 4717117f1b4Smrg 4727117f1b4Smrg 4737117f1b4Smrg/** 4747117f1b4Smrg * Free texture image. 4757117f1b4Smrg * 4764a49301eSmrg * \param texImage texture image. 4777117f1b4Smrg * 4787117f1b4Smrg * Free the texture image structure and the associated image data. 4797117f1b4Smrg */ 4807117f1b4Smrgvoid 4817117f1b4Smrg_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) 4827117f1b4Smrg{ 4837117f1b4Smrg /* Free texImage->Data and/or any other driver-specific texture 4847117f1b4Smrg * image storage. 4857117f1b4Smrg */ 4867117f1b4Smrg ASSERT(ctx->Driver.FreeTexImageData); 4877117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 4887117f1b4Smrg 4897117f1b4Smrg ASSERT(texImage->Data == NULL); 4907117f1b4Smrg if (texImage->ImageOffsets) 4917117f1b4Smrg _mesa_free(texImage->ImageOffsets); 4927117f1b4Smrg _mesa_free(texImage); 4937117f1b4Smrg} 4947117f1b4Smrg 4957117f1b4Smrg 4967117f1b4Smrg/** 4977117f1b4Smrg * Test if a target is a proxy target. 4987117f1b4Smrg * 4997117f1b4Smrg * \param target texture target. 5007117f1b4Smrg * 5017117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 5027117f1b4Smrg */ 5037117f1b4SmrgGLboolean 5047117f1b4Smrg_mesa_is_proxy_texture(GLenum target) 5057117f1b4Smrg{ 5064a49301eSmrg /* NUM_TEXTURE_TARGETS should match number of terms below */ 5074a49301eSmrg assert(NUM_TEXTURE_TARGETS == 7); 5084a49301eSmrg 5097117f1b4Smrg return (target == GL_PROXY_TEXTURE_1D || 5107117f1b4Smrg target == GL_PROXY_TEXTURE_2D || 5117117f1b4Smrg target == GL_PROXY_TEXTURE_3D || 5127117f1b4Smrg target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 513c1f859d4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV || 514c1f859d4Smrg target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 515c1f859d4Smrg target == GL_PROXY_TEXTURE_2D_ARRAY_EXT); 5167117f1b4Smrg} 5177117f1b4Smrg 5187117f1b4Smrg 5197117f1b4Smrg/** 5207117f1b4Smrg * Get the texture object that corresponds to the target of the given texture unit. 5217117f1b4Smrg * 5227117f1b4Smrg * \param ctx GL context. 5237117f1b4Smrg * \param texUnit texture unit. 5247117f1b4Smrg * \param target texture target. 5257117f1b4Smrg * 5267117f1b4Smrg * \return pointer to the texture object on success, or NULL on failure. 5277117f1b4Smrg * 5287117f1b4Smrg * \sa gl_texture_unit. 5297117f1b4Smrg */ 5307117f1b4Smrgstruct gl_texture_object * 5317117f1b4Smrg_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 5327117f1b4Smrg GLenum target) 5337117f1b4Smrg{ 5347117f1b4Smrg switch (target) { 5357117f1b4Smrg case GL_TEXTURE_1D: 536c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 5377117f1b4Smrg case GL_PROXY_TEXTURE_1D: 538c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 5397117f1b4Smrg case GL_TEXTURE_2D: 540c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 5417117f1b4Smrg case GL_PROXY_TEXTURE_2D: 542c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 5437117f1b4Smrg case GL_TEXTURE_3D: 544c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 5457117f1b4Smrg case GL_PROXY_TEXTURE_3D: 546c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 5477117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 5487117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 5497117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 5507117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 5517117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 5527117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 5537117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 5547117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 555c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 5567117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 5577117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 558c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 5597117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 5607117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 561c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 5627117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 5637117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 564c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 565c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 566c1f859d4Smrg return ctx->Extensions.MESA_texture_array 567c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 568c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 569c1f859d4Smrg return ctx->Extensions.MESA_texture_array 570c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 571c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 572c1f859d4Smrg return ctx->Extensions.MESA_texture_array 573c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 574c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 575c1f859d4Smrg return ctx->Extensions.MESA_texture_array 576c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 5777117f1b4Smrg default: 5787117f1b4Smrg _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 5797117f1b4Smrg return NULL; 5807117f1b4Smrg } 5817117f1b4Smrg} 5827117f1b4Smrg 5837117f1b4Smrg 5847117f1b4Smrg/** 5854a49301eSmrg * Return pointer to texture object for given target on current texture unit. 5864a49301eSmrg */ 5874a49301eSmrgstruct gl_texture_object * 5884a49301eSmrg_mesa_get_current_tex_object(GLcontext *ctx, GLenum target) 5894a49301eSmrg{ 5904a49301eSmrg struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 5914a49301eSmrg return _mesa_select_tex_object(ctx, texUnit, target); 5924a49301eSmrg} 5934a49301eSmrg 5944a49301eSmrg 5954a49301eSmrg/** 5964a49301eSmrg * Get a texture image pointer from a texture object, given a texture 5974a49301eSmrg * target and mipmap level. The target and level parameters should 5984a49301eSmrg * have already been error-checked. 5997117f1b4Smrg * 6007117f1b4Smrg * \param ctx GL context. 6014a49301eSmrg * \param texObj texture unit. 6027117f1b4Smrg * \param target texture target. 6037117f1b4Smrg * \param level image level. 6047117f1b4Smrg * 6054a49301eSmrg * \return pointer to the texture image structure, or NULL on failure. 6067117f1b4Smrg */ 6077117f1b4Smrgstruct gl_texture_image * 6087117f1b4Smrg_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, 6097117f1b4Smrg GLenum target, GLint level) 6107117f1b4Smrg{ 6114a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 6127117f1b4Smrg 6134a49301eSmrg ASSERT(texObj); 6144a49301eSmrg ASSERT(level >= 0); 6154a49301eSmrg ASSERT(level < MAX_TEXTURE_LEVELS); 616c1f859d4Smrg 6174a49301eSmrg return texObj->Image[face][level]; 6187117f1b4Smrg} 6197117f1b4Smrg 6207117f1b4Smrg 6217117f1b4Smrg/** 6227117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 6237117f1b4Smrg * it and install it. Only return NULL if passed a bad parameter or run 6247117f1b4Smrg * out of memory. 6257117f1b4Smrg */ 6267117f1b4Smrgstruct gl_texture_image * 6277117f1b4Smrg_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj, 6287117f1b4Smrg GLenum target, GLint level) 6297117f1b4Smrg{ 6307117f1b4Smrg struct gl_texture_image *texImage; 6317117f1b4Smrg 6327117f1b4Smrg if (!texObj) 6337117f1b4Smrg return NULL; 6347117f1b4Smrg 6357117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 6367117f1b4Smrg if (!texImage) { 6377117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 6387117f1b4Smrg if (!texImage) { 6397117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 6407117f1b4Smrg return NULL; 6417117f1b4Smrg } 6427117f1b4Smrg 6437117f1b4Smrg _mesa_set_tex_image(texObj, target, level, texImage); 6447117f1b4Smrg } 6457117f1b4Smrg 6467117f1b4Smrg return texImage; 6477117f1b4Smrg} 6487117f1b4Smrg 6497117f1b4Smrg 6507117f1b4Smrg/** 6517117f1b4Smrg * Return pointer to the specified proxy texture image. 6527117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit. 6537117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid 6547117f1b4Smrg * level, or out of memory. 6557117f1b4Smrg */ 6567117f1b4Smrgstruct gl_texture_image * 6577117f1b4Smrg_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) 6587117f1b4Smrg{ 6597117f1b4Smrg struct gl_texture_image *texImage; 6604a49301eSmrg GLuint texIndex; 6617117f1b4Smrg 6627117f1b4Smrg if (level < 0 ) 6637117f1b4Smrg return NULL; 6647117f1b4Smrg 6657117f1b4Smrg switch (target) { 6667117f1b4Smrg case GL_PROXY_TEXTURE_1D: 6677117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 6687117f1b4Smrg return NULL; 6694a49301eSmrg texIndex = TEXTURE_1D_INDEX; 6704a49301eSmrg break; 6717117f1b4Smrg case GL_PROXY_TEXTURE_2D: 6727117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 6737117f1b4Smrg return NULL; 6744a49301eSmrg texIndex = TEXTURE_2D_INDEX; 6754a49301eSmrg break; 6767117f1b4Smrg case GL_PROXY_TEXTURE_3D: 6777117f1b4Smrg if (level >= ctx->Const.Max3DTextureLevels) 6787117f1b4Smrg return NULL; 6794a49301eSmrg texIndex = TEXTURE_3D_INDEX; 6804a49301eSmrg break; 6817117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP: 6827117f1b4Smrg if (level >= ctx->Const.MaxCubeTextureLevels) 6837117f1b4Smrg return NULL; 6844a49301eSmrg texIndex = TEXTURE_CUBE_INDEX; 6854a49301eSmrg break; 6867117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 6877117f1b4Smrg if (level > 0) 6887117f1b4Smrg return NULL; 6894a49301eSmrg texIndex = TEXTURE_RECT_INDEX; 6904a49301eSmrg break; 691c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 692c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 693c1f859d4Smrg return NULL; 6944a49301eSmrg texIndex = TEXTURE_1D_ARRAY_INDEX; 6954a49301eSmrg break; 696c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 697c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 698c1f859d4Smrg return NULL; 6994a49301eSmrg texIndex = TEXTURE_2D_ARRAY_INDEX; 7004a49301eSmrg break; 7017117f1b4Smrg default: 7027117f1b4Smrg return NULL; 7037117f1b4Smrg } 7044a49301eSmrg 7054a49301eSmrg texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 7064a49301eSmrg if (!texImage) { 7074a49301eSmrg texImage = ctx->Driver.NewTextureImage(ctx); 7084a49301eSmrg if (!texImage) { 7094a49301eSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 7104a49301eSmrg return NULL; 7114a49301eSmrg } 7124a49301eSmrg ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 7134a49301eSmrg /* Set the 'back' pointer */ 7144a49301eSmrg texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 7154a49301eSmrg } 7164a49301eSmrg return texImage; 7177117f1b4Smrg} 7187117f1b4Smrg 7197117f1b4Smrg 7207117f1b4Smrg/** 7217117f1b4Smrg * Get the maximum number of allowed mipmap levels. 7227117f1b4Smrg * 7237117f1b4Smrg * \param ctx GL context. 7247117f1b4Smrg * \param target texture target. 7257117f1b4Smrg * 7267117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given 7277117f1b4Smrg * texture target, or zero if passed a bad target. 7287117f1b4Smrg * 7297117f1b4Smrg * \sa gl_constants. 7307117f1b4Smrg */ 7317117f1b4SmrgGLint 7327117f1b4Smrg_mesa_max_texture_levels(GLcontext *ctx, GLenum target) 7337117f1b4Smrg{ 7347117f1b4Smrg switch (target) { 7357117f1b4Smrg case GL_TEXTURE_1D: 7367117f1b4Smrg case GL_PROXY_TEXTURE_1D: 7377117f1b4Smrg case GL_TEXTURE_2D: 7387117f1b4Smrg case GL_PROXY_TEXTURE_2D: 7397117f1b4Smrg return ctx->Const.MaxTextureLevels; 7407117f1b4Smrg case GL_TEXTURE_3D: 7417117f1b4Smrg case GL_PROXY_TEXTURE_3D: 7427117f1b4Smrg return ctx->Const.Max3DTextureLevels; 7437117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 7447117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 7457117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 7467117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 7477117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 7487117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 7497117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 7507117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 7514a49301eSmrg return ctx->Extensions.ARB_texture_cube_map 7524a49301eSmrg ? ctx->Const.MaxCubeTextureLevels : 0; 7537117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 7547117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 7554a49301eSmrg return ctx->Extensions.NV_texture_rectangle ? 1 : 0; 7564a49301eSmrg case GL_TEXTURE_1D_ARRAY_EXT: 7574a49301eSmrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 7584a49301eSmrg case GL_TEXTURE_2D_ARRAY_EXT: 7594a49301eSmrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 7604a49301eSmrg return ctx->Extensions.MESA_texture_array 7614a49301eSmrg ? ctx->Const.MaxTextureLevels : 0; 7627117f1b4Smrg default: 7637117f1b4Smrg return 0; /* bad target */ 7647117f1b4Smrg } 7657117f1b4Smrg} 7667117f1b4Smrg 7677117f1b4Smrg 7687117f1b4Smrg 7697117f1b4Smrg#if 000 /* not used anymore */ 7707117f1b4Smrg/* 7717117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer. In this case we 7727117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL 7737117f1b4Smrg * spec. 7747117f1b4Smrg */ 7757117f1b4Smrgstatic GLubyte * 7767117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format) 7777117f1b4Smrg{ 7787117f1b4Smrg const GLint components = _mesa_components_in_format(format); 7797117f1b4Smrg const GLint numPixels = width * height * depth; 7807117f1b4Smrg GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 7817117f1b4Smrg 7827117f1b4Smrg#ifdef DEBUG 7837117f1b4Smrg /* 7847117f1b4Smrg * Let's see if anyone finds this. If glTexImage2D() is called with 7857117f1b4Smrg * a NULL image pointer then load the texture image with something 7867117f1b4Smrg * interesting instead of leaving it indeterminate. 7877117f1b4Smrg */ 7887117f1b4Smrg if (data) { 7897117f1b4Smrg static const char message[8][32] = { 7907117f1b4Smrg " X X XXXXX XXX X ", 7917117f1b4Smrg " XX XX X X X X X ", 7927117f1b4Smrg " X X X X X X X ", 7937117f1b4Smrg " X X XXXX XXX XXXXX ", 7947117f1b4Smrg " X X X X X X ", 7957117f1b4Smrg " X X X X X X X ", 7967117f1b4Smrg " X X XXXXX XXX X X ", 7977117f1b4Smrg " " 7987117f1b4Smrg }; 7997117f1b4Smrg 8007117f1b4Smrg GLubyte *imgPtr = data; 8017117f1b4Smrg GLint h, i, j, k; 8027117f1b4Smrg for (h = 0; h < depth; h++) { 8037117f1b4Smrg for (i = 0; i < height; i++) { 8047117f1b4Smrg GLint srcRow = 7 - (i % 8); 8057117f1b4Smrg for (j = 0; j < width; j++) { 8067117f1b4Smrg GLint srcCol = j % 32; 8077117f1b4Smrg GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 8087117f1b4Smrg for (k = 0; k < components; k++) { 8097117f1b4Smrg *imgPtr++ = texel; 8107117f1b4Smrg } 8117117f1b4Smrg } 8127117f1b4Smrg } 8137117f1b4Smrg } 8147117f1b4Smrg } 8157117f1b4Smrg#endif 8167117f1b4Smrg 8177117f1b4Smrg return data; 8187117f1b4Smrg} 8197117f1b4Smrg#endif 8207117f1b4Smrg 8217117f1b4Smrg 8227117f1b4Smrg 8237117f1b4Smrg/** 8247117f1b4Smrg * Reset the fields of a gl_texture_image struct to zero. 8257117f1b4Smrg * 8267117f1b4Smrg * \param img texture image structure. 8277117f1b4Smrg * 8287117f1b4Smrg * This is called when a proxy texture test fails, we set all the 8297117f1b4Smrg * image members (except DriverData) to zero. 8307117f1b4Smrg * It's also used in glTexImage[123]D as a safeguard to be sure all 8317117f1b4Smrg * required fields get initialized properly by the Driver.TexImage[123]D 8327117f1b4Smrg * functions. 8337117f1b4Smrg */ 8347117f1b4Smrgstatic void 8357117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img) 8367117f1b4Smrg{ 8377117f1b4Smrg ASSERT(img); 8387117f1b4Smrg img->_BaseFormat = 0; 8397117f1b4Smrg img->InternalFormat = 0; 8407117f1b4Smrg img->Border = 0; 8417117f1b4Smrg img->Width = 0; 8427117f1b4Smrg img->Height = 0; 8437117f1b4Smrg img->Depth = 0; 8447117f1b4Smrg img->RowStride = 0; 8457117f1b4Smrg if (img->ImageOffsets) { 8467117f1b4Smrg _mesa_free(img->ImageOffsets); 8477117f1b4Smrg img->ImageOffsets = NULL; 8487117f1b4Smrg } 8497117f1b4Smrg img->Width2 = 0; 8507117f1b4Smrg img->Height2 = 0; 8517117f1b4Smrg img->Depth2 = 0; 8527117f1b4Smrg img->WidthLog2 = 0; 8537117f1b4Smrg img->HeightLog2 = 0; 8547117f1b4Smrg img->DepthLog2 = 0; 8557117f1b4Smrg img->Data = NULL; 8564a49301eSmrg img->TexFormat = MESA_FORMAT_NONE; 8577117f1b4Smrg img->FetchTexelc = NULL; 8587117f1b4Smrg img->FetchTexelf = NULL; 8597117f1b4Smrg} 8607117f1b4Smrg 8617117f1b4Smrg 8627117f1b4Smrg/** 8637117f1b4Smrg * Initialize basic fields of the gl_texture_image struct. 8647117f1b4Smrg * 8657117f1b4Smrg * \param ctx GL context. 8667117f1b4Smrg * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 8677117f1b4Smrg * \param img texture image structure to be initialized. 8687117f1b4Smrg * \param width image width. 8697117f1b4Smrg * \param height image height. 8707117f1b4Smrg * \param depth image depth. 8717117f1b4Smrg * \param border image border. 8727117f1b4Smrg * \param internalFormat internal format. 8737117f1b4Smrg * 8747117f1b4Smrg * Fills in the fields of \p img with the given information. 8757117f1b4Smrg * Note: width, height and depth include the border. 8767117f1b4Smrg */ 8777117f1b4Smrgvoid 8787117f1b4Smrg_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, 8797117f1b4Smrg struct gl_texture_image *img, 8807117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 8817117f1b4Smrg GLint border, GLenum internalFormat) 8827117f1b4Smrg{ 8837117f1b4Smrg GLint i; 8847117f1b4Smrg 8857117f1b4Smrg ASSERT(img); 8867117f1b4Smrg ASSERT(width >= 0); 8877117f1b4Smrg ASSERT(height >= 0); 8887117f1b4Smrg ASSERT(depth >= 0); 8897117f1b4Smrg 8907117f1b4Smrg img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 8917117f1b4Smrg ASSERT(img->_BaseFormat > 0); 8927117f1b4Smrg img->InternalFormat = internalFormat; 8937117f1b4Smrg img->Border = border; 8947117f1b4Smrg img->Width = width; 8957117f1b4Smrg img->Height = height; 8967117f1b4Smrg img->Depth = depth; 8974a49301eSmrg 8987117f1b4Smrg img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 8997117f1b4Smrg img->WidthLog2 = logbase2(img->Width2); 9004a49301eSmrg 9014a49301eSmrg if (height == 1) { /* 1-D texture */ 9024a49301eSmrg img->Height2 = 1; 9037117f1b4Smrg img->HeightLog2 = 0; 9044a49301eSmrg } 9054a49301eSmrg else { 9064a49301eSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 9077117f1b4Smrg img->HeightLog2 = logbase2(img->Height2); 9084a49301eSmrg } 9094a49301eSmrg 9104a49301eSmrg if (depth == 1) { /* 2-D texture */ 9114a49301eSmrg img->Depth2 = 1; 9127117f1b4Smrg img->DepthLog2 = 0; 9134a49301eSmrg } 9144a49301eSmrg else { 9154a49301eSmrg img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 9167117f1b4Smrg img->DepthLog2 = logbase2(img->Depth2); 9174a49301eSmrg } 9184a49301eSmrg 9197117f1b4Smrg img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 9207117f1b4Smrg 921c1f859d4Smrg if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 922c1f859d4Smrg (height == 1 || _mesa_is_pow_two(img->Height2)) && 923c1f859d4Smrg (depth == 1 || _mesa_is_pow_two(img->Depth2))) 9247117f1b4Smrg img->_IsPowerOfTwo = GL_TRUE; 9257117f1b4Smrg else 9267117f1b4Smrg img->_IsPowerOfTwo = GL_FALSE; 9277117f1b4Smrg 9287117f1b4Smrg /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 9297117f1b4Smrg img->RowStride = width; 9307117f1b4Smrg /* Allocate the ImageOffsets array and initialize to typical values. 9317117f1b4Smrg * We allocate the array for 1D/2D textures too in order to avoid special- 9327117f1b4Smrg * case code in the texstore routines. 9337117f1b4Smrg */ 9344a49301eSmrg if (img->ImageOffsets) 9354a49301eSmrg _mesa_free(img->ImageOffsets); 9367117f1b4Smrg img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint)); 9377117f1b4Smrg for (i = 0; i < depth; i++) { 9387117f1b4Smrg img->ImageOffsets[i] = i * width * height; 9397117f1b4Smrg } 9407117f1b4Smrg 9417117f1b4Smrg /* Compute Width/Height/DepthScale for mipmap lod computation */ 9427117f1b4Smrg if (target == GL_TEXTURE_RECTANGLE_NV) { 9437117f1b4Smrg /* scale = 1.0 since texture coords directly map to texels */ 9447117f1b4Smrg img->WidthScale = 1.0; 9457117f1b4Smrg img->HeightScale = 1.0; 9467117f1b4Smrg img->DepthScale = 1.0; 9477117f1b4Smrg } 9487117f1b4Smrg else { 9497117f1b4Smrg img->WidthScale = (GLfloat) img->Width; 9507117f1b4Smrg img->HeightScale = (GLfloat) img->Height; 9517117f1b4Smrg img->DepthScale = (GLfloat) img->Depth; 9527117f1b4Smrg } 9534a49301eSmrg 9544a49301eSmrg img->FetchTexelc = NULL; 9554a49301eSmrg img->FetchTexelf = NULL; 9564a49301eSmrg} 9574a49301eSmrg 9584a49301eSmrg 9594a49301eSmrg/** 9604a49301eSmrg * Free and clear fields of the gl_texture_image struct. 9614a49301eSmrg * 9624a49301eSmrg * \param ctx GL context. 9634a49301eSmrg * \param texImage texture image structure to be cleared. 9644a49301eSmrg * 9654a49301eSmrg * After the call, \p texImage will have no data associated with it. Its 9664a49301eSmrg * fields are cleared so that its parent object will test incomplete. 9674a49301eSmrg */ 9684a49301eSmrgvoid 9694a49301eSmrg_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage) 9704a49301eSmrg{ 9714a49301eSmrg ctx->Driver.FreeTexImageData(ctx, texImage); 9724a49301eSmrg clear_teximage_fields(texImage); 9737117f1b4Smrg} 9747117f1b4Smrg 9757117f1b4Smrg 9767117f1b4Smrg/** 9777117f1b4Smrg * This is the fallback for Driver.TestProxyTexImage(). Test the texture 9787117f1b4Smrg * level, width, height and depth against the ctx->Const limits for textures. 9797117f1b4Smrg * 9807117f1b4Smrg * A hardware driver might override this function if, for example, the 9817117f1b4Smrg * max 3D texture size is 512x512x64 (i.e. not a cube). 9827117f1b4Smrg * 9837117f1b4Smrg * Note that width, height, depth == 0 is not an error. However, a 9847117f1b4Smrg * texture with zero width/height/depth will be considered "incomplete" 9857117f1b4Smrg * and texturing will effectively be disabled. 9867117f1b4Smrg * 9877117f1b4Smrg * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 9887117f1b4Smrg * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 9897117f1b4Smrg * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 9907117f1b4Smrg * \param level as passed to glTexImage 9917117f1b4Smrg * \param internalFormat as passed to glTexImage 9927117f1b4Smrg * \param format as passed to glTexImage 9937117f1b4Smrg * \param type as passed to glTexImage 9947117f1b4Smrg * \param width as passed to glTexImage 9957117f1b4Smrg * \param height as passed to glTexImage 9967117f1b4Smrg * \param depth as passed to glTexImage 9977117f1b4Smrg * \param border as passed to glTexImage 9987117f1b4Smrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 9997117f1b4Smrg */ 10007117f1b4SmrgGLboolean 10017117f1b4Smrg_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 10027117f1b4Smrg GLint internalFormat, GLenum format, GLenum type, 10037117f1b4Smrg GLint width, GLint height, GLint depth, GLint border) 10047117f1b4Smrg{ 10057117f1b4Smrg GLint maxSize; 10067117f1b4Smrg 10077117f1b4Smrg (void) internalFormat; 10087117f1b4Smrg (void) format; 10097117f1b4Smrg (void) type; 10107117f1b4Smrg 10117117f1b4Smrg switch (target) { 10127117f1b4Smrg case GL_PROXY_TEXTURE_1D: 10137117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 10147117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 10157117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1016c1f859d4Smrg width >0 && !_mesa_is_pow_two(width - 2 * border)) || 10177117f1b4Smrg level >= ctx->Const.MaxTextureLevels) { 10187117f1b4Smrg /* bad width or level */ 10197117f1b4Smrg return GL_FALSE; 10207117f1b4Smrg } 10217117f1b4Smrg return GL_TRUE; 10227117f1b4Smrg case GL_PROXY_TEXTURE_2D: 10237117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 10247117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 10257117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1026c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 10277117f1b4Smrg height < 2 * border || height > 2 + maxSize || 10287117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1029c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 10307117f1b4Smrg level >= ctx->Const.MaxTextureLevels) { 10317117f1b4Smrg /* bad width or height or level */ 10327117f1b4Smrg return GL_FALSE; 10337117f1b4Smrg } 10347117f1b4Smrg return GL_TRUE; 10357117f1b4Smrg case GL_PROXY_TEXTURE_3D: 10367117f1b4Smrg maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 10377117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 10387117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1039c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 10407117f1b4Smrg height < 2 * border || height > 2 + maxSize || 10417117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1042c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 10437117f1b4Smrg depth < 2 * border || depth > 2 + maxSize || 10447117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1045c1f859d4Smrg depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) || 10467117f1b4Smrg level >= ctx->Const.Max3DTextureLevels) { 10477117f1b4Smrg /* bad width or height or depth or level */ 10487117f1b4Smrg return GL_FALSE; 10497117f1b4Smrg } 10507117f1b4Smrg return GL_TRUE; 10517117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 10527117f1b4Smrg if (width < 0 || width > ctx->Const.MaxTextureRectSize || 10537117f1b4Smrg height < 0 || height > ctx->Const.MaxTextureRectSize || 10547117f1b4Smrg level != 0) { 10557117f1b4Smrg /* bad width or height or level */ 10567117f1b4Smrg return GL_FALSE; 10577117f1b4Smrg } 10587117f1b4Smrg return GL_TRUE; 10597117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 10607117f1b4Smrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 10617117f1b4Smrg if (width < 2 * border || width > 2 + maxSize || 10627117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1063c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 10647117f1b4Smrg height < 2 * border || height > 2 + maxSize || 10657117f1b4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1066c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 10677117f1b4Smrg level >= ctx->Const.MaxCubeTextureLevels) { 10687117f1b4Smrg /* bad width or height */ 10697117f1b4Smrg return GL_FALSE; 10707117f1b4Smrg } 10717117f1b4Smrg return GL_TRUE; 1072c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1073c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1074c1f859d4Smrg if (width < 2 * border || width > 2 + maxSize || 1075c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1076c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1077c1f859d4Smrg level >= ctx->Const.MaxTextureLevels) { 1078c1f859d4Smrg /* bad width or level */ 1079c1f859d4Smrg return GL_FALSE; 1080c1f859d4Smrg } 1081c1f859d4Smrg 1082c1f859d4Smrg if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) { 1083c1f859d4Smrg return GL_FALSE; 1084c1f859d4Smrg } 1085c1f859d4Smrg return GL_TRUE; 1086c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1087c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1088c1f859d4Smrg if (width < 2 * border || width > 2 + maxSize || 1089c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1090c1f859d4Smrg width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1091c1f859d4Smrg height < 2 * border || height > 2 + maxSize || 1092c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && 1093c1f859d4Smrg height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1094c1f859d4Smrg level >= ctx->Const.MaxTextureLevels) { 1095c1f859d4Smrg /* bad width or height or level */ 1096c1f859d4Smrg return GL_FALSE; 1097c1f859d4Smrg } 1098c1f859d4Smrg if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) { 1099c1f859d4Smrg return GL_FALSE; 1100c1f859d4Smrg } 1101c1f859d4Smrg return GL_TRUE; 11027117f1b4Smrg default: 11037117f1b4Smrg _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 11047117f1b4Smrg return GL_FALSE; 11057117f1b4Smrg } 11067117f1b4Smrg} 11077117f1b4Smrg 11087117f1b4Smrg 11097117f1b4Smrg/** 11107117f1b4Smrg * Helper function to determine whether a target supports compressed textures 11117117f1b4Smrg */ 11127117f1b4Smrgstatic GLboolean 11137117f1b4Smrgtarget_can_be_compressed(GLcontext *ctx, GLenum target) 11147117f1b4Smrg{ 11157117f1b4Smrg return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 11167117f1b4Smrg || ((ctx->Extensions.ARB_texture_cube_map && 11177117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP || 11187117f1b4Smrg (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 1119c1f859d4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)))) 1120c1f859d4Smrg || ((ctx->Extensions.MESA_texture_array && 1121c1f859d4Smrg ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) || 1122c1f859d4Smrg (target == GL_TEXTURE_2D_ARRAY_EXT))))); 11237117f1b4Smrg} 11247117f1b4Smrg 11257117f1b4Smrg 11267117f1b4Smrg/** 11277117f1b4Smrg * Test the glTexImage[123]D() parameters for errors. 11287117f1b4Smrg * 11297117f1b4Smrg * \param ctx GL context. 11307117f1b4Smrg * \param target texture target given by the user. 11317117f1b4Smrg * \param level image level given by the user. 11327117f1b4Smrg * \param internalFormat internal format given by the user. 11337117f1b4Smrg * \param format pixel data format given by the user. 11347117f1b4Smrg * \param type pixel data type given by the user. 11357117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 11367117f1b4Smrg * \param width image width given by the user. 11377117f1b4Smrg * \param height image height given by the user. 11387117f1b4Smrg * \param depth image depth given by the user. 11397117f1b4Smrg * \param border image border given by the user. 11407117f1b4Smrg * 11417117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 11427117f1b4Smrg * 11437117f1b4Smrg * Verifies each of the parameters against the constants specified in 11447117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 11457117f1b4Smrg * OpenGL specification. 11467117f1b4Smrg */ 11477117f1b4Smrgstatic GLboolean 11487117f1b4Smrgtexture_error_check( GLcontext *ctx, GLenum target, 11497117f1b4Smrg GLint level, GLint internalFormat, 11507117f1b4Smrg GLenum format, GLenum type, 11517117f1b4Smrg GLuint dimensions, 11527117f1b4Smrg GLint width, GLint height, 11537117f1b4Smrg GLint depth, GLint border ) 11547117f1b4Smrg{ 11557117f1b4Smrg const GLboolean isProxy = _mesa_is_proxy_texture(target); 11567117f1b4Smrg GLboolean sizeOK = GL_TRUE; 11577117f1b4Smrg GLboolean colorFormat, indexFormat; 11587117f1b4Smrg GLenum proxy_target; 11597117f1b4Smrg 11607117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 11617117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 11627117f1b4Smrg if (!isProxy) { 11637117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 11647117f1b4Smrg "glTexImage%dD(level=%d)", dimensions, level); 11657117f1b4Smrg } 11667117f1b4Smrg return GL_TRUE; 11677117f1b4Smrg } 11687117f1b4Smrg 11697117f1b4Smrg /* Check border */ 11707117f1b4Smrg if (border < 0 || border > 1 || 11717117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 11727117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 11737117f1b4Smrg if (!isProxy) { 11747117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 11757117f1b4Smrg "glTexImage%dD(border=%d)", dimensions, border); 11767117f1b4Smrg } 11777117f1b4Smrg return GL_TRUE; 11787117f1b4Smrg } 11797117f1b4Smrg 11807117f1b4Smrg if (width < 0 || height < 0 || depth < 0) { 11817117f1b4Smrg if (!isProxy) { 11827117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 11837117f1b4Smrg "glTexImage%dD(width, height or depth < 0)", dimensions); 11847117f1b4Smrg } 11857117f1b4Smrg return GL_TRUE; 11867117f1b4Smrg } 11877117f1b4Smrg 11887117f1b4Smrg /* Check target and call ctx->Driver.TestProxyTexImage() to check the 11897117f1b4Smrg * level, width, height and depth. 11907117f1b4Smrg */ 11917117f1b4Smrg if (dimensions == 1) { 11927117f1b4Smrg if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 11937117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_1D; 11947117f1b4Smrg height = 1; 11957117f1b4Smrg depth = 1; 11967117f1b4Smrg } 11977117f1b4Smrg else { 11987117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 11997117f1b4Smrg return GL_TRUE; 12007117f1b4Smrg } 12017117f1b4Smrg } 12027117f1b4Smrg else if (dimensions == 2) { 12037117f1b4Smrg depth = 1; 12047117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 12057117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_2D; 12067117f1b4Smrg } 12077117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 12087117f1b4Smrg (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 12097117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 12107117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 12117117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 12127117f1b4Smrg return GL_TRUE; 12137117f1b4Smrg } 12147117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 12157117f1b4Smrg sizeOK = (width == height); 12167117f1b4Smrg } 12177117f1b4Smrg else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 12187117f1b4Smrg target == GL_TEXTURE_RECTANGLE_NV) { 12197117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 12207117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 12217117f1b4Smrg return GL_TRUE; 12227117f1b4Smrg } 12237117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 12247117f1b4Smrg } 1225c1f859d4Smrg else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 1226c1f859d4Smrg target == GL_TEXTURE_1D_ARRAY_EXT) { 1227c1f859d4Smrg proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; 1228c1f859d4Smrg } 12297117f1b4Smrg else { 12307117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 12317117f1b4Smrg return GL_TRUE; 12327117f1b4Smrg } 12337117f1b4Smrg } 12347117f1b4Smrg else if (dimensions == 3) { 12357117f1b4Smrg if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 12367117f1b4Smrg proxy_target = GL_PROXY_TEXTURE_3D; 12377117f1b4Smrg } 1238c1f859d4Smrg else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT || 1239c1f859d4Smrg target == GL_TEXTURE_2D_ARRAY_EXT) { 1240c1f859d4Smrg proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; 1241c1f859d4Smrg } 12427117f1b4Smrg else { 12437117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 12447117f1b4Smrg return GL_TRUE; 12457117f1b4Smrg } 12467117f1b4Smrg } 12477117f1b4Smrg else { 12487117f1b4Smrg _mesa_problem( ctx, "bad dims in texture_error_check" ); 12497117f1b4Smrg return GL_TRUE; 12507117f1b4Smrg } 12517117f1b4Smrg 12527117f1b4Smrg sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 12537117f1b4Smrg internalFormat, format, 12547117f1b4Smrg type, width, height, 12557117f1b4Smrg depth, border); 12567117f1b4Smrg if (!sizeOK) { 12577117f1b4Smrg if (!isProxy) { 12587117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 12597117f1b4Smrg "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 12607117f1b4Smrg dimensions, level, width, height, depth); 12617117f1b4Smrg } 12627117f1b4Smrg return GL_TRUE; 12637117f1b4Smrg } 12647117f1b4Smrg 12657117f1b4Smrg /* Check internalFormat */ 12667117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 12677117f1b4Smrg if (!isProxy) { 12687117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 12694a49301eSmrg "glTexImage%dD(internalFormat=%s)", 12704a49301eSmrg dimensions, _mesa_lookup_enum_by_nr(internalFormat)); 12717117f1b4Smrg } 12727117f1b4Smrg return GL_TRUE; 12737117f1b4Smrg } 12747117f1b4Smrg 12757117f1b4Smrg /* Check incoming image format and type */ 12767117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 12777117f1b4Smrg /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 12787117f1b4Smrg * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 12797117f1b4Smrg */ 12807117f1b4Smrg if (!isProxy) { 12817117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 12824a49301eSmrg "glTexImage%dD(incompatible format 0x%x, type 0x%x)", 12834a49301eSmrg dimensions, format, type); 12847117f1b4Smrg } 12857117f1b4Smrg return GL_TRUE; 12867117f1b4Smrg } 12877117f1b4Smrg 12887117f1b4Smrg /* make sure internal format and format basically agree */ 1289c1f859d4Smrg colorFormat = _mesa_is_color_format(format); 12904a49301eSmrg indexFormat = _mesa_is_index_format(format); 1291c1f859d4Smrg if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 12924a49301eSmrg (_mesa_is_index_format(internalFormat) && !indexFormat) || 12934a49301eSmrg (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || 12944a49301eSmrg (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || 12954a49301eSmrg (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || 12964a49301eSmrg (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) { 12977117f1b4Smrg if (!isProxy) 12987117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 12994a49301eSmrg "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)", 13004a49301eSmrg dimensions, internalFormat, format); 13017117f1b4Smrg return GL_TRUE; 13027117f1b4Smrg } 13037117f1b4Smrg 13047117f1b4Smrg /* additional checks for ycbcr textures */ 13057117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) { 13067117f1b4Smrg ASSERT(ctx->Extensions.MESA_ycbcr_texture); 13077117f1b4Smrg if (type != GL_UNSIGNED_SHORT_8_8_MESA && 13087117f1b4Smrg type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 13097117f1b4Smrg char message[100]; 13107117f1b4Smrg _mesa_sprintf(message, 13117117f1b4Smrg "glTexImage%d(format/type YCBCR mismatch", dimensions); 13127117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, message); 13137117f1b4Smrg return GL_TRUE; /* error */ 13147117f1b4Smrg } 13157117f1b4Smrg if (target != GL_TEXTURE_2D && 13167117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 13177117f1b4Smrg target != GL_TEXTURE_RECTANGLE_NV && 13187117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 13197117f1b4Smrg if (!isProxy) 13207117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 13217117f1b4Smrg return GL_TRUE; 13227117f1b4Smrg } 13237117f1b4Smrg if (border != 0) { 13247117f1b4Smrg if (!isProxy) { 13257117f1b4Smrg char message[100]; 13267117f1b4Smrg _mesa_sprintf(message, 13277117f1b4Smrg "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 13287117f1b4Smrg dimensions, border); 13297117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, message); 13307117f1b4Smrg } 13317117f1b4Smrg return GL_TRUE; 13327117f1b4Smrg } 13337117f1b4Smrg } 13347117f1b4Smrg 13357117f1b4Smrg /* additional checks for depth textures */ 13367117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 13377117f1b4Smrg /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 13387117f1b4Smrg if (target != GL_TEXTURE_1D && 13397117f1b4Smrg target != GL_PROXY_TEXTURE_1D && 13407117f1b4Smrg target != GL_TEXTURE_2D && 13417117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 13427117f1b4Smrg target != GL_TEXTURE_RECTANGLE_ARB && 13437117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 13447117f1b4Smrg if (!isProxy) 13457117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 13467117f1b4Smrg "glTexImage(target/internalFormat)"); 13477117f1b4Smrg return GL_TRUE; 13487117f1b4Smrg } 13497117f1b4Smrg } 13507117f1b4Smrg 13517117f1b4Smrg /* additional checks for compressed textures */ 13527117f1b4Smrg if (is_compressed_format(ctx, internalFormat)) { 13537117f1b4Smrg if (!target_can_be_compressed(ctx, target) && !isProxy) { 13547117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 13557117f1b4Smrg "glTexImage%d(target)", dimensions); 13567117f1b4Smrg return GL_TRUE; 13577117f1b4Smrg } 13587117f1b4Smrg if (border != 0) { 13597117f1b4Smrg if (!isProxy) { 13607117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 13617117f1b4Smrg "glTexImage%D(border!=0)", dimensions); 13627117f1b4Smrg } 13637117f1b4Smrg return GL_TRUE; 13647117f1b4Smrg } 13657117f1b4Smrg } 13667117f1b4Smrg 13677117f1b4Smrg /* if we get here, the parameters are OK */ 13687117f1b4Smrg return GL_FALSE; 13697117f1b4Smrg} 13707117f1b4Smrg 13717117f1b4Smrg 13727117f1b4Smrg/** 13737117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors. 13747117f1b4Smrg * 13757117f1b4Smrg * \param ctx GL context. 13767117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 13777117f1b4Smrg * \param target texture target given by the user. 13787117f1b4Smrg * \param level image level given by the user. 13797117f1b4Smrg * \param xoffset sub-image x offset given by the user. 13807117f1b4Smrg * \param yoffset sub-image y offset given by the user. 13817117f1b4Smrg * \param zoffset sub-image z offset given by the user. 13827117f1b4Smrg * \param format pixel data format given by the user. 13837117f1b4Smrg * \param type pixel data type given by the user. 13847117f1b4Smrg * \param width image width given by the user. 13857117f1b4Smrg * \param height image height given by the user. 13867117f1b4Smrg * \param depth image depth given by the user. 13877117f1b4Smrg * 13887117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 13897117f1b4Smrg * 13907117f1b4Smrg * Verifies each of the parameters against the constants specified in 13917117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 13927117f1b4Smrg * OpenGL specification. 13937117f1b4Smrg */ 13947117f1b4Smrgstatic GLboolean 13957117f1b4Smrgsubtexture_error_check( GLcontext *ctx, GLuint dimensions, 13967117f1b4Smrg GLenum target, GLint level, 13977117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 13987117f1b4Smrg GLint width, GLint height, GLint depth, 13997117f1b4Smrg GLenum format, GLenum type ) 14007117f1b4Smrg{ 14017117f1b4Smrg /* Check target */ 14027117f1b4Smrg if (dimensions == 1) { 14037117f1b4Smrg if (target != GL_TEXTURE_1D) { 14047117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 14057117f1b4Smrg return GL_TRUE; 14067117f1b4Smrg } 14077117f1b4Smrg } 14087117f1b4Smrg else if (dimensions == 2) { 14097117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 14107117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 14117117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 14127117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 14137117f1b4Smrg return GL_TRUE; 14147117f1b4Smrg } 14157117f1b4Smrg } 14167117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 14177117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 14187117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 14197117f1b4Smrg return GL_TRUE; 14207117f1b4Smrg } 14217117f1b4Smrg } 1422c1f859d4Smrg else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1423c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1424c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1425c1f859d4Smrg return GL_TRUE; 1426c1f859d4Smrg } 1427c1f859d4Smrg } 14287117f1b4Smrg else if (target != GL_TEXTURE_2D) { 14297117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 14307117f1b4Smrg return GL_TRUE; 14317117f1b4Smrg } 14327117f1b4Smrg } 14337117f1b4Smrg else if (dimensions == 3) { 1434c1f859d4Smrg if (target == GL_TEXTURE_2D_ARRAY_EXT) { 1435c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1436c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1437c1f859d4Smrg return GL_TRUE; 1438c1f859d4Smrg } 1439c1f859d4Smrg } 1440c1f859d4Smrg else if (target != GL_TEXTURE_3D) { 14417117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 14427117f1b4Smrg return GL_TRUE; 14437117f1b4Smrg } 14447117f1b4Smrg } 14457117f1b4Smrg else { 14467117f1b4Smrg _mesa_problem( ctx, "invalid dims in texture_error_check" ); 14477117f1b4Smrg return GL_TRUE; 14487117f1b4Smrg } 14497117f1b4Smrg 14507117f1b4Smrg /* Basic level check */ 14517117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 14527117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 14537117f1b4Smrg return GL_TRUE; 14547117f1b4Smrg } 14557117f1b4Smrg 14567117f1b4Smrg if (width < 0) { 14577117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14587117f1b4Smrg "glTexSubImage%dD(width=%d)", dimensions, width); 14597117f1b4Smrg return GL_TRUE; 14607117f1b4Smrg } 14617117f1b4Smrg if (height < 0 && dimensions > 1) { 14627117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14637117f1b4Smrg "glTexSubImage%dD(height=%d)", dimensions, height); 14647117f1b4Smrg return GL_TRUE; 14657117f1b4Smrg } 14667117f1b4Smrg if (depth < 0 && dimensions > 2) { 14677117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 14687117f1b4Smrg "glTexSubImage%dD(depth=%d)", dimensions, depth); 14697117f1b4Smrg return GL_TRUE; 14707117f1b4Smrg } 14717117f1b4Smrg 14727117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 14737117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 14744a49301eSmrg "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)", 14754a49301eSmrg dimensions, format, type); 14767117f1b4Smrg return GL_TRUE; 14777117f1b4Smrg } 14787117f1b4Smrg 14797117f1b4Smrg return GL_FALSE; 14807117f1b4Smrg} 14817117f1b4Smrg 14824a49301eSmrg 14834a49301eSmrg/** 14844a49301eSmrg * Do second part of glTexSubImage which depends on the destination texture. 14854a49301eSmrg * \return GL_TRUE if error recorded, GL_FALSE otherwise 14864a49301eSmrg */ 14877117f1b4Smrgstatic GLboolean 14887117f1b4Smrgsubtexture_error_check2( GLcontext *ctx, GLuint dimensions, 14897117f1b4Smrg GLenum target, GLint level, 14907117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 14917117f1b4Smrg GLint width, GLint height, GLint depth, 14927117f1b4Smrg GLenum format, GLenum type, 14937117f1b4Smrg const struct gl_texture_image *destTex ) 14947117f1b4Smrg{ 14957117f1b4Smrg if (!destTex) { 14967117f1b4Smrg /* undefined image level */ 14977117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 14987117f1b4Smrg return GL_TRUE; 14997117f1b4Smrg } 15007117f1b4Smrg 15017117f1b4Smrg if (xoffset < -((GLint)destTex->Border)) { 15027117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 15037117f1b4Smrg dimensions); 15047117f1b4Smrg return GL_TRUE; 15057117f1b4Smrg } 15067117f1b4Smrg if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 15077117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 15087117f1b4Smrg dimensions); 15097117f1b4Smrg return GL_TRUE; 15107117f1b4Smrg } 15117117f1b4Smrg if (dimensions > 1) { 15127117f1b4Smrg if (yoffset < -((GLint)destTex->Border)) { 15137117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 15147117f1b4Smrg dimensions); 15157117f1b4Smrg return GL_TRUE; 15167117f1b4Smrg } 15177117f1b4Smrg if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 15187117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 15197117f1b4Smrg dimensions); 15207117f1b4Smrg return GL_TRUE; 15217117f1b4Smrg } 15227117f1b4Smrg } 15237117f1b4Smrg if (dimensions > 2) { 15247117f1b4Smrg if (zoffset < -((GLint)destTex->Border)) { 15257117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 15267117f1b4Smrg return GL_TRUE; 15277117f1b4Smrg } 15287117f1b4Smrg if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 15297117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 15307117f1b4Smrg return GL_TRUE; 15317117f1b4Smrg } 15327117f1b4Smrg } 15337117f1b4Smrg 15344a49301eSmrg if (_mesa_is_format_compressed(destTex->TexFormat)) { 15354a49301eSmrg GLuint bw, bh; 15367117f1b4Smrg 15377117f1b4Smrg if (!target_can_be_compressed(ctx, target)) { 15387117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 15394a49301eSmrg "glTexSubImage%D(target=%s)", dimensions, 15404a49301eSmrg _mesa_lookup_enum_by_nr(target)); 15417117f1b4Smrg return GL_TRUE; 15427117f1b4Smrg } 15434a49301eSmrg 15444a49301eSmrg /* do tests which depend on compression block size */ 15454a49301eSmrg _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); 15464a49301eSmrg 15474a49301eSmrg /* offset must be multiple of block size */ 15484a49301eSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0)) { 15497117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 15504a49301eSmrg "glTexSubImage%D(xoffset = %d, yoffset = %d)", 15514a49301eSmrg dimensions, xoffset, yoffset); 15527117f1b4Smrg return GL_TRUE; 15537117f1b4Smrg } 15544a49301eSmrg /* size must be multiple of bw by bh or equal to whole texture size */ 15554a49301eSmrg if ((width % bw != 0) && (GLuint) width != destTex->Width) { 15567117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 15574a49301eSmrg "glTexSubImage%D(width = %d)", dimensions, width); 15587117f1b4Smrg return GL_TRUE; 15597117f1b4Smrg } 15604a49301eSmrg if ((height % bh != 0) && (GLuint) height != destTex->Height) { 15617117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 15624a49301eSmrg "glTexSubImage%D(height = %d)", dimensions, height); 15637117f1b4Smrg return GL_TRUE; 15647117f1b4Smrg } 15657117f1b4Smrg } 15667117f1b4Smrg 15677117f1b4Smrg return GL_FALSE; 15687117f1b4Smrg} 15697117f1b4Smrg 15707117f1b4Smrg 15717117f1b4Smrg/** 15727117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors. 15737117f1b4Smrg * 15747117f1b4Smrg * \param ctx GL context. 15757117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 15767117f1b4Smrg * \param target texture target given by the user. 15777117f1b4Smrg * \param level image level given by the user. 15787117f1b4Smrg * \param internalFormat internal format given by the user. 15797117f1b4Smrg * \param width image width given by the user. 15807117f1b4Smrg * \param height image height given by the user. 15817117f1b4Smrg * \param border texture border. 15827117f1b4Smrg * 15837117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 15847117f1b4Smrg * 15857117f1b4Smrg * Verifies each of the parameters against the constants specified in 15867117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the 15877117f1b4Smrg * OpenGL specification. 15887117f1b4Smrg */ 15897117f1b4Smrgstatic GLboolean 15907117f1b4Smrgcopytexture_error_check( GLcontext *ctx, GLuint dimensions, 15917117f1b4Smrg GLenum target, GLint level, GLint internalFormat, 15927117f1b4Smrg GLint width, GLint height, GLint border ) 15937117f1b4Smrg{ 15947117f1b4Smrg GLenum type; 15957117f1b4Smrg GLboolean sizeOK; 15967117f1b4Smrg GLint format; 15977117f1b4Smrg 15987117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 15997117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 16007117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16017117f1b4Smrg "glCopyTexImage%dD(level=%d)", dimensions, level); 16027117f1b4Smrg return GL_TRUE; 16037117f1b4Smrg } 16047117f1b4Smrg 16057117f1b4Smrg /* Check that the source buffer is complete */ 16067117f1b4Smrg if (ctx->ReadBuffer->Name) { 16077117f1b4Smrg _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 16087117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 16097117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 16107117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 16117117f1b4Smrg return GL_TRUE; 16127117f1b4Smrg } 16137117f1b4Smrg } 16147117f1b4Smrg 16157117f1b4Smrg /* Check border */ 16167117f1b4Smrg if (border < 0 || border > 1 || 16177117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 16187117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 16197117f1b4Smrg return GL_TRUE; 16207117f1b4Smrg } 16217117f1b4Smrg 16227117f1b4Smrg format = _mesa_base_tex_format(ctx, internalFormat); 16237117f1b4Smrg if (format < 0) { 16247117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16257117f1b4Smrg "glCopyTexImage%dD(internalFormat)", dimensions); 16267117f1b4Smrg return GL_TRUE; 16277117f1b4Smrg } 16287117f1b4Smrg 16297117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, format)) { 16307117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 16317117f1b4Smrg "glCopyTexImage%dD(missing readbuffer)", dimensions); 16327117f1b4Smrg return GL_TRUE; 16337117f1b4Smrg } 16347117f1b4Smrg 16354a49301eSmrg /* NOTE: the format and type aren't really significant for 16364a49301eSmrg * TestProxyTexImage(). Only the internalformat really matters. 16377117f1b4Smrg */ 16387117f1b4Smrg type = GL_FLOAT; 16397117f1b4Smrg 16407117f1b4Smrg /* Check target and call ctx->Driver.TestProxyTexImage() to check the 16417117f1b4Smrg * level, width, height and depth. 16427117f1b4Smrg */ 16437117f1b4Smrg if (dimensions == 1) { 16447117f1b4Smrg if (target == GL_TEXTURE_1D) { 16457117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 16467117f1b4Smrg level, internalFormat, 16477117f1b4Smrg format, type, 16487117f1b4Smrg width, 1, 1, border); 16497117f1b4Smrg } 16507117f1b4Smrg else { 16517117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 16527117f1b4Smrg return GL_TRUE; 16537117f1b4Smrg } 16547117f1b4Smrg } 16557117f1b4Smrg else if (dimensions == 2) { 16567117f1b4Smrg if (target == GL_TEXTURE_2D) { 16577117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 16587117f1b4Smrg level, internalFormat, 16597117f1b4Smrg format, type, 16607117f1b4Smrg width, height, 1, border); 16617117f1b4Smrg } 16627117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 16637117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 16647117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 16657117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 16667117f1b4Smrg return GL_TRUE; 16677117f1b4Smrg } 16687117f1b4Smrg sizeOK = (width == height) && 16697117f1b4Smrg ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 16707117f1b4Smrg level, internalFormat, format, type, 16717117f1b4Smrg width, height, 1, border); 16727117f1b4Smrg } 16737117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 16747117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 16757117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 16767117f1b4Smrg return GL_TRUE; 16777117f1b4Smrg } 16787117f1b4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, 16797117f1b4Smrg GL_PROXY_TEXTURE_RECTANGLE_NV, 16807117f1b4Smrg level, internalFormat, 16817117f1b4Smrg format, type, 16827117f1b4Smrg width, height, 1, border); 16837117f1b4Smrg } 1684c1f859d4Smrg else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1685c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1686c1f859d4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)"); 1687c1f859d4Smrg return GL_TRUE; 1688c1f859d4Smrg } 1689c1f859d4Smrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1690c1f859d4Smrg GL_PROXY_TEXTURE_1D_ARRAY_EXT, 1691c1f859d4Smrg level, internalFormat, 1692c1f859d4Smrg format, type, 1693c1f859d4Smrg width, height, 1, border); 1694c1f859d4Smrg } 16957117f1b4Smrg else { 16967117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 16977117f1b4Smrg return GL_TRUE; 16987117f1b4Smrg } 16997117f1b4Smrg } 17007117f1b4Smrg else { 17017117f1b4Smrg _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 17027117f1b4Smrg return GL_TRUE; 17037117f1b4Smrg } 17047117f1b4Smrg 17057117f1b4Smrg if (!sizeOK) { 17067117f1b4Smrg if (dimensions == 1) { 17077117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17087117f1b4Smrg "glCopyTexImage1D(width=%d)", width); 17097117f1b4Smrg } 17107117f1b4Smrg else { 17117117f1b4Smrg ASSERT(dimensions == 2); 17127117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17137117f1b4Smrg "glCopyTexImage2D(width=%d, height=%d)", width, height); 17147117f1b4Smrg } 17157117f1b4Smrg return GL_TRUE; 17167117f1b4Smrg } 17177117f1b4Smrg 17187117f1b4Smrg if (is_compressed_format(ctx, internalFormat)) { 1719c1f859d4Smrg if (!target_can_be_compressed(ctx, target)) { 17207117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 17217117f1b4Smrg "glCopyTexImage%d(target)", dimensions); 17227117f1b4Smrg return GL_TRUE; 17237117f1b4Smrg } 17247117f1b4Smrg if (border != 0) { 17257117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17267117f1b4Smrg "glCopyTexImage%D(border!=0)", dimensions); 17277117f1b4Smrg return GL_TRUE; 17287117f1b4Smrg } 17297117f1b4Smrg } 17304a49301eSmrg else if (_mesa_is_depth_format(internalFormat)) { 17317117f1b4Smrg /* make sure we have depth/stencil buffers */ 17327117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 17337117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17347117f1b4Smrg "glCopyTexImage%D(no depth)", dimensions); 17357117f1b4Smrg return GL_TRUE; 17367117f1b4Smrg } 17377117f1b4Smrg } 17384a49301eSmrg else if (_mesa_is_depthstencil_format(internalFormat)) { 17397117f1b4Smrg /* make sure we have depth/stencil buffers */ 17407117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 17417117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17427117f1b4Smrg "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 17437117f1b4Smrg return GL_TRUE; 17447117f1b4Smrg } 17457117f1b4Smrg } 17467117f1b4Smrg 17477117f1b4Smrg /* if we get here, the parameters are OK */ 17487117f1b4Smrg return GL_FALSE; 17497117f1b4Smrg} 17507117f1b4Smrg 17517117f1b4Smrg 17527117f1b4Smrg/** 17537117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors. 1754c1f859d4Smrg * Note that this is the first part of error checking. 1755c1f859d4Smrg * See also copytexsubimage_error_check2() below for the second part. 17567117f1b4Smrg * 17577117f1b4Smrg * \param ctx GL context. 17587117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 17597117f1b4Smrg * \param target texture target given by the user. 17607117f1b4Smrg * \param level image level given by the user. 17617117f1b4Smrg * 17627117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 17637117f1b4Smrg */ 17647117f1b4Smrgstatic GLboolean 1765c1f859d4Smrgcopytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions, 1766c1f859d4Smrg GLenum target, GLint level) 17677117f1b4Smrg{ 17687117f1b4Smrg /* Check that the source buffer is complete */ 17697117f1b4Smrg if (ctx->ReadBuffer->Name) { 17707117f1b4Smrg _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 17717117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 17727117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 17737117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 17747117f1b4Smrg return GL_TRUE; 17757117f1b4Smrg } 17767117f1b4Smrg } 17777117f1b4Smrg 1778c1f859d4Smrg /* Check target */ 17797117f1b4Smrg if (dimensions == 1) { 17807117f1b4Smrg if (target != GL_TEXTURE_1D) { 17817117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 17827117f1b4Smrg return GL_TRUE; 17837117f1b4Smrg } 17847117f1b4Smrg } 17857117f1b4Smrg else if (dimensions == 2) { 17867117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 17877117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 17887117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) { 17897117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 17907117f1b4Smrg return GL_TRUE; 17917117f1b4Smrg } 17927117f1b4Smrg } 17937117f1b4Smrg else if (target == GL_TEXTURE_RECTANGLE_NV) { 17947117f1b4Smrg if (!ctx->Extensions.NV_texture_rectangle) { 17957117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 17967117f1b4Smrg return GL_TRUE; 17977117f1b4Smrg } 17987117f1b4Smrg } 1799c1f859d4Smrg else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1800c1f859d4Smrg if (!ctx->Extensions.MESA_texture_array) { 1801c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1802c1f859d4Smrg return GL_TRUE; 1803c1f859d4Smrg } 1804c1f859d4Smrg } 18057117f1b4Smrg else if (target != GL_TEXTURE_2D) { 18067117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 18077117f1b4Smrg return GL_TRUE; 18087117f1b4Smrg } 18097117f1b4Smrg } 18107117f1b4Smrg else if (dimensions == 3) { 1811c1f859d4Smrg if (((target != GL_TEXTURE_2D_ARRAY_EXT) || 1812c1f859d4Smrg (!ctx->Extensions.MESA_texture_array)) 1813c1f859d4Smrg && (target != GL_TEXTURE_3D)) { 1814c1f859d4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 1815c1f859d4Smrg return GL_TRUE; 18167117f1b4Smrg } 18177117f1b4Smrg } 18187117f1b4Smrg 18197117f1b4Smrg /* Check level */ 18207117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 18217117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18227117f1b4Smrg "glCopyTexSubImage%dD(level=%d)", dimensions, level); 18237117f1b4Smrg return GL_TRUE; 18247117f1b4Smrg } 18257117f1b4Smrg 18267117f1b4Smrg return GL_FALSE; 18277117f1b4Smrg} 18287117f1b4Smrg 1829c1f859d4Smrg 1830c1f859d4Smrg/** 1831c1f859d4Smrg * Second part of error checking for glCopyTexSubImage[12]D(). 1832c1f859d4Smrg * \param xoffset sub-image x offset given by the user. 1833c1f859d4Smrg * \param yoffset sub-image y offset given by the user. 1834c1f859d4Smrg * \param zoffset sub-image z offset given by the user. 1835c1f859d4Smrg * \param width image width given by the user. 1836c1f859d4Smrg * \param height image height given by the user. 1837c1f859d4Smrg */ 18387117f1b4Smrgstatic GLboolean 18397117f1b4Smrgcopytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 18407117f1b4Smrg GLenum target, GLint level, 18417117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 18427117f1b4Smrg GLsizei width, GLsizei height, 18437117f1b4Smrg const struct gl_texture_image *teximage ) 18447117f1b4Smrg{ 1845c1f859d4Smrg /* check that dest tex image exists */ 18467117f1b4Smrg if (!teximage) { 18477117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18487117f1b4Smrg "glCopyTexSubImage%dD(undefined texture level: %d)", 18497117f1b4Smrg dimensions, level); 18507117f1b4Smrg return GL_TRUE; 18517117f1b4Smrg } 18527117f1b4Smrg 1853c1f859d4Smrg /* Check size */ 1854c1f859d4Smrg if (width < 0) { 1855c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1856c1f859d4Smrg "glCopyTexSubImage%dD(width=%d)", dimensions, width); 1857c1f859d4Smrg return GL_TRUE; 1858c1f859d4Smrg } 1859c1f859d4Smrg if (dimensions > 1 && height < 0) { 1860c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1861c1f859d4Smrg "glCopyTexSubImage%dD(height=%d)", dimensions, height); 1862c1f859d4Smrg return GL_TRUE; 1863c1f859d4Smrg } 1864c1f859d4Smrg 1865c1f859d4Smrg /* check x/y offsets */ 18667117f1b4Smrg if (xoffset < -((GLint)teximage->Border)) { 18677117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18687117f1b4Smrg "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 18697117f1b4Smrg return GL_TRUE; 18707117f1b4Smrg } 18717117f1b4Smrg if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 18727117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18737117f1b4Smrg "glCopyTexSubImage%dD(xoffset+width)", dimensions); 18747117f1b4Smrg return GL_TRUE; 18757117f1b4Smrg } 18767117f1b4Smrg if (dimensions > 1) { 18777117f1b4Smrg if (yoffset < -((GLint)teximage->Border)) { 18787117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18797117f1b4Smrg "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 18807117f1b4Smrg return GL_TRUE; 18817117f1b4Smrg } 18827117f1b4Smrg /* NOTE: we're adding the border here, not subtracting! */ 18837117f1b4Smrg if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 18847117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18857117f1b4Smrg "glCopyTexSubImage%dD(yoffset+height)", dimensions); 18867117f1b4Smrg return GL_TRUE; 18877117f1b4Smrg } 18887117f1b4Smrg } 18897117f1b4Smrg 1890c1f859d4Smrg /* check z offset */ 18917117f1b4Smrg if (dimensions > 2) { 18927117f1b4Smrg if (zoffset < -((GLint)teximage->Border)) { 18937117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18947117f1b4Smrg "glCopyTexSubImage%dD(zoffset)", dimensions); 18957117f1b4Smrg return GL_TRUE; 18967117f1b4Smrg } 18977117f1b4Smrg if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 18987117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18997117f1b4Smrg "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 19007117f1b4Smrg return GL_TRUE; 19017117f1b4Smrg } 19027117f1b4Smrg } 19037117f1b4Smrg 19044a49301eSmrg if (_mesa_is_format_compressed(teximage->TexFormat)) { 1905c1f859d4Smrg if (!target_can_be_compressed(ctx, target)) { 19067117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 19077117f1b4Smrg "glCopyTexSubImage%d(target)", dimensions); 19087117f1b4Smrg return GL_TRUE; 19097117f1b4Smrg } 19107117f1b4Smrg /* offset must be multiple of 4 */ 19117117f1b4Smrg if ((xoffset & 3) || (yoffset & 3)) { 19127117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19137117f1b4Smrg "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 19147117f1b4Smrg return GL_TRUE; 19157117f1b4Smrg } 19167117f1b4Smrg /* size must be multiple of 4 */ 19177117f1b4Smrg if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 19187117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19197117f1b4Smrg "glCopyTexSubImage%D(width)", dimensions); 19207117f1b4Smrg return GL_TRUE; 19217117f1b4Smrg } 19227117f1b4Smrg if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 19237117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19247117f1b4Smrg "glCopyTexSubImage%D(height)", dimensions); 19257117f1b4Smrg return GL_TRUE; 19267117f1b4Smrg } 19277117f1b4Smrg } 19287117f1b4Smrg 19297117f1b4Smrg if (teximage->InternalFormat == GL_YCBCR_MESA) { 19307117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 19317117f1b4Smrg return GL_TRUE; 19327117f1b4Smrg } 19337117f1b4Smrg 19347117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 19357117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1936c1f859d4Smrg "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 1937c1f859d4Smrg dimensions, teximage->_BaseFormat); 19387117f1b4Smrg return GL_TRUE; 19397117f1b4Smrg } 19407117f1b4Smrg 19417117f1b4Smrg if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 19427117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 19437117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 19447117f1b4Smrg "glCopyTexSubImage%D(no depth buffer)", 19457117f1b4Smrg dimensions); 19467117f1b4Smrg return GL_TRUE; 19477117f1b4Smrg } 19487117f1b4Smrg } 19497117f1b4Smrg else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 19507117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 19517117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 19527117f1b4Smrg "glCopyTexSubImage%D(no depth/stencil buffer)", 19537117f1b4Smrg dimensions); 19547117f1b4Smrg return GL_TRUE; 19557117f1b4Smrg } 19567117f1b4Smrg } 19577117f1b4Smrg 19587117f1b4Smrg /* if we get here, the parameters are OK */ 19597117f1b4Smrg return GL_FALSE; 19607117f1b4Smrg} 19617117f1b4Smrg 19627117f1b4Smrg 19634a49301eSmrg/** Callback info for walking over FBO hash table */ 19644a49301eSmrgstruct cb_info 19657117f1b4Smrg{ 19664a49301eSmrg GLcontext *ctx; 19677117f1b4Smrg struct gl_texture_object *texObj; 19684a49301eSmrg GLuint level, face; 19694a49301eSmrg}; 19707117f1b4Smrg 19717117f1b4Smrg 19727117f1b4Smrg/** 19734a49301eSmrg * Check render to texture callback. Called from _mesa_HashWalk(). 19747117f1b4Smrg */ 19757117f1b4Smrgstatic void 19764a49301eSmrgcheck_rtt_cb(GLuint key, void *data, void *userData) 19777117f1b4Smrg{ 19784a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 19794a49301eSmrg const struct cb_info *info = (struct cb_info *) userData; 19804a49301eSmrg GLcontext *ctx = info->ctx; 19814a49301eSmrg const struct gl_texture_object *texObj = info->texObj; 19824a49301eSmrg const GLuint level = info->level, face = info->face; 19834a49301eSmrg 19844a49301eSmrg /* If this is a user-created FBO */ 19854a49301eSmrg if (fb->Name) { 19867117f1b4Smrg GLuint i; 19874a49301eSmrg /* check if any of the FBO's attachments point to 'texObj' */ 19887117f1b4Smrg for (i = 0; i < BUFFER_COUNT; i++) { 19894a49301eSmrg struct gl_renderbuffer_attachment *att = fb->Attachment + i; 19907117f1b4Smrg if (att->Type == GL_TEXTURE && 19917117f1b4Smrg att->Texture == texObj && 19927117f1b4Smrg att->TextureLevel == level && 19937117f1b4Smrg att->CubeMapFace == face) { 19947117f1b4Smrg ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 19957117f1b4Smrg /* Tell driver about the new renderbuffer texture */ 19967117f1b4Smrg ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 19974a49301eSmrg /* Mark fb status as indeterminate to force re-validation */ 19984a49301eSmrg fb->_Status = 0; 19997117f1b4Smrg } 20007117f1b4Smrg } 20017117f1b4Smrg } 20027117f1b4Smrg} 20037117f1b4Smrg 20047117f1b4Smrg 20054a49301eSmrg/** 20064a49301eSmrg * When a texture image is specified we have to check if it's bound to 20074a49301eSmrg * any framebuffer objects (render to texture) in order to detect changes 20084a49301eSmrg * in size or format since that effects FBO completeness. 20094a49301eSmrg * Any FBOs rendering into the texture must be re-validated. 20104a49301eSmrg */ 20114a49301eSmrgstatic void 20124a49301eSmrgupdate_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 20134a49301eSmrg GLuint face, GLuint level) 20144a49301eSmrg{ 20154a49301eSmrg /* Only check this texture if it's been marked as RenderToTexture */ 20164a49301eSmrg if (texObj->_RenderToTexture) { 20174a49301eSmrg struct cb_info info; 20184a49301eSmrg info.ctx = ctx; 20194a49301eSmrg info.texObj = texObj; 20204a49301eSmrg info.level = level; 20214a49301eSmrg info.face = face; 20224a49301eSmrg _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 20234a49301eSmrg } 20244a49301eSmrg} 20254a49301eSmrg 20264a49301eSmrg 20274a49301eSmrg/** 20284a49301eSmrg * If the texture object's GenerateMipmap flag is set and we've 20294a49301eSmrg * changed the texture base level image, regenerate the rest of the 20304a49301eSmrg * mipmap levels now. 20314a49301eSmrg */ 20324a49301eSmrgstatic INLINE void 20334a49301eSmrgcheck_gen_mipmap(GLcontext *ctx, GLenum target, 20344a49301eSmrg struct gl_texture_object *texObj, GLint level) 20354a49301eSmrg{ 20364a49301eSmrg ASSERT(target != GL_TEXTURE_CUBE_MAP); 20374a49301eSmrg if (texObj->GenerateMipmap && 20384a49301eSmrg level == texObj->BaseLevel && 20394a49301eSmrg level < texObj->MaxLevel) { 20404a49301eSmrg ASSERT(ctx->Driver.GenerateMipmap); 20414a49301eSmrg ctx->Driver.GenerateMipmap(ctx, target, texObj); 20424a49301eSmrg } 20434a49301eSmrg} 20444a49301eSmrg 20454a49301eSmrg 20464a49301eSmrg/** Debug helper: override the user-requested internal format */ 20474a49301eSmrgstatic GLenum 20484a49301eSmrgoverride_internal_format(GLenum internalFormat, GLint width, GLint height) 20494a49301eSmrg{ 20504a49301eSmrg#if 0 20514a49301eSmrg if (internalFormat == GL_RGBA16F_ARB || 20524a49301eSmrg internalFormat == GL_RGBA32F_ARB) { 20534a49301eSmrg printf("Convert rgba float tex to int %d x %d\n", width, height); 20544a49301eSmrg return GL_RGBA; 20554a49301eSmrg } 20564a49301eSmrg else if (internalFormat == GL_RGB16F_ARB || 20574a49301eSmrg internalFormat == GL_RGB32F_ARB) { 20584a49301eSmrg printf("Convert rgb float tex to int %d x %d\n", width, height); 20594a49301eSmrg return GL_RGB; 20604a49301eSmrg } 20614a49301eSmrg else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 20624a49301eSmrg internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 20634a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 20644a49301eSmrg return GL_LUMINANCE_ALPHA; 20654a49301eSmrg } 20664a49301eSmrg else if (internalFormat == GL_LUMINANCE16F_ARB || 20674a49301eSmrg internalFormat == GL_LUMINANCE32F_ARB) { 20684a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 20694a49301eSmrg return GL_LUMINANCE; 20704a49301eSmrg } 20714a49301eSmrg else if (internalFormat == GL_ALPHA16F_ARB || 20724a49301eSmrg internalFormat == GL_ALPHA32F_ARB) { 20734a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 20744a49301eSmrg return GL_ALPHA; 20754a49301eSmrg } 20764a49301eSmrg /* 20774a49301eSmrg else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 20784a49301eSmrg internalFormat = GL_RGBA; 20794a49301eSmrg } 20804a49301eSmrg */ 20814a49301eSmrg else { 20824a49301eSmrg return internalFormat; 20834a49301eSmrg } 20844a49301eSmrg#else 20854a49301eSmrg return internalFormat; 20864a49301eSmrg#endif 20874a49301eSmrg} 20884a49301eSmrg 20897117f1b4Smrg 20907117f1b4Smrg/* 20917117f1b4Smrg * Called from the API. Note that width includes the border. 20927117f1b4Smrg */ 20937117f1b4Smrgvoid GLAPIENTRY 20947117f1b4Smrg_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 20957117f1b4Smrg GLsizei width, GLint border, GLenum format, 20967117f1b4Smrg GLenum type, const GLvoid *pixels ) 20977117f1b4Smrg{ 20987117f1b4Smrg GLsizei postConvWidth = width; 20997117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 21007117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 21017117f1b4Smrg 21024a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 21034a49301eSmrg _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n", 21044a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 21054a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), width, border, 21064a49301eSmrg _mesa_lookup_enum_by_nr(format), 21074a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 21084a49301eSmrg 21094a49301eSmrg internalFormat = override_internal_format(internalFormat, width, 1); 21104a49301eSmrg 2111c1f859d4Smrg#if FEATURE_convolve 2112c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 21137117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 21147117f1b4Smrg } 2115c1f859d4Smrg#endif 21167117f1b4Smrg 21177117f1b4Smrg if (target == GL_TEXTURE_1D) { 21187117f1b4Smrg /* non-proxy target */ 21197117f1b4Smrg struct gl_texture_object *texObj; 21207117f1b4Smrg struct gl_texture_image *texImage; 2121c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 21227117f1b4Smrg 21237117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 21247117f1b4Smrg format, type, 1, postConvWidth, 1, 1, border)) { 21257117f1b4Smrg return; /* error was recorded */ 21267117f1b4Smrg } 21277117f1b4Smrg 21284a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 21297117f1b4Smrg _mesa_update_state(ctx); 21307117f1b4Smrg 21314a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 21327117f1b4Smrg _mesa_lock_texture(ctx, texObj); 21337117f1b4Smrg { 21347117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 21357117f1b4Smrg if (!texImage) { 21367117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 21377117f1b4Smrg } 21384a49301eSmrg else { 21394a49301eSmrg if (texImage->Data) { 21404a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 21414a49301eSmrg } 21424a49301eSmrg 21434a49301eSmrg ASSERT(texImage->Data == NULL); 21444a49301eSmrg 21454a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 21464a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 21474a49301eSmrg postConvWidth, 1, 1, 21484a49301eSmrg border, internalFormat); 21494a49301eSmrg 21504a49301eSmrg /* Choose actual texture format */ 21514a49301eSmrg texImage->TexFormat = 21524a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 21534a49301eSmrg format, type); 21544a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 21554a49301eSmrg 21564a49301eSmrg /* Give the texture to the driver. <pixels> may be null. */ 21574a49301eSmrg ASSERT(ctx->Driver.TexImage1D); 21584a49301eSmrg ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 21594a49301eSmrg width, border, format, type, pixels, 21604a49301eSmrg &ctx->Unpack, texObj, texImage); 21617117f1b4Smrg 21624a49301eSmrg ASSERT(texImage->TexFormat); 21634a49301eSmrg 21644a49301eSmrg _mesa_set_fetch_functions(texImage, 1); 21654a49301eSmrg 21664a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 21674a49301eSmrg 21684a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 21694a49301eSmrg 21704a49301eSmrg /* state update */ 21714a49301eSmrg texObj->_Complete = GL_FALSE; 21724a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 21734a49301eSmrg } 21744a49301eSmrg } 21757117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 21767117f1b4Smrg } 21777117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 21787117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 21797117f1b4Smrg struct gl_texture_image *texImage; 21807117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 21817117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 21827117f1b4Smrg format, type, 1, postConvWidth, 1, 1, border)) { 21837117f1b4Smrg /* when error, clear all proxy texture image parameters */ 21847117f1b4Smrg if (texImage) 21857117f1b4Smrg clear_teximage_fields(texImage); 21867117f1b4Smrg } 21877117f1b4Smrg else { 21887117f1b4Smrg /* no error, set the tex image parameters */ 21897117f1b4Smrg ASSERT(texImage); 21907117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 21917117f1b4Smrg postConvWidth, 1, 1, 21927117f1b4Smrg border, internalFormat); 21934a49301eSmrg texImage->TexFormat = 21944a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 21957117f1b4Smrg } 21967117f1b4Smrg } 21977117f1b4Smrg else { 21987117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 21997117f1b4Smrg return; 22007117f1b4Smrg } 22017117f1b4Smrg} 22027117f1b4Smrg 22037117f1b4Smrg 22047117f1b4Smrgvoid GLAPIENTRY 22057117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 22067117f1b4Smrg GLsizei width, GLsizei height, GLint border, 22077117f1b4Smrg GLenum format, GLenum type, 22087117f1b4Smrg const GLvoid *pixels ) 22097117f1b4Smrg{ 22107117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 22117117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 22127117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 22137117f1b4Smrg 22144a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 22154a49301eSmrg _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n", 22164a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 22174a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), width, height, 22184a49301eSmrg border, _mesa_lookup_enum_by_nr(format), 22194a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 22204a49301eSmrg 22214a49301eSmrg internalFormat = override_internal_format(internalFormat, width, height); 22224a49301eSmrg 2223c1f859d4Smrg#if FEATURE_convolve 2224c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 22257117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 22267117f1b4Smrg &postConvHeight); 22277117f1b4Smrg } 2228c1f859d4Smrg#endif 22297117f1b4Smrg 22307117f1b4Smrg if (target == GL_TEXTURE_2D || 22317117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 22327117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 22337117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 22347117f1b4Smrg (ctx->Extensions.NV_texture_rectangle && 2235c1f859d4Smrg target == GL_TEXTURE_RECTANGLE_NV) || 2236c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2237c1f859d4Smrg target == GL_TEXTURE_1D_ARRAY_EXT)) { 22387117f1b4Smrg /* non-proxy target */ 22397117f1b4Smrg struct gl_texture_object *texObj; 22407117f1b4Smrg struct gl_texture_image *texImage; 2241c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 22427117f1b4Smrg 22437117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 22447117f1b4Smrg format, type, 2, postConvWidth, postConvHeight, 22457117f1b4Smrg 1, border)) { 22467117f1b4Smrg return; /* error was recorded */ 22477117f1b4Smrg } 22487117f1b4Smrg 22494a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 22507117f1b4Smrg _mesa_update_state(ctx); 22517117f1b4Smrg 22524a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 22537117f1b4Smrg _mesa_lock_texture(ctx, texObj); 22547117f1b4Smrg { 22557117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 22567117f1b4Smrg if (!texImage) { 22577117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 22587117f1b4Smrg } 22594a49301eSmrg else { 22604a49301eSmrg if (texImage->Data) { 22614a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 22624a49301eSmrg } 22634a49301eSmrg 22644a49301eSmrg ASSERT(texImage->Data == NULL); 22654a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 22664a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 22674a49301eSmrg postConvWidth, postConvHeight, 1, 22684a49301eSmrg border, internalFormat); 22694a49301eSmrg 22704a49301eSmrg /* Choose actual texture format */ 22714a49301eSmrg texImage->TexFormat = 22724a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 22734a49301eSmrg format, type); 22744a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 22754a49301eSmrg 22764a49301eSmrg /* Give the texture to the driver. <pixels> may be null. */ 22774a49301eSmrg ASSERT(ctx->Driver.TexImage2D); 22784a49301eSmrg ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 22794a49301eSmrg width, height, border, format, type, 22804a49301eSmrg pixels, &ctx->Unpack, texObj, texImage); 22814a49301eSmrg 22824a49301eSmrg ASSERT(texImage->TexFormat); 22834a49301eSmrg 22844a49301eSmrg _mesa_set_fetch_functions(texImage, 2); 22854a49301eSmrg 22864a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 22874a49301eSmrg 22884a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 22894a49301eSmrg 22904a49301eSmrg /* state update */ 22914a49301eSmrg texObj->_Complete = GL_FALSE; 22924a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 22934a49301eSmrg } 22944a49301eSmrg } 22957117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 22967117f1b4Smrg } 22977117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 22987117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 22997117f1b4Smrg ctx->Extensions.ARB_texture_cube_map) || 23007117f1b4Smrg (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 2301c1f859d4Smrg ctx->Extensions.NV_texture_rectangle) || 2302c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2303c1f859d4Smrg target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { 23047117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 23057117f1b4Smrg struct gl_texture_image *texImage; 23067117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 23077117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 23087117f1b4Smrg format, type, 2, postConvWidth, postConvHeight, 23097117f1b4Smrg 1, border)) { 23107117f1b4Smrg /* when error, clear all proxy texture image parameters */ 23117117f1b4Smrg if (texImage) 2312c1f859d4Smrg clear_teximage_fields(texImage); 23137117f1b4Smrg } 23147117f1b4Smrg else { 23157117f1b4Smrg /* no error, set the tex image parameters */ 23167117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, 23177117f1b4Smrg postConvWidth, postConvHeight, 1, 23187117f1b4Smrg border, internalFormat); 23194a49301eSmrg texImage->TexFormat = 23204a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 23217117f1b4Smrg } 23227117f1b4Smrg } 23237117f1b4Smrg else { 23247117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 23257117f1b4Smrg return; 23267117f1b4Smrg } 23277117f1b4Smrg} 23287117f1b4Smrg 23297117f1b4Smrg 23307117f1b4Smrg/* 23317117f1b4Smrg * Called by the API or display list executor. 23327117f1b4Smrg * Note that width and height include the border. 23337117f1b4Smrg */ 23347117f1b4Smrgvoid GLAPIENTRY 23357117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 23367117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 23377117f1b4Smrg GLint border, GLenum format, GLenum type, 23387117f1b4Smrg const GLvoid *pixels ) 23397117f1b4Smrg{ 23407117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 23417117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 23427117f1b4Smrg 23434a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 23444a49301eSmrg _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n", 23454a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 23464a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), width, height, 23474a49301eSmrg depth, border, _mesa_lookup_enum_by_nr(format), 23484a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 23494a49301eSmrg 23504a49301eSmrg internalFormat = override_internal_format(internalFormat, width, height); 23514a49301eSmrg 2352c1f859d4Smrg if (target == GL_TEXTURE_3D || 2353c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2354c1f859d4Smrg target == GL_TEXTURE_2D_ARRAY_EXT)) { 23557117f1b4Smrg /* non-proxy target */ 23567117f1b4Smrg struct gl_texture_object *texObj; 23577117f1b4Smrg struct gl_texture_image *texImage; 2358c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 23597117f1b4Smrg 23607117f1b4Smrg if (texture_error_check(ctx, target, level, (GLint) internalFormat, 23617117f1b4Smrg format, type, 3, width, height, depth, border)) { 23627117f1b4Smrg return; /* error was recorded */ 23637117f1b4Smrg } 23647117f1b4Smrg 23654a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 23667117f1b4Smrg _mesa_update_state(ctx); 23677117f1b4Smrg 23684a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 23697117f1b4Smrg _mesa_lock_texture(ctx, texObj); 23707117f1b4Smrg { 23717117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 23727117f1b4Smrg if (!texImage) { 23737117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 23747117f1b4Smrg } 23754a49301eSmrg else { 23764a49301eSmrg if (texImage->Data) { 23774a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 23784a49301eSmrg } 23797117f1b4Smrg 23804a49301eSmrg ASSERT(texImage->Data == NULL); 23814a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 23824a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 23834a49301eSmrg width, height, depth, 23844a49301eSmrg border, internalFormat); 23857117f1b4Smrg 23864a49301eSmrg /* Choose actual texture format */ 23874a49301eSmrg texImage->TexFormat = 23884a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 23894a49301eSmrg format, type); 23904a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 23917117f1b4Smrg 23924a49301eSmrg /* Give the texture to the driver. <pixels> may be null. */ 23934a49301eSmrg ASSERT(ctx->Driver.TexImage3D); 23944a49301eSmrg ctx->Driver.TexImage3D(ctx, target, level, internalFormat, 23954a49301eSmrg width, height, depth, border, format, type, 23964a49301eSmrg pixels, &ctx->Unpack, texObj, texImage); 23977117f1b4Smrg 23984a49301eSmrg ASSERT(texImage->TexFormat); 23997117f1b4Smrg 24004a49301eSmrg _mesa_set_fetch_functions(texImage, 3); 24014a49301eSmrg 24024a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 24034a49301eSmrg 24044a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 24054a49301eSmrg 24064a49301eSmrg /* state update */ 24074a49301eSmrg texObj->_Complete = GL_FALSE; 24084a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 24094a49301eSmrg } 24107117f1b4Smrg } 24117117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 24127117f1b4Smrg } 2413c1f859d4Smrg else if (target == GL_PROXY_TEXTURE_3D || 2414c1f859d4Smrg (ctx->Extensions.MESA_texture_array && 2415c1f859d4Smrg target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { 24167117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 24177117f1b4Smrg struct gl_texture_image *texImage; 24187117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 24197117f1b4Smrg if (texture_error_check(ctx, target, level, internalFormat, 24207117f1b4Smrg format, type, 3, width, height, depth, border)) { 24217117f1b4Smrg /* when error, clear all proxy texture image parameters */ 24227117f1b4Smrg if (texImage) 24237117f1b4Smrg clear_teximage_fields(texImage); 24247117f1b4Smrg } 24257117f1b4Smrg else { 24267117f1b4Smrg /* no error, set the tex image parameters */ 24277117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 24287117f1b4Smrg depth, border, internalFormat); 24294a49301eSmrg texImage->TexFormat = 24304a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 24317117f1b4Smrg } 24327117f1b4Smrg } 24337117f1b4Smrg else { 24347117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 24357117f1b4Smrg return; 24367117f1b4Smrg } 24377117f1b4Smrg} 24387117f1b4Smrg 24397117f1b4Smrg 24407117f1b4Smrgvoid GLAPIENTRY 24417117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 24427117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 24437117f1b4Smrg GLint border, GLenum format, GLenum type, 24447117f1b4Smrg const GLvoid *pixels ) 24457117f1b4Smrg{ 24467117f1b4Smrg _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 24477117f1b4Smrg depth, border, format, type, pixels); 24487117f1b4Smrg} 24497117f1b4Smrg 24507117f1b4Smrg 24517117f1b4Smrg 24527117f1b4Smrgvoid GLAPIENTRY 24537117f1b4Smrg_mesa_TexSubImage1D( GLenum target, GLint level, 24547117f1b4Smrg GLint xoffset, GLsizei width, 24557117f1b4Smrg GLenum format, GLenum type, 24567117f1b4Smrg const GLvoid *pixels ) 24577117f1b4Smrg{ 24587117f1b4Smrg GLsizei postConvWidth = width; 24597117f1b4Smrg struct gl_texture_object *texObj; 24604a49301eSmrg struct gl_texture_image *texImage; 24617117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 24627117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 24637117f1b4Smrg 24644a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 24654a49301eSmrg _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n", 24664a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 24674a49301eSmrg xoffset, width, _mesa_lookup_enum_by_nr(format), 24684a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 24694a49301eSmrg 24704a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 24717117f1b4Smrg _mesa_update_state(ctx); 24727117f1b4Smrg 2473c1f859d4Smrg#if FEATURE_convolve 24747117f1b4Smrg /* XXX should test internal format */ 2475c1f859d4Smrg if (_mesa_is_color_format(format)) { 24767117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 24777117f1b4Smrg } 2478c1f859d4Smrg#endif 24797117f1b4Smrg 24807117f1b4Smrg if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 24817117f1b4Smrg postConvWidth, 1, 1, format, type)) { 24827117f1b4Smrg return; /* error was detected */ 24837117f1b4Smrg } 24847117f1b4Smrg 24857117f1b4Smrg 24864a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 24877117f1b4Smrg assert(texObj); 24887117f1b4Smrg 24897117f1b4Smrg _mesa_lock_texture(ctx, texObj); 24907117f1b4Smrg { 24917117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 24927117f1b4Smrg 24937117f1b4Smrg if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 24944a49301eSmrg postConvWidth, 1, 1, 24954a49301eSmrg format, type, texImage)) { 24964a49301eSmrg /* error was recorded */ 24977117f1b4Smrg } 24984a49301eSmrg else if (width > 0) { 24994a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 25004a49301eSmrg xoffset += texImage->Border; 25017117f1b4Smrg 25024a49301eSmrg ASSERT(ctx->Driver.TexSubImage1D); 25034a49301eSmrg ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width, 25044a49301eSmrg format, type, pixels, &ctx->Unpack, 25054a49301eSmrg texObj, texImage); 25067117f1b4Smrg 25074a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 25087117f1b4Smrg 25094a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 25104a49301eSmrg } 25117117f1b4Smrg } 25127117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 25137117f1b4Smrg} 25147117f1b4Smrg 25157117f1b4Smrg 25167117f1b4Smrgvoid GLAPIENTRY 25177117f1b4Smrg_mesa_TexSubImage2D( GLenum target, GLint level, 25187117f1b4Smrg GLint xoffset, GLint yoffset, 25197117f1b4Smrg GLsizei width, GLsizei height, 25207117f1b4Smrg GLenum format, GLenum type, 25217117f1b4Smrg const GLvoid *pixels ) 25227117f1b4Smrg{ 25237117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 25247117f1b4Smrg struct gl_texture_object *texObj; 25257117f1b4Smrg struct gl_texture_image *texImage; 25267117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25277117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 25287117f1b4Smrg 25294a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 25304a49301eSmrg _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n", 25314a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 25324a49301eSmrg xoffset, yoffset, width, height, 25334a49301eSmrg _mesa_lookup_enum_by_nr(format), 25344a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 25354a49301eSmrg 25364a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 25377117f1b4Smrg _mesa_update_state(ctx); 25387117f1b4Smrg 2539c1f859d4Smrg#if FEATURE_convolve 25407117f1b4Smrg /* XXX should test internal format */ 2541c1f859d4Smrg if (_mesa_is_color_format(format)) { 25427117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 25437117f1b4Smrg &postConvHeight); 25447117f1b4Smrg } 2545c1f859d4Smrg#endif 25467117f1b4Smrg 25477117f1b4Smrg if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 25487117f1b4Smrg postConvWidth, postConvHeight, 1, format, type)) { 25497117f1b4Smrg return; /* error was detected */ 25507117f1b4Smrg } 25517117f1b4Smrg 25524a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 25534a49301eSmrg 25547117f1b4Smrg _mesa_lock_texture(ctx, texObj); 25557117f1b4Smrg { 25567117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 25577117f1b4Smrg 25587117f1b4Smrg if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 25594a49301eSmrg postConvWidth, postConvHeight, 1, 25604a49301eSmrg format, type, texImage)) { 25614a49301eSmrg /* error was recorded */ 25627117f1b4Smrg } 25634a49301eSmrg else if (width > 0 && height >= 0) { 25644a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 25654a49301eSmrg xoffset += texImage->Border; 25664a49301eSmrg yoffset += texImage->Border; 25674a49301eSmrg 25684a49301eSmrg ASSERT(ctx->Driver.TexSubImage2D); 25694a49301eSmrg ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset, 25704a49301eSmrg width, height, format, type, pixels, 25714a49301eSmrg &ctx->Unpack, texObj, texImage); 25727117f1b4Smrg 25734a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 25747117f1b4Smrg 25754a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 25764a49301eSmrg } 25777117f1b4Smrg } 25787117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 25797117f1b4Smrg} 25807117f1b4Smrg 25817117f1b4Smrg 25827117f1b4Smrg 25837117f1b4Smrgvoid GLAPIENTRY 25847117f1b4Smrg_mesa_TexSubImage3D( GLenum target, GLint level, 25857117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 25867117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 25877117f1b4Smrg GLenum format, GLenum type, 25887117f1b4Smrg const GLvoid *pixels ) 25897117f1b4Smrg{ 25907117f1b4Smrg struct gl_texture_object *texObj; 25917117f1b4Smrg struct gl_texture_image *texImage; 25927117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25937117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 25947117f1b4Smrg 25954a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 25964a49301eSmrg _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n", 25974a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 25984a49301eSmrg xoffset, yoffset, zoffset, width, height, depth, 25994a49301eSmrg _mesa_lookup_enum_by_nr(format), 26004a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 26014a49301eSmrg 26024a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 26037117f1b4Smrg _mesa_update_state(ctx); 26047117f1b4Smrg 26057117f1b4Smrg if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 26067117f1b4Smrg width, height, depth, format, type)) { 26077117f1b4Smrg return; /* error was detected */ 26087117f1b4Smrg } 26097117f1b4Smrg 26104a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 26117117f1b4Smrg 26127117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26137117f1b4Smrg { 26147117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 26157117f1b4Smrg 26164a49301eSmrg if (subtexture_error_check2(ctx, 3, target, level, 26174a49301eSmrg xoffset, yoffset, zoffset, 26184a49301eSmrg width, height, depth, 26194a49301eSmrg format, type, texImage)) { 26204a49301eSmrg /* error was recorded */ 26217117f1b4Smrg } 26224a49301eSmrg else if (width > 0 && height > 0 && height > 0) { 26234a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 26244a49301eSmrg xoffset += texImage->Border; 26254a49301eSmrg yoffset += texImage->Border; 26264a49301eSmrg zoffset += texImage->Border; 26277117f1b4Smrg 26284a49301eSmrg ASSERT(ctx->Driver.TexSubImage3D); 26294a49301eSmrg ctx->Driver.TexSubImage3D(ctx, target, level, 26304a49301eSmrg xoffset, yoffset, zoffset, 26314a49301eSmrg width, height, depth, 26324a49301eSmrg format, type, pixels, 26334a49301eSmrg &ctx->Unpack, texObj, texImage ); 26347117f1b4Smrg 26354a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 26367117f1b4Smrg 26374a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 26384a49301eSmrg } 26397117f1b4Smrg } 26407117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 26417117f1b4Smrg} 26427117f1b4Smrg 26437117f1b4Smrg 26447117f1b4Smrg 26457117f1b4Smrgvoid GLAPIENTRY 26467117f1b4Smrg_mesa_CopyTexImage1D( GLenum target, GLint level, 26477117f1b4Smrg GLenum internalFormat, 26487117f1b4Smrg GLint x, GLint y, 26497117f1b4Smrg GLsizei width, GLint border ) 26507117f1b4Smrg{ 26517117f1b4Smrg struct gl_texture_object *texObj; 26527117f1b4Smrg struct gl_texture_image *texImage; 26537117f1b4Smrg GLsizei postConvWidth = width; 2654c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 26557117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 26567117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 26577117f1b4Smrg 26584a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 26594a49301eSmrg _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n", 26604a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 26614a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 26624a49301eSmrg x, y, width, border); 26634a49301eSmrg 2664c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 26657117f1b4Smrg _mesa_update_state(ctx); 26667117f1b4Smrg 2667c1f859d4Smrg#if FEATURE_convolve 2668c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 26697117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 26707117f1b4Smrg } 2671c1f859d4Smrg#endif 26727117f1b4Smrg 26737117f1b4Smrg if (copytexture_error_check(ctx, 1, target, level, internalFormat, 26747117f1b4Smrg postConvWidth, 1, border)) 26757117f1b4Smrg return; 26767117f1b4Smrg 26774a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 26784a49301eSmrg 26797117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26807117f1b4Smrg { 26817117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 26827117f1b4Smrg if (!texImage) { 26837117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 26847117f1b4Smrg } 26854a49301eSmrg else { 26864a49301eSmrg if (texImage->Data) { 26874a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 26884a49301eSmrg } 26897117f1b4Smrg 26904a49301eSmrg ASSERT(texImage->Data == NULL); 26914a49301eSmrg 26924a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 26934a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 26944a49301eSmrg border, internalFormat); 26957117f1b4Smrg 26964a49301eSmrg /* Choose actual texture format */ 26974a49301eSmrg texImage->TexFormat = 26984a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 26994a49301eSmrg GL_NONE, GL_NONE); 27004a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 27017117f1b4Smrg 27024a49301eSmrg ASSERT(ctx->Driver.CopyTexImage1D); 27034a49301eSmrg ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, 27044a49301eSmrg x, y, width, border); 27057117f1b4Smrg 27064a49301eSmrg ASSERT(texImage->TexFormat); 27077117f1b4Smrg 27084a49301eSmrg _mesa_set_fetch_functions(texImage, 1); 27097117f1b4Smrg 27104a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 27117117f1b4Smrg 27124a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 27134a49301eSmrg 27144a49301eSmrg /* state update */ 27154a49301eSmrg texObj->_Complete = GL_FALSE; 27164a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 27174a49301eSmrg } 27187117f1b4Smrg } 27197117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 27207117f1b4Smrg} 27217117f1b4Smrg 27227117f1b4Smrg 27237117f1b4Smrg 27247117f1b4Smrgvoid GLAPIENTRY 27257117f1b4Smrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 27267117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height, 27277117f1b4Smrg GLint border ) 27287117f1b4Smrg{ 27297117f1b4Smrg struct gl_texture_object *texObj; 27307117f1b4Smrg struct gl_texture_image *texImage; 27317117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 2732c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 27337117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27347117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 27357117f1b4Smrg 27364a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 27374a49301eSmrg _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n", 27384a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 27394a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 27404a49301eSmrg x, y, width, height, border); 27414a49301eSmrg 2742c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 27437117f1b4Smrg _mesa_update_state(ctx); 27447117f1b4Smrg 2745c1f859d4Smrg#if FEATURE_convolve 2746c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 27477117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 27487117f1b4Smrg &postConvHeight); 27497117f1b4Smrg } 2750c1f859d4Smrg#endif 27517117f1b4Smrg 27527117f1b4Smrg if (copytexture_error_check(ctx, 2, target, level, internalFormat, 27537117f1b4Smrg postConvWidth, postConvHeight, border)) 27547117f1b4Smrg return; 27557117f1b4Smrg 27564a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 27577117f1b4Smrg 27587117f1b4Smrg _mesa_lock_texture(ctx, texObj); 27597117f1b4Smrg { 27607117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 27617117f1b4Smrg 27627117f1b4Smrg if (!texImage) { 27637117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 27647117f1b4Smrg } 27654a49301eSmrg else { 27664a49301eSmrg if (texImage->Data) { 27674a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 27684a49301eSmrg } 27694a49301eSmrg 27704a49301eSmrg ASSERT(texImage->Data == NULL); 27714a49301eSmrg 27724a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 27734a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 27744a49301eSmrg postConvWidth, postConvHeight, 1, 27754a49301eSmrg border, internalFormat); 27764a49301eSmrg 27774a49301eSmrg /* Choose actual texture format */ 27784a49301eSmrg texImage->TexFormat = 27794a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 27804a49301eSmrg GL_NONE, GL_NONE); 27814a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 27827117f1b4Smrg 27834a49301eSmrg ASSERT(ctx->Driver.CopyTexImage2D); 27844a49301eSmrg ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, 27854a49301eSmrg x, y, width, height, border); 27867117f1b4Smrg 27874a49301eSmrg ASSERT(texImage->TexFormat); 27887117f1b4Smrg 27894a49301eSmrg _mesa_set_fetch_functions(texImage, 2); 27904a49301eSmrg 27914a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 27924a49301eSmrg 27934a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 27944a49301eSmrg 27954a49301eSmrg /* state update */ 27964a49301eSmrg texObj->_Complete = GL_FALSE; 27974a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 27984a49301eSmrg } 27997117f1b4Smrg } 28007117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28017117f1b4Smrg} 28027117f1b4Smrg 28037117f1b4Smrg 28047117f1b4Smrgvoid GLAPIENTRY 28057117f1b4Smrg_mesa_CopyTexSubImage1D( GLenum target, GLint level, 28067117f1b4Smrg GLint xoffset, GLint x, GLint y, GLsizei width ) 28077117f1b4Smrg{ 28087117f1b4Smrg struct gl_texture_object *texObj; 28097117f1b4Smrg struct gl_texture_image *texImage; 28107117f1b4Smrg GLsizei postConvWidth = width; 2811c1f859d4Smrg GLint yoffset = 0; 2812c1f859d4Smrg GLsizei height = 1; 2813c1f859d4Smrg 28147117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28157117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28167117f1b4Smrg 28174a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 28184a49301eSmrg _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n", 28194a49301eSmrg _mesa_lookup_enum_by_nr(target), 28204a49301eSmrg level, xoffset, x, y, width); 28214a49301eSmrg 2822c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 28237117f1b4Smrg _mesa_update_state(ctx); 28247117f1b4Smrg 2825c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 1, target, level)) 28267117f1b4Smrg return; 28277117f1b4Smrg 28284a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 28297117f1b4Smrg 28307117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28317117f1b4Smrg { 28327117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 28337117f1b4Smrg 2834c1f859d4Smrg#if FEATURE_convolve 2835c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2836c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2837c1f859d4Smrg } 2838c1f859d4Smrg#endif 2839c1f859d4Smrg 28407117f1b4Smrg if (copytexsubimage_error_check2(ctx, 1, target, level, 28417117f1b4Smrg xoffset, 0, 0, postConvWidth, 1, 28424a49301eSmrg texImage)) { 28434a49301eSmrg /* error was recorded */ 28444a49301eSmrg } 28454a49301eSmrg else { 28464a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 28474a49301eSmrg xoffset += texImage->Border; 28487117f1b4Smrg 28494a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 28504a49301eSmrg &width, &height)) { 28514a49301eSmrg ASSERT(ctx->Driver.CopyTexSubImage1D); 28524a49301eSmrg ctx->Driver.CopyTexSubImage1D(ctx, target, level, 28534a49301eSmrg xoffset, x, y, width); 28547117f1b4Smrg 28554a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 2856c1f859d4Smrg 28574a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 28584a49301eSmrg } 28594a49301eSmrg } 28607117f1b4Smrg } 28617117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28627117f1b4Smrg} 28637117f1b4Smrg 28647117f1b4Smrg 28657117f1b4Smrg 28667117f1b4Smrgvoid GLAPIENTRY 28677117f1b4Smrg_mesa_CopyTexSubImage2D( GLenum target, GLint level, 28687117f1b4Smrg GLint xoffset, GLint yoffset, 28697117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 28707117f1b4Smrg{ 28717117f1b4Smrg struct gl_texture_object *texObj; 28727117f1b4Smrg struct gl_texture_image *texImage; 28737117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 28747117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28757117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28767117f1b4Smrg 28774a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 28784a49301eSmrg _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n", 28794a49301eSmrg _mesa_lookup_enum_by_nr(target), 28804a49301eSmrg level, xoffset, yoffset, x, y, width, height); 28814a49301eSmrg 2882c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 28837117f1b4Smrg _mesa_update_state(ctx); 28847117f1b4Smrg 2885c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 2, target, level)) 28867117f1b4Smrg return; 28877117f1b4Smrg 28884a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 28897117f1b4Smrg 28907117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28917117f1b4Smrg { 28927117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 28937117f1b4Smrg 2894c1f859d4Smrg#if FEATURE_convolve 2895c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2896c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 2, 2897c1f859d4Smrg &postConvWidth, &postConvHeight); 2898c1f859d4Smrg } 2899c1f859d4Smrg#endif 2900c1f859d4Smrg 29014a49301eSmrg if (copytexsubimage_error_check2(ctx, 2, target, level, 29024a49301eSmrg xoffset, yoffset, 0, 29034a49301eSmrg postConvWidth, postConvHeight, 29044a49301eSmrg texImage)) { 29054a49301eSmrg /* error was recorded */ 29064a49301eSmrg } 29074a49301eSmrg else { 29084a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 29094a49301eSmrg xoffset += texImage->Border; 29104a49301eSmrg yoffset += texImage->Border; 29114a49301eSmrg 29124a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 29134a49301eSmrg &width, &height)) { 29144a49301eSmrg ASSERT(ctx->Driver.CopyTexSubImage2D); 29154a49301eSmrg ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, 29164a49301eSmrg x, y, width, height); 29177117f1b4Smrg 29184a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 2919c1f859d4Smrg 29204a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 29214a49301eSmrg } 2922c1f859d4Smrg } 29237117f1b4Smrg } 29247117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29257117f1b4Smrg} 29267117f1b4Smrg 29277117f1b4Smrg 29287117f1b4Smrg 29297117f1b4Smrgvoid GLAPIENTRY 29307117f1b4Smrg_mesa_CopyTexSubImage3D( GLenum target, GLint level, 29317117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 29327117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 29337117f1b4Smrg{ 29347117f1b4Smrg struct gl_texture_object *texObj; 29357117f1b4Smrg struct gl_texture_image *texImage; 29367117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 29377117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29387117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29397117f1b4Smrg 29404a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 29414a49301eSmrg _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n", 29424a49301eSmrg _mesa_lookup_enum_by_nr(target), 29434a49301eSmrg level, xoffset, yoffset, zoffset, x, y, width, height); 29444a49301eSmrg 2945c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 29467117f1b4Smrg _mesa_update_state(ctx); 29477117f1b4Smrg 2948c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 3, target, level)) 29497117f1b4Smrg return; 29507117f1b4Smrg 29514a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 29527117f1b4Smrg 29537117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29547117f1b4Smrg { 29557117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 29567117f1b4Smrg 2957c1f859d4Smrg#if FEATURE_convolve 2958c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2959c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 2, 2960c1f859d4Smrg &postConvWidth, &postConvHeight); 2961c1f859d4Smrg } 2962c1f859d4Smrg#endif 2963c1f859d4Smrg 29647117f1b4Smrg if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 29657117f1b4Smrg zoffset, postConvWidth, postConvHeight, 29664a49301eSmrg texImage)) { 29674a49301eSmrg /* error was recored */ 2968c1f859d4Smrg } 29694a49301eSmrg else { 29704a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 29714a49301eSmrg xoffset += texImage->Border; 29724a49301eSmrg yoffset += texImage->Border; 29734a49301eSmrg zoffset += texImage->Border; 29744a49301eSmrg 29754a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 29764a49301eSmrg &width, &height)) { 29774a49301eSmrg ASSERT(ctx->Driver.CopyTexSubImage3D); 29784a49301eSmrg ctx->Driver.CopyTexSubImage3D(ctx, target, level, 29794a49301eSmrg xoffset, yoffset, zoffset, 29804a49301eSmrg x, y, width, height); 2981c1f859d4Smrg 29824a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 29834a49301eSmrg 29844a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 29854a49301eSmrg } 29864a49301eSmrg } 29877117f1b4Smrg } 29887117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29897117f1b4Smrg} 29907117f1b4Smrg 29917117f1b4Smrg 29927117f1b4Smrg 29937117f1b4Smrg 29947117f1b4Smrg/**********************************************************************/ 29957117f1b4Smrg/****** Compressed Textures ******/ 29967117f1b4Smrg/**********************************************************************/ 29977117f1b4Smrg 29987117f1b4Smrg 29994a49301eSmrg/** 30004a49301eSmrg * Return expected size of a compressed texture. 30014a49301eSmrg */ 30024a49301eSmrgstatic GLuint 30034a49301eSmrgcompressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, 30044a49301eSmrg GLenum glformat) 30054a49301eSmrg{ 30064a49301eSmrg gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 30074a49301eSmrg return _mesa_format_image_size(mesaFormat, width, height, depth); 30084a49301eSmrg} 30094a49301eSmrg 30104a49301eSmrg 30114a49301eSmrg/* 30124a49301eSmrg * Return compressed texture block size, in pixels. 30134a49301eSmrg */ 30144a49301eSmrgstatic void 30154a49301eSmrgget_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) 30164a49301eSmrg{ 30174a49301eSmrg gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 30184a49301eSmrg _mesa_get_format_block_size(mesaFormat, bw, bh); 30194a49301eSmrg} 30204a49301eSmrg 30214a49301eSmrg 30227117f1b4Smrg/** 30237117f1b4Smrg * Error checking for glCompressedTexImage[123]D(). 30247117f1b4Smrg * \return error code or GL_NO_ERROR. 30257117f1b4Smrg */ 30267117f1b4Smrgstatic GLenum 30277117f1b4Smrgcompressed_texture_error_check(GLcontext *ctx, GLint dimensions, 30287117f1b4Smrg GLenum target, GLint level, 30297117f1b4Smrg GLenum internalFormat, GLsizei width, 30307117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 30317117f1b4Smrg GLsizei imageSize) 30327117f1b4Smrg{ 30337117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 30347117f1b4Smrg 30357117f1b4Smrg if (dimensions == 1) { 30367117f1b4Smrg /* 1D compressed textures not allowed */ 30377117f1b4Smrg return GL_INVALID_ENUM; 30387117f1b4Smrg } 30397117f1b4Smrg else if (dimensions == 2) { 30407117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 30417117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 30427117f1b4Smrg } 30437117f1b4Smrg else if (target == GL_TEXTURE_2D) { 30447117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 30457117f1b4Smrg } 30467117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 30477117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 30487117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30497117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 30507117f1b4Smrg } 30517117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 30527117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 30537117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 30547117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30557117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 30567117f1b4Smrg } 30577117f1b4Smrg else { 30587117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30597117f1b4Smrg } 30607117f1b4Smrg } 30617117f1b4Smrg else if (dimensions == 3) { 30627117f1b4Smrg /* 3D compressed textures not allowed */ 30637117f1b4Smrg return GL_INVALID_ENUM; 30647117f1b4Smrg } 30657117f1b4Smrg 30667117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 30677117f1b4Smrg 30687117f1b4Smrg /* This will detect any invalid internalFormat value */ 30697117f1b4Smrg if (!is_compressed_format(ctx, internalFormat)) 30707117f1b4Smrg return GL_INVALID_ENUM; 30717117f1b4Smrg 30727117f1b4Smrg /* This should really never fail */ 30737117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) 30747117f1b4Smrg return GL_INVALID_ENUM; 30757117f1b4Smrg 30767117f1b4Smrg if (border != 0) 30777117f1b4Smrg return GL_INVALID_VALUE; 30787117f1b4Smrg 30797117f1b4Smrg /* 30807117f1b4Smrg * XXX We should probably use the proxy texture error check function here. 30817117f1b4Smrg */ 30827117f1b4Smrg if (width < 1 || width > maxTextureSize || 3083c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) 30847117f1b4Smrg return GL_INVALID_VALUE; 30857117f1b4Smrg 30867117f1b4Smrg if ((height < 1 || height > maxTextureSize || 3087c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) 30887117f1b4Smrg && dimensions > 1) 30897117f1b4Smrg return GL_INVALID_VALUE; 30907117f1b4Smrg 30917117f1b4Smrg if ((depth < 1 || depth > maxTextureSize || 3092c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) 30937117f1b4Smrg && dimensions > 2) 30947117f1b4Smrg return GL_INVALID_VALUE; 30957117f1b4Smrg 30967117f1b4Smrg /* For cube map, width must equal height */ 30977117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 30987117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 30997117f1b4Smrg return GL_INVALID_VALUE; 31007117f1b4Smrg 31017117f1b4Smrg if (level < 0 || level >= maxLevels) 31027117f1b4Smrg return GL_INVALID_VALUE; 31037117f1b4Smrg 31044a49301eSmrg expectedSize = compressed_tex_size(width, height, depth, internalFormat); 31057117f1b4Smrg if (expectedSize != imageSize) 31067117f1b4Smrg return GL_INVALID_VALUE; 31077117f1b4Smrg 31087117f1b4Smrg#if FEATURE_EXT_texture_sRGB 31097117f1b4Smrg if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 31107117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 31117117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 31127117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 31137117f1b4Smrg && border != 0) { 31147117f1b4Smrg return GL_INVALID_OPERATION; 31157117f1b4Smrg } 31167117f1b4Smrg#endif 31177117f1b4Smrg 31187117f1b4Smrg return GL_NO_ERROR; 31197117f1b4Smrg} 31207117f1b4Smrg 31217117f1b4Smrg 31227117f1b4Smrg/** 31237117f1b4Smrg * Error checking for glCompressedTexSubImage[123]D(). 31247117f1b4Smrg * \warning There are some bad assumptions here about the size of compressed 31257117f1b4Smrg * texture tiles (multiple of 4) used to test the validity of the 31267117f1b4Smrg * offset and size parameters. 31277117f1b4Smrg * \return error code or GL_NO_ERROR. 31287117f1b4Smrg */ 31297117f1b4Smrgstatic GLenum 31307117f1b4Smrgcompressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 31317117f1b4Smrg GLenum target, GLint level, 31327117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 31337117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 31347117f1b4Smrg GLenum format, GLsizei imageSize) 31357117f1b4Smrg{ 31367117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 31374a49301eSmrg GLuint bw, bh; 31387117f1b4Smrg (void) zoffset; 31397117f1b4Smrg 31407117f1b4Smrg if (dimensions == 1) { 31417117f1b4Smrg /* 1D compressed textures not allowed */ 31427117f1b4Smrg return GL_INVALID_ENUM; 31437117f1b4Smrg } 31447117f1b4Smrg else if (dimensions == 2) { 31457117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 31467117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 31477117f1b4Smrg } 31487117f1b4Smrg else if (target == GL_TEXTURE_2D) { 31497117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 31507117f1b4Smrg } 31517117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 31527117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 31537117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31547117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 31557117f1b4Smrg } 31567117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 31577117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 31587117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 31597117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31607117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 31617117f1b4Smrg } 31627117f1b4Smrg else { 31637117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31647117f1b4Smrg } 31657117f1b4Smrg } 31667117f1b4Smrg else if (dimensions == 3) { 31677117f1b4Smrg /* 3D compressed textures not allowed */ 31687117f1b4Smrg return GL_INVALID_ENUM; 31697117f1b4Smrg } 31707117f1b4Smrg 31717117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 31727117f1b4Smrg 31737117f1b4Smrg /* this will catch any invalid compressed format token */ 31747117f1b4Smrg if (!is_compressed_format(ctx, format)) 31757117f1b4Smrg return GL_INVALID_ENUM; 31767117f1b4Smrg 31777117f1b4Smrg if (width < 1 || width > maxTextureSize) 31787117f1b4Smrg return GL_INVALID_VALUE; 31797117f1b4Smrg 31807117f1b4Smrg if ((height < 1 || height > maxTextureSize) 31817117f1b4Smrg && dimensions > 1) 31827117f1b4Smrg return GL_INVALID_VALUE; 31837117f1b4Smrg 31847117f1b4Smrg if (level < 0 || level >= maxLevels) 31857117f1b4Smrg return GL_INVALID_VALUE; 31867117f1b4Smrg 31874a49301eSmrg /* 31884a49301eSmrg * do checks which depend on compression block size 31897117f1b4Smrg */ 31904a49301eSmrg get_compressed_block_size(format, &bw, &bh); 31914a49301eSmrg 31924a49301eSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0)) 31937117f1b4Smrg return GL_INVALID_VALUE; 31947117f1b4Smrg 31954a49301eSmrg if ((width % bw != 0) && width != 2 && width != 1) 31967117f1b4Smrg return GL_INVALID_VALUE; 31977117f1b4Smrg 31984a49301eSmrg if ((height % bh != 0) && height != 2 && height != 1) 31997117f1b4Smrg return GL_INVALID_VALUE; 32007117f1b4Smrg 32014a49301eSmrg expectedSize = compressed_tex_size(width, height, depth, format); 32027117f1b4Smrg if (expectedSize != imageSize) 32037117f1b4Smrg return GL_INVALID_VALUE; 32047117f1b4Smrg 32057117f1b4Smrg return GL_NO_ERROR; 32067117f1b4Smrg} 32077117f1b4Smrg 32087117f1b4Smrg 32094a49301eSmrg/** 32104a49301eSmrg * Do second part of glCompressedTexSubImage error checking. 32114a49301eSmrg * \return GL_TRUE if error found, GL_FALSE otherwise. 32124a49301eSmrg */ 32134a49301eSmrgstatic GLboolean 32144a49301eSmrgcompressed_subtexture_error_check2(GLcontext *ctx, GLuint dims, 32154a49301eSmrg GLsizei width, GLsizei height, 32164a49301eSmrg GLsizei depth, GLenum format, 32174a49301eSmrg struct gl_texture_image *texImage) 32184a49301eSmrg{ 32194a49301eSmrg 32204a49301eSmrg if ((GLint) format != texImage->InternalFormat) { 32214a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 32224a49301eSmrg "glCompressedTexSubImage%uD(format=0x%x)", dims, format); 32234a49301eSmrg return GL_TRUE; 32244a49301eSmrg } 32254a49301eSmrg 32264a49301eSmrg if (((width == 1 || width == 2) && 32274a49301eSmrg (GLuint) width != texImage->Width) || 32284a49301eSmrg (width > texImage->Width)) { 32294a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32304a49301eSmrg "glCompressedTexSubImage%uD(width=%d)", dims, width); 32314a49301eSmrg return GL_TRUE; 32324a49301eSmrg } 32334a49301eSmrg 32344a49301eSmrg if (dims >= 2) { 32354a49301eSmrg if (((height == 1 || height == 2) && 32364a49301eSmrg (GLuint) height != texImage->Height) || 32374a49301eSmrg (height > texImage->Height)) { 32384a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32394a49301eSmrg "glCompressedTexSubImage%uD(height=%d)", dims, height); 32404a49301eSmrg return GL_TRUE; 32414a49301eSmrg } 32424a49301eSmrg } 32434a49301eSmrg 32444a49301eSmrg if (dims >= 3) { 32454a49301eSmrg if (((depth == 1 || depth == 2) && 32464a49301eSmrg (GLuint) depth != texImage->Depth) || 32474a49301eSmrg (depth > texImage->Depth)) { 32484a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32494a49301eSmrg "glCompressedTexSubImage%uD(depth=%d)", dims, depth); 32504a49301eSmrg return GL_TRUE; 32514a49301eSmrg } 32524a49301eSmrg } 32534a49301eSmrg 32544a49301eSmrg return GL_FALSE; 32554a49301eSmrg} 32564a49301eSmrg 32574a49301eSmrg 32587117f1b4Smrg 32597117f1b4Smrgvoid GLAPIENTRY 32607117f1b4Smrg_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 32617117f1b4Smrg GLenum internalFormat, GLsizei width, 32627117f1b4Smrg GLint border, GLsizei imageSize, 32637117f1b4Smrg const GLvoid *data) 32647117f1b4Smrg{ 32657117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 32667117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 32677117f1b4Smrg 32684a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 32694a49301eSmrg _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n", 32704a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 32714a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 32724a49301eSmrg width, border, imageSize, data); 32734a49301eSmrg 32747117f1b4Smrg if (target == GL_TEXTURE_1D) { 32757117f1b4Smrg /* non-proxy target */ 32767117f1b4Smrg struct gl_texture_object *texObj; 32777117f1b4Smrg struct gl_texture_image *texImage; 32787117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 32797117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 32807117f1b4Smrg if (error) { 32817117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage1D"); 32827117f1b4Smrg return; 32837117f1b4Smrg } 32847117f1b4Smrg 32854a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 32867117f1b4Smrg 32877117f1b4Smrg _mesa_lock_texture(ctx, texObj); 32887117f1b4Smrg { 32897117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 32907117f1b4Smrg if (!texImage) { 32917117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 32927117f1b4Smrg } 32934a49301eSmrg else { 32944a49301eSmrg if (texImage->Data) { 32954a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 32964a49301eSmrg } 32974a49301eSmrg ASSERT(texImage->Data == NULL); 32984a49301eSmrg 32994a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 33004a49301eSmrg border, internalFormat); 33014a49301eSmrg 33024a49301eSmrg /* Choose actual texture format */ 33034a49301eSmrg texImage->TexFormat = 33044a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 33054a49301eSmrg GL_NONE, GL_NONE); 33064a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 33074a49301eSmrg 33084a49301eSmrg ASSERT(ctx->Driver.CompressedTexImage1D); 33094a49301eSmrg ctx->Driver.CompressedTexImage1D(ctx, target, level, 33104a49301eSmrg internalFormat, width, border, 33114a49301eSmrg imageSize, data, 33124a49301eSmrg texObj, texImage); 33137117f1b4Smrg 33144a49301eSmrg _mesa_set_fetch_functions(texImage, 1); 33157117f1b4Smrg 33164a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 33177117f1b4Smrg 33184a49301eSmrg /* state update */ 33194a49301eSmrg texObj->_Complete = GL_FALSE; 33204a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 33214a49301eSmrg } 33227117f1b4Smrg } 33237117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33247117f1b4Smrg } 33257117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 33267117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 33277117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 33287117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 33297117f1b4Smrg if (!error) { 33307117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 33317117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 33327117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 33337117f1b4Smrg width, 1, 1, border); 33347117f1b4Smrg } 33357117f1b4Smrg if (error) { 33367117f1b4Smrg /* if error, clear all proxy texture image parameters */ 33377117f1b4Smrg struct gl_texture_image *texImage; 33387117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 33397117f1b4Smrg if (texImage) 33407117f1b4Smrg clear_teximage_fields(texImage); 33417117f1b4Smrg } 33427117f1b4Smrg else { 33437117f1b4Smrg /* store the teximage parameters */ 33447117f1b4Smrg struct gl_texture_object *texObj; 33457117f1b4Smrg struct gl_texture_image *texImage; 33464a49301eSmrg 33474a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 33487117f1b4Smrg 33497117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33507117f1b4Smrg { 33517117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 33527117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 33537117f1b4Smrg border, internalFormat); 33547117f1b4Smrg } 33557117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33567117f1b4Smrg } 33577117f1b4Smrg } 33587117f1b4Smrg else { 33597117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 33607117f1b4Smrg return; 33617117f1b4Smrg } 33627117f1b4Smrg} 33637117f1b4Smrg 33647117f1b4Smrg 33657117f1b4Smrgvoid GLAPIENTRY 33667117f1b4Smrg_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 33677117f1b4Smrg GLenum internalFormat, GLsizei width, 33687117f1b4Smrg GLsizei height, GLint border, GLsizei imageSize, 33697117f1b4Smrg const GLvoid *data) 33707117f1b4Smrg{ 33717117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 33727117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 33737117f1b4Smrg 33744a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 33754a49301eSmrg _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n", 33764a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 33774a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 33784a49301eSmrg width, height, border, imageSize, data); 33794a49301eSmrg 33807117f1b4Smrg if (target == GL_TEXTURE_2D || 33817117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 33827117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 33837117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 33847117f1b4Smrg /* non-proxy target */ 33857117f1b4Smrg struct gl_texture_object *texObj; 33867117f1b4Smrg struct gl_texture_image *texImage; 33874a49301eSmrg 33887117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 33897117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 33907117f1b4Smrg if (error) { 33917117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage2D"); 33927117f1b4Smrg return; 33937117f1b4Smrg } 33947117f1b4Smrg 33954a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 33967117f1b4Smrg 33977117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33987117f1b4Smrg { 33997117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 34007117f1b4Smrg if (!texImage) { 34017117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 34027117f1b4Smrg } 34034a49301eSmrg else { 34044a49301eSmrg if (texImage->Data) { 34054a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 34064a49301eSmrg } 34074a49301eSmrg ASSERT(texImage->Data == NULL); 34084a49301eSmrg 34094a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 34104a49301eSmrg border, internalFormat); 34114a49301eSmrg 34124a49301eSmrg /* Choose actual texture format */ 34134a49301eSmrg texImage->TexFormat = 34144a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 34154a49301eSmrg GL_NONE, GL_NONE); 34164a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 34174a49301eSmrg 34184a49301eSmrg ASSERT(ctx->Driver.CompressedTexImage2D); 34194a49301eSmrg ctx->Driver.CompressedTexImage2D(ctx, target, level, 34204a49301eSmrg internalFormat, width, height, 34214a49301eSmrg border, imageSize, data, 34224a49301eSmrg texObj, texImage); 34234a49301eSmrg 34244a49301eSmrg _mesa_set_fetch_functions(texImage, 2); 34254a49301eSmrg 34264a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 34274a49301eSmrg 34284a49301eSmrg /* state update */ 34294a49301eSmrg texObj->_Complete = GL_FALSE; 34304a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 34314a49301eSmrg } 34324a49301eSmrg } 34337117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34347117f1b4Smrg } 34357117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 34367117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 34377117f1b4Smrg ctx->Extensions.ARB_texture_cube_map)) { 34387117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 34397117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 34407117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 34417117f1b4Smrg if (!error) { 34427117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 34437117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 34447117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 34457117f1b4Smrg width, height, 1, border); 34467117f1b4Smrg } 34477117f1b4Smrg if (error) { 34487117f1b4Smrg /* if error, clear all proxy texture image parameters */ 34497117f1b4Smrg struct gl_texture_image *texImage; 34507117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 34517117f1b4Smrg if (texImage) 34527117f1b4Smrg clear_teximage_fields(texImage); 34537117f1b4Smrg } 34547117f1b4Smrg else { 34557117f1b4Smrg /* store the teximage parameters */ 34567117f1b4Smrg struct gl_texture_object *texObj; 34577117f1b4Smrg struct gl_texture_image *texImage; 34584a49301eSmrg 34594a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 34607117f1b4Smrg 34617117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34627117f1b4Smrg { 34637117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 34647117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 34657117f1b4Smrg border, internalFormat); 34667117f1b4Smrg } 34677117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34687117f1b4Smrg } 34697117f1b4Smrg } 34707117f1b4Smrg else { 34717117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 34727117f1b4Smrg return; 34737117f1b4Smrg } 34747117f1b4Smrg} 34757117f1b4Smrg 34767117f1b4Smrg 34777117f1b4Smrgvoid GLAPIENTRY 34787117f1b4Smrg_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 34797117f1b4Smrg GLenum internalFormat, GLsizei width, 34807117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 34817117f1b4Smrg GLsizei imageSize, const GLvoid *data) 34827117f1b4Smrg{ 34837117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 34847117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 34857117f1b4Smrg 34864a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 34874a49301eSmrg _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n", 34884a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 34894a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 34904a49301eSmrg width, height, depth, border, imageSize, data); 34914a49301eSmrg 34927117f1b4Smrg if (target == GL_TEXTURE_3D) { 34937117f1b4Smrg /* non-proxy target */ 34947117f1b4Smrg struct gl_texture_object *texObj; 34957117f1b4Smrg struct gl_texture_image *texImage; 34967117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 34977117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 34987117f1b4Smrg if (error) { 34997117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage3D"); 35007117f1b4Smrg return; 35017117f1b4Smrg } 35027117f1b4Smrg 35034a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 35044a49301eSmrg 35057117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35067117f1b4Smrg { 35077117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 35087117f1b4Smrg if (!texImage) { 35097117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 35107117f1b4Smrg } 35114a49301eSmrg else { 35124a49301eSmrg if (texImage->Data) { 35134a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 35144a49301eSmrg } 35154a49301eSmrg ASSERT(texImage->Data == NULL); 35164a49301eSmrg 35174a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 35184a49301eSmrg width, height, depth, 35194a49301eSmrg border, internalFormat); 35204a49301eSmrg 35214a49301eSmrg /* Choose actual texture format */ 35224a49301eSmrg texImage->TexFormat = 35234a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 35244a49301eSmrg GL_NONE, GL_NONE); 35254a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 35264a49301eSmrg 35274a49301eSmrg ASSERT(ctx->Driver.CompressedTexImage3D); 35284a49301eSmrg ctx->Driver.CompressedTexImage3D(ctx, target, level, 35294a49301eSmrg internalFormat, 35304a49301eSmrg width, height, depth, 35314a49301eSmrg border, imageSize, data, 35324a49301eSmrg texObj, texImage); 35334a49301eSmrg 35344a49301eSmrg _mesa_set_fetch_functions(texImage, 3); 35354a49301eSmrg 35364a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 35374a49301eSmrg 35384a49301eSmrg /* state update */ 35394a49301eSmrg texObj->_Complete = GL_FALSE; 35404a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 35414a49301eSmrg } 35424a49301eSmrg } 35437117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35447117f1b4Smrg } 35457117f1b4Smrg else if (target == GL_PROXY_TEXTURE_3D) { 35467117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 35477117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 35487117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 35497117f1b4Smrg if (!error) { 35507117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 35517117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 35527117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 35537117f1b4Smrg width, height, depth, border); 35547117f1b4Smrg } 35557117f1b4Smrg if (error) { 35567117f1b4Smrg /* if error, clear all proxy texture image parameters */ 35577117f1b4Smrg struct gl_texture_image *texImage; 35587117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 35597117f1b4Smrg if (texImage) 35607117f1b4Smrg clear_teximage_fields(texImage); 35617117f1b4Smrg } 35627117f1b4Smrg else { 35637117f1b4Smrg /* store the teximage parameters */ 35647117f1b4Smrg struct gl_texture_object *texObj; 35657117f1b4Smrg struct gl_texture_image *texImage; 35664a49301eSmrg 35674a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 35684a49301eSmrg 35697117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35707117f1b4Smrg { 35717117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 35727117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 35737117f1b4Smrg depth, border, internalFormat); 35747117f1b4Smrg } 35757117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35767117f1b4Smrg } 35777117f1b4Smrg } 35787117f1b4Smrg else { 35797117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 35807117f1b4Smrg return; 35817117f1b4Smrg } 35827117f1b4Smrg} 35837117f1b4Smrg 35847117f1b4Smrg 35854a49301eSmrg/** 35864a49301eSmrg * Common helper for glCompressedTexSubImage1/2/3D(). 35874a49301eSmrg */ 35884a49301eSmrgstatic void 35894a49301eSmrgcompressed_tex_sub_image(GLuint dims, GLenum target, GLint level, 35904a49301eSmrg GLint xoffset, GLint yoffset, GLint zoffset, 35914a49301eSmrg GLsizei width, GLsizei height, GLsizei depth, 35924a49301eSmrg GLenum format, GLsizei imageSize, const GLvoid *data) 35937117f1b4Smrg{ 35947117f1b4Smrg struct gl_texture_object *texObj; 35957117f1b4Smrg struct gl_texture_image *texImage; 35967117f1b4Smrg GLenum error; 35977117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35987117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 35997117f1b4Smrg 36004a49301eSmrg error = compressed_subtexture_error_check(ctx, dims, target, level, 36017117f1b4Smrg xoffset, 0, 0, /* pos */ 36024a49301eSmrg width, height, depth, /* size */ 36037117f1b4Smrg format, imageSize); 36047117f1b4Smrg if (error) { 36054a49301eSmrg _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims); 36067117f1b4Smrg return; 36077117f1b4Smrg } 36087117f1b4Smrg 36094a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 36104a49301eSmrg 36117117f1b4Smrg _mesa_lock_texture(ctx, texObj); 36127117f1b4Smrg { 36137117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 36147117f1b4Smrg assert(texImage); 36157117f1b4Smrg 36164a49301eSmrg if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, 36174a49301eSmrg format, texImage)) { 36184a49301eSmrg /* error was recorded */ 36194a49301eSmrg } 36204a49301eSmrg else if (width > 0 && height > 0 && depth > 0) { 36214a49301eSmrg switch (dims) { 36224a49301eSmrg case 1: 36234a49301eSmrg if (ctx->Driver.CompressedTexSubImage1D) { 36244a49301eSmrg ctx->Driver.CompressedTexSubImage1D(ctx, target, level, 36254a49301eSmrg xoffset, width, 36264a49301eSmrg format, imageSize, data, 36274a49301eSmrg texObj, texImage); 36284a49301eSmrg } 36294a49301eSmrg break; 36304a49301eSmrg case 2: 36314a49301eSmrg if (ctx->Driver.CompressedTexSubImage2D) { 36324a49301eSmrg ctx->Driver.CompressedTexSubImage2D(ctx, target, level, 36334a49301eSmrg xoffset, yoffset, 36344a49301eSmrg width, height, 36354a49301eSmrg format, imageSize, data, 36364a49301eSmrg texObj, texImage); 36374a49301eSmrg } 36384a49301eSmrg break; 36394a49301eSmrg case 3: 36404a49301eSmrg if (ctx->Driver.CompressedTexSubImage3D) { 36414a49301eSmrg ctx->Driver.CompressedTexSubImage3D(ctx, target, level, 36424a49301eSmrg xoffset, yoffset, zoffset, 36434a49301eSmrg width, height, depth, 36444a49301eSmrg format, imageSize, data, 36454a49301eSmrg texObj, texImage); 36464a49301eSmrg } 36474a49301eSmrg break; 36484a49301eSmrg default: 36494a49301eSmrg ; 36504a49301eSmrg } 36517117f1b4Smrg 36524a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 36537117f1b4Smrg 36544a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 36557117f1b4Smrg } 36567117f1b4Smrg } 36577117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36587117f1b4Smrg} 36597117f1b4Smrg 36607117f1b4Smrg 36614a49301eSmrgvoid GLAPIENTRY 36624a49301eSmrg_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 36634a49301eSmrg GLsizei width, GLenum format, 36644a49301eSmrg GLsizei imageSize, const GLvoid *data) 36654a49301eSmrg{ 36664a49301eSmrg compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1, 36674a49301eSmrg format, imageSize, data); 36684a49301eSmrg} 36694a49301eSmrg 36704a49301eSmrg 36717117f1b4Smrgvoid GLAPIENTRY 36727117f1b4Smrg_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 36737117f1b4Smrg GLint yoffset, GLsizei width, GLsizei height, 36747117f1b4Smrg GLenum format, GLsizei imageSize, 36757117f1b4Smrg const GLvoid *data) 36767117f1b4Smrg{ 36774a49301eSmrg compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0, 36784a49301eSmrg width, height, 1, format, imageSize, data); 36797117f1b4Smrg} 36807117f1b4Smrg 36817117f1b4Smrg 36827117f1b4Smrgvoid GLAPIENTRY 36837117f1b4Smrg_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 36847117f1b4Smrg GLint yoffset, GLint zoffset, GLsizei width, 36857117f1b4Smrg GLsizei height, GLsizei depth, GLenum format, 36867117f1b4Smrg GLsizei imageSize, const GLvoid *data) 36877117f1b4Smrg{ 36884a49301eSmrg compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset, 36894a49301eSmrg width, height, depth, format, imageSize, data); 36907117f1b4Smrg} 36917117f1b4Smrg 36927117f1b4Smrg 3693