teximage.c revision cdc920a0
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) 491cdc920a0Smrg free(texImage->ImageOffsets); 492cdc920a0Smrg 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) { 846cdc920a0Smrg 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) 935cdc920a0Smrg free(img->ImageOffsets); 936cdc920a0Smrg img->ImageOffsets = (GLuint *) 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]; 1310cdc920a0Smrg 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]; 1326cdc920a0Smrg 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 2451cdc920a0Smrg#if FEATURE_OES_EGL_image 2452cdc920a0Smrgvoid GLAPIENTRY 2453cdc920a0Smrg_mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) 2454cdc920a0Smrg{ 2455cdc920a0Smrg struct gl_texture_object *texObj; 2456cdc920a0Smrg struct gl_texture_image *texImage; 2457cdc920a0Smrg GET_CURRENT_CONTEXT(ctx); 2458cdc920a0Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2459cdc920a0Smrg 2460cdc920a0Smrg if (target != GL_TEXTURE_2D) { 2461cdc920a0Smrg _mesa_error(ctx, GL_INVALID_ENUM, 2462cdc920a0Smrg "glEGLImageTargetTexture2D(target=%d)", target); 2463cdc920a0Smrg return; 2464cdc920a0Smrg } 2465cdc920a0Smrg 2466cdc920a0Smrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2467cdc920a0Smrg _mesa_update_state(ctx); 2468cdc920a0Smrg 2469cdc920a0Smrg texObj = _mesa_get_current_tex_object(ctx, target); 2470cdc920a0Smrg _mesa_lock_texture(ctx, texObj); 2471cdc920a0Smrg 2472cdc920a0Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 2473cdc920a0Smrg if (!texImage) { 2474cdc920a0Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D"); 2475cdc920a0Smrg } else { 2476cdc920a0Smrg if (texImage->Data) 2477cdc920a0Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 2478cdc920a0Smrg 2479cdc920a0Smrg ASSERT(texImage->Data == NULL); 2480cdc920a0Smrg ctx->Driver.EGLImageTargetTexture2D(ctx, target, 2481cdc920a0Smrg texObj, texImage, image); 2482cdc920a0Smrg 2483cdc920a0Smrg /* state update */ 2484cdc920a0Smrg texObj->_Complete = GL_FALSE; 2485cdc920a0Smrg ctx->NewState |= _NEW_TEXTURE; 2486cdc920a0Smrg } 2487cdc920a0Smrg _mesa_unlock_texture(ctx, texObj); 2488cdc920a0Smrg 2489cdc920a0Smrg} 2490cdc920a0Smrg#endif 2491cdc920a0Smrg 24927117f1b4Smrg 24937117f1b4Smrgvoid GLAPIENTRY 24947117f1b4Smrg_mesa_TexSubImage1D( GLenum target, GLint level, 24957117f1b4Smrg GLint xoffset, GLsizei width, 24967117f1b4Smrg GLenum format, GLenum type, 24977117f1b4Smrg const GLvoid *pixels ) 24987117f1b4Smrg{ 24997117f1b4Smrg GLsizei postConvWidth = width; 25007117f1b4Smrg struct gl_texture_object *texObj; 25014a49301eSmrg struct gl_texture_image *texImage; 25027117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25037117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 25047117f1b4Smrg 25054a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 25064a49301eSmrg _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n", 25074a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 25084a49301eSmrg xoffset, width, _mesa_lookup_enum_by_nr(format), 25094a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 25104a49301eSmrg 25114a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 25127117f1b4Smrg _mesa_update_state(ctx); 25137117f1b4Smrg 2514c1f859d4Smrg#if FEATURE_convolve 25157117f1b4Smrg /* XXX should test internal format */ 2516c1f859d4Smrg if (_mesa_is_color_format(format)) { 25177117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 25187117f1b4Smrg } 2519c1f859d4Smrg#endif 25207117f1b4Smrg 25217117f1b4Smrg if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 25227117f1b4Smrg postConvWidth, 1, 1, format, type)) { 25237117f1b4Smrg return; /* error was detected */ 25247117f1b4Smrg } 25257117f1b4Smrg 25267117f1b4Smrg 25274a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 25287117f1b4Smrg assert(texObj); 25297117f1b4Smrg 25307117f1b4Smrg _mesa_lock_texture(ctx, texObj); 25317117f1b4Smrg { 25327117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 25337117f1b4Smrg 25347117f1b4Smrg if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 25354a49301eSmrg postConvWidth, 1, 1, 25364a49301eSmrg format, type, texImage)) { 25374a49301eSmrg /* error was recorded */ 25387117f1b4Smrg } 25394a49301eSmrg else if (width > 0) { 25404a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 25414a49301eSmrg xoffset += texImage->Border; 25427117f1b4Smrg 25434a49301eSmrg ASSERT(ctx->Driver.TexSubImage1D); 25444a49301eSmrg ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width, 25454a49301eSmrg format, type, pixels, &ctx->Unpack, 25464a49301eSmrg texObj, texImage); 25477117f1b4Smrg 25484a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 25497117f1b4Smrg 25504a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 25514a49301eSmrg } 25527117f1b4Smrg } 25537117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 25547117f1b4Smrg} 25557117f1b4Smrg 25567117f1b4Smrg 25577117f1b4Smrgvoid GLAPIENTRY 25587117f1b4Smrg_mesa_TexSubImage2D( GLenum target, GLint level, 25597117f1b4Smrg GLint xoffset, GLint yoffset, 25607117f1b4Smrg GLsizei width, GLsizei height, 25617117f1b4Smrg GLenum format, GLenum type, 25627117f1b4Smrg const GLvoid *pixels ) 25637117f1b4Smrg{ 25647117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 25657117f1b4Smrg struct gl_texture_object *texObj; 25667117f1b4Smrg struct gl_texture_image *texImage; 25677117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25687117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 25697117f1b4Smrg 25704a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 25714a49301eSmrg _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n", 25724a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 25734a49301eSmrg xoffset, yoffset, width, height, 25744a49301eSmrg _mesa_lookup_enum_by_nr(format), 25754a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 25764a49301eSmrg 25774a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 25787117f1b4Smrg _mesa_update_state(ctx); 25797117f1b4Smrg 2580c1f859d4Smrg#if FEATURE_convolve 25817117f1b4Smrg /* XXX should test internal format */ 2582c1f859d4Smrg if (_mesa_is_color_format(format)) { 25837117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 25847117f1b4Smrg &postConvHeight); 25857117f1b4Smrg } 2586c1f859d4Smrg#endif 25877117f1b4Smrg 25887117f1b4Smrg if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 25897117f1b4Smrg postConvWidth, postConvHeight, 1, format, type)) { 25907117f1b4Smrg return; /* error was detected */ 25917117f1b4Smrg } 25927117f1b4Smrg 25934a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 25944a49301eSmrg 25957117f1b4Smrg _mesa_lock_texture(ctx, texObj); 25967117f1b4Smrg { 25977117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 25987117f1b4Smrg 25997117f1b4Smrg if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 26004a49301eSmrg postConvWidth, postConvHeight, 1, 26014a49301eSmrg format, type, texImage)) { 26024a49301eSmrg /* error was recorded */ 26037117f1b4Smrg } 26044a49301eSmrg else if (width > 0 && height >= 0) { 26054a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 26064a49301eSmrg xoffset += texImage->Border; 26074a49301eSmrg yoffset += texImage->Border; 26084a49301eSmrg 26094a49301eSmrg ASSERT(ctx->Driver.TexSubImage2D); 26104a49301eSmrg ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset, 26114a49301eSmrg width, height, format, type, pixels, 26124a49301eSmrg &ctx->Unpack, texObj, texImage); 26137117f1b4Smrg 26144a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 26157117f1b4Smrg 26164a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 26174a49301eSmrg } 26187117f1b4Smrg } 26197117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 26207117f1b4Smrg} 26217117f1b4Smrg 26227117f1b4Smrg 26237117f1b4Smrg 26247117f1b4Smrgvoid GLAPIENTRY 26257117f1b4Smrg_mesa_TexSubImage3D( GLenum target, GLint level, 26267117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 26277117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 26287117f1b4Smrg GLenum format, GLenum type, 26297117f1b4Smrg const GLvoid *pixels ) 26307117f1b4Smrg{ 26317117f1b4Smrg struct gl_texture_object *texObj; 26327117f1b4Smrg struct gl_texture_image *texImage; 26337117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 26347117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 26357117f1b4Smrg 26364a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 26374a49301eSmrg _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n", 26384a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 26394a49301eSmrg xoffset, yoffset, zoffset, width, height, depth, 26404a49301eSmrg _mesa_lookup_enum_by_nr(format), 26414a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 26424a49301eSmrg 26434a49301eSmrg if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 26447117f1b4Smrg _mesa_update_state(ctx); 26457117f1b4Smrg 26467117f1b4Smrg if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 26477117f1b4Smrg width, height, depth, format, type)) { 26487117f1b4Smrg return; /* error was detected */ 26497117f1b4Smrg } 26507117f1b4Smrg 26514a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 26527117f1b4Smrg 26537117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26547117f1b4Smrg { 26557117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 26567117f1b4Smrg 26574a49301eSmrg if (subtexture_error_check2(ctx, 3, target, level, 26584a49301eSmrg xoffset, yoffset, zoffset, 26594a49301eSmrg width, height, depth, 26604a49301eSmrg format, type, texImage)) { 26614a49301eSmrg /* error was recorded */ 26627117f1b4Smrg } 26634a49301eSmrg else if (width > 0 && height > 0 && height > 0) { 26644a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 26654a49301eSmrg xoffset += texImage->Border; 26664a49301eSmrg yoffset += texImage->Border; 26674a49301eSmrg zoffset += texImage->Border; 26687117f1b4Smrg 26694a49301eSmrg ASSERT(ctx->Driver.TexSubImage3D); 26704a49301eSmrg ctx->Driver.TexSubImage3D(ctx, target, level, 26714a49301eSmrg xoffset, yoffset, zoffset, 26724a49301eSmrg width, height, depth, 26734a49301eSmrg format, type, pixels, 26744a49301eSmrg &ctx->Unpack, texObj, texImage ); 26757117f1b4Smrg 26764a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 26777117f1b4Smrg 26784a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 26794a49301eSmrg } 26807117f1b4Smrg } 26817117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 26827117f1b4Smrg} 26837117f1b4Smrg 26847117f1b4Smrg 26857117f1b4Smrg 26867117f1b4Smrgvoid GLAPIENTRY 26877117f1b4Smrg_mesa_CopyTexImage1D( GLenum target, GLint level, 26887117f1b4Smrg GLenum internalFormat, 26897117f1b4Smrg GLint x, GLint y, 26907117f1b4Smrg GLsizei width, GLint border ) 26917117f1b4Smrg{ 26927117f1b4Smrg struct gl_texture_object *texObj; 26937117f1b4Smrg struct gl_texture_image *texImage; 26947117f1b4Smrg GLsizei postConvWidth = width; 2695c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 26967117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 26977117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 26987117f1b4Smrg 26994a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 27004a49301eSmrg _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n", 27014a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 27024a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 27034a49301eSmrg x, y, width, border); 27044a49301eSmrg 2705c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 27067117f1b4Smrg _mesa_update_state(ctx); 27077117f1b4Smrg 2708c1f859d4Smrg#if FEATURE_convolve 2709c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 27107117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 27117117f1b4Smrg } 2712c1f859d4Smrg#endif 27137117f1b4Smrg 27147117f1b4Smrg if (copytexture_error_check(ctx, 1, target, level, internalFormat, 27157117f1b4Smrg postConvWidth, 1, border)) 27167117f1b4Smrg return; 27177117f1b4Smrg 27184a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 27194a49301eSmrg 27207117f1b4Smrg _mesa_lock_texture(ctx, texObj); 27217117f1b4Smrg { 27227117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 27237117f1b4Smrg if (!texImage) { 27247117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 27257117f1b4Smrg } 27264a49301eSmrg else { 27274a49301eSmrg if (texImage->Data) { 27284a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 27294a49301eSmrg } 27307117f1b4Smrg 27314a49301eSmrg ASSERT(texImage->Data == NULL); 27324a49301eSmrg 27334a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 27344a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 27354a49301eSmrg border, internalFormat); 27367117f1b4Smrg 27374a49301eSmrg /* Choose actual texture format */ 27384a49301eSmrg texImage->TexFormat = 27394a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 27404a49301eSmrg GL_NONE, GL_NONE); 27414a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 27427117f1b4Smrg 27434a49301eSmrg ASSERT(ctx->Driver.CopyTexImage1D); 27444a49301eSmrg ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, 27454a49301eSmrg x, y, width, border); 27467117f1b4Smrg 27474a49301eSmrg ASSERT(texImage->TexFormat); 27487117f1b4Smrg 27494a49301eSmrg _mesa_set_fetch_functions(texImage, 1); 27507117f1b4Smrg 27514a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 27527117f1b4Smrg 27534a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 27544a49301eSmrg 27554a49301eSmrg /* state update */ 27564a49301eSmrg texObj->_Complete = GL_FALSE; 27574a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 27584a49301eSmrg } 27597117f1b4Smrg } 27607117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 27617117f1b4Smrg} 27627117f1b4Smrg 27637117f1b4Smrg 27647117f1b4Smrg 27657117f1b4Smrgvoid GLAPIENTRY 27667117f1b4Smrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 27677117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height, 27687117f1b4Smrg GLint border ) 27697117f1b4Smrg{ 27707117f1b4Smrg struct gl_texture_object *texObj; 27717117f1b4Smrg struct gl_texture_image *texImage; 27727117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 2773c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 27747117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27757117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 27767117f1b4Smrg 27774a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 27784a49301eSmrg _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n", 27794a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 27804a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 27814a49301eSmrg x, y, width, height, border); 27824a49301eSmrg 2783c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 27847117f1b4Smrg _mesa_update_state(ctx); 27857117f1b4Smrg 2786c1f859d4Smrg#if FEATURE_convolve 2787c1f859d4Smrg if (_mesa_is_color_format(internalFormat)) { 27887117f1b4Smrg _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 27897117f1b4Smrg &postConvHeight); 27907117f1b4Smrg } 2791c1f859d4Smrg#endif 27927117f1b4Smrg 27937117f1b4Smrg if (copytexture_error_check(ctx, 2, target, level, internalFormat, 27947117f1b4Smrg postConvWidth, postConvHeight, border)) 27957117f1b4Smrg return; 27967117f1b4Smrg 27974a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 27987117f1b4Smrg 27997117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28007117f1b4Smrg { 28017117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 28027117f1b4Smrg 28037117f1b4Smrg if (!texImage) { 28047117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 28057117f1b4Smrg } 28064a49301eSmrg else { 28074a49301eSmrg if (texImage->Data) { 28084a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 28094a49301eSmrg } 28104a49301eSmrg 28114a49301eSmrg ASSERT(texImage->Data == NULL); 28124a49301eSmrg 28134a49301eSmrg clear_teximage_fields(texImage); /* not really needed, but helpful */ 28144a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 28154a49301eSmrg postConvWidth, postConvHeight, 1, 28164a49301eSmrg border, internalFormat); 28174a49301eSmrg 28184a49301eSmrg /* Choose actual texture format */ 28194a49301eSmrg texImage->TexFormat = 28204a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 28214a49301eSmrg GL_NONE, GL_NONE); 28224a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 28237117f1b4Smrg 28244a49301eSmrg ASSERT(ctx->Driver.CopyTexImage2D); 28254a49301eSmrg ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, 28264a49301eSmrg x, y, width, height, border); 28277117f1b4Smrg 28284a49301eSmrg ASSERT(texImage->TexFormat); 28297117f1b4Smrg 28304a49301eSmrg _mesa_set_fetch_functions(texImage, 2); 28314a49301eSmrg 28324a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 28334a49301eSmrg 28344a49301eSmrg update_fbo_texture(ctx, texObj, face, level); 28354a49301eSmrg 28364a49301eSmrg /* state update */ 28374a49301eSmrg texObj->_Complete = GL_FALSE; 28384a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 28394a49301eSmrg } 28407117f1b4Smrg } 28417117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28427117f1b4Smrg} 28437117f1b4Smrg 28447117f1b4Smrg 28457117f1b4Smrgvoid GLAPIENTRY 28467117f1b4Smrg_mesa_CopyTexSubImage1D( GLenum target, GLint level, 28477117f1b4Smrg GLint xoffset, GLint x, GLint y, GLsizei width ) 28487117f1b4Smrg{ 28497117f1b4Smrg struct gl_texture_object *texObj; 28507117f1b4Smrg struct gl_texture_image *texImage; 28517117f1b4Smrg GLsizei postConvWidth = width; 2852c1f859d4Smrg GLint yoffset = 0; 2853c1f859d4Smrg GLsizei height = 1; 2854c1f859d4Smrg 28557117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28567117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 28577117f1b4Smrg 28584a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 28594a49301eSmrg _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n", 28604a49301eSmrg _mesa_lookup_enum_by_nr(target), 28614a49301eSmrg level, xoffset, x, y, width); 28624a49301eSmrg 2863c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 28647117f1b4Smrg _mesa_update_state(ctx); 28657117f1b4Smrg 2866c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 1, target, level)) 28677117f1b4Smrg return; 28687117f1b4Smrg 28694a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 28707117f1b4Smrg 28717117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28727117f1b4Smrg { 28737117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 28747117f1b4Smrg 2875c1f859d4Smrg#if FEATURE_convolve 2876c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2877c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2878c1f859d4Smrg } 2879c1f859d4Smrg#endif 2880c1f859d4Smrg 28817117f1b4Smrg if (copytexsubimage_error_check2(ctx, 1, target, level, 28827117f1b4Smrg xoffset, 0, 0, postConvWidth, 1, 28834a49301eSmrg texImage)) { 28844a49301eSmrg /* error was recorded */ 28854a49301eSmrg } 28864a49301eSmrg else { 28874a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 28884a49301eSmrg xoffset += texImage->Border; 28897117f1b4Smrg 28904a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 28914a49301eSmrg &width, &height)) { 28924a49301eSmrg ASSERT(ctx->Driver.CopyTexSubImage1D); 28934a49301eSmrg ctx->Driver.CopyTexSubImage1D(ctx, target, level, 28944a49301eSmrg xoffset, x, y, width); 28957117f1b4Smrg 28964a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 2897c1f859d4Smrg 28984a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 28994a49301eSmrg } 29004a49301eSmrg } 29017117f1b4Smrg } 29027117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29037117f1b4Smrg} 29047117f1b4Smrg 29057117f1b4Smrg 29067117f1b4Smrg 29077117f1b4Smrgvoid GLAPIENTRY 29087117f1b4Smrg_mesa_CopyTexSubImage2D( GLenum target, GLint level, 29097117f1b4Smrg GLint xoffset, GLint yoffset, 29107117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 29117117f1b4Smrg{ 29127117f1b4Smrg struct gl_texture_object *texObj; 29137117f1b4Smrg struct gl_texture_image *texImage; 29147117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 29157117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29167117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29177117f1b4Smrg 29184a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 29194a49301eSmrg _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n", 29204a49301eSmrg _mesa_lookup_enum_by_nr(target), 29214a49301eSmrg level, xoffset, yoffset, x, y, width, height); 29224a49301eSmrg 2923c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 29247117f1b4Smrg _mesa_update_state(ctx); 29257117f1b4Smrg 2926c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 2, target, level)) 29277117f1b4Smrg return; 29287117f1b4Smrg 29294a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 29307117f1b4Smrg 29317117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29327117f1b4Smrg { 29337117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 29347117f1b4Smrg 2935c1f859d4Smrg#if FEATURE_convolve 2936c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2937c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 2, 2938c1f859d4Smrg &postConvWidth, &postConvHeight); 2939c1f859d4Smrg } 2940c1f859d4Smrg#endif 2941c1f859d4Smrg 29424a49301eSmrg if (copytexsubimage_error_check2(ctx, 2, target, level, 29434a49301eSmrg xoffset, yoffset, 0, 29444a49301eSmrg postConvWidth, postConvHeight, 29454a49301eSmrg texImage)) { 29464a49301eSmrg /* error was recorded */ 29474a49301eSmrg } 29484a49301eSmrg else { 29494a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 29504a49301eSmrg xoffset += texImage->Border; 29514a49301eSmrg yoffset += texImage->Border; 29524a49301eSmrg 29534a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 29544a49301eSmrg &width, &height)) { 29554a49301eSmrg ASSERT(ctx->Driver.CopyTexSubImage2D); 29564a49301eSmrg ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, 29574a49301eSmrg x, y, width, height); 29587117f1b4Smrg 29594a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 2960c1f859d4Smrg 29614a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 29624a49301eSmrg } 2963c1f859d4Smrg } 29647117f1b4Smrg } 29657117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29667117f1b4Smrg} 29677117f1b4Smrg 29687117f1b4Smrg 29697117f1b4Smrg 29707117f1b4Smrgvoid GLAPIENTRY 29717117f1b4Smrg_mesa_CopyTexSubImage3D( GLenum target, GLint level, 29727117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 29737117f1b4Smrg GLint x, GLint y, GLsizei width, GLsizei height ) 29747117f1b4Smrg{ 29757117f1b4Smrg struct gl_texture_object *texObj; 29767117f1b4Smrg struct gl_texture_image *texImage; 29777117f1b4Smrg GLsizei postConvWidth = width, postConvHeight = height; 29787117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29797117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29807117f1b4Smrg 29814a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 29824a49301eSmrg _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n", 29834a49301eSmrg _mesa_lookup_enum_by_nr(target), 29844a49301eSmrg level, xoffset, yoffset, zoffset, x, y, width, height); 29854a49301eSmrg 2986c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 29877117f1b4Smrg _mesa_update_state(ctx); 29887117f1b4Smrg 2989c1f859d4Smrg if (copytexsubimage_error_check1(ctx, 3, target, level)) 29907117f1b4Smrg return; 29917117f1b4Smrg 29924a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 29937117f1b4Smrg 29947117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29957117f1b4Smrg { 29967117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 29977117f1b4Smrg 2998c1f859d4Smrg#if FEATURE_convolve 2999c1f859d4Smrg if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3000c1f859d4Smrg _mesa_adjust_image_for_convolution(ctx, 2, 3001c1f859d4Smrg &postConvWidth, &postConvHeight); 3002c1f859d4Smrg } 3003c1f859d4Smrg#endif 3004c1f859d4Smrg 30057117f1b4Smrg if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 30067117f1b4Smrg zoffset, postConvWidth, postConvHeight, 30074a49301eSmrg texImage)) { 30084a49301eSmrg /* error was recored */ 3009c1f859d4Smrg } 30104a49301eSmrg else { 30114a49301eSmrg /* If we have a border, xoffset=-1 is legal. Bias by border width */ 30124a49301eSmrg xoffset += texImage->Border; 30134a49301eSmrg yoffset += texImage->Border; 30144a49301eSmrg zoffset += texImage->Border; 30154a49301eSmrg 30164a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 30174a49301eSmrg &width, &height)) { 30184a49301eSmrg ASSERT(ctx->Driver.CopyTexSubImage3D); 30194a49301eSmrg ctx->Driver.CopyTexSubImage3D(ctx, target, level, 30204a49301eSmrg xoffset, yoffset, zoffset, 30214a49301eSmrg x, y, width, height); 3022c1f859d4Smrg 30234a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 30244a49301eSmrg 30254a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 30264a49301eSmrg } 30274a49301eSmrg } 30287117f1b4Smrg } 30297117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 30307117f1b4Smrg} 30317117f1b4Smrg 30327117f1b4Smrg 30337117f1b4Smrg 30347117f1b4Smrg 30357117f1b4Smrg/**********************************************************************/ 30367117f1b4Smrg/****** Compressed Textures ******/ 30377117f1b4Smrg/**********************************************************************/ 30387117f1b4Smrg 30397117f1b4Smrg 30404a49301eSmrg/** 30414a49301eSmrg * Return expected size of a compressed texture. 30424a49301eSmrg */ 30434a49301eSmrgstatic GLuint 30444a49301eSmrgcompressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, 30454a49301eSmrg GLenum glformat) 30464a49301eSmrg{ 30474a49301eSmrg gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 30484a49301eSmrg return _mesa_format_image_size(mesaFormat, width, height, depth); 30494a49301eSmrg} 30504a49301eSmrg 30514a49301eSmrg 30524a49301eSmrg/* 30534a49301eSmrg * Return compressed texture block size, in pixels. 30544a49301eSmrg */ 30554a49301eSmrgstatic void 30564a49301eSmrgget_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) 30574a49301eSmrg{ 30584a49301eSmrg gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 30594a49301eSmrg _mesa_get_format_block_size(mesaFormat, bw, bh); 30604a49301eSmrg} 30614a49301eSmrg 30624a49301eSmrg 30637117f1b4Smrg/** 30647117f1b4Smrg * Error checking for glCompressedTexImage[123]D(). 30657117f1b4Smrg * \return error code or GL_NO_ERROR. 30667117f1b4Smrg */ 30677117f1b4Smrgstatic GLenum 30687117f1b4Smrgcompressed_texture_error_check(GLcontext *ctx, GLint dimensions, 30697117f1b4Smrg GLenum target, GLint level, 30707117f1b4Smrg GLenum internalFormat, GLsizei width, 30717117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 30727117f1b4Smrg GLsizei imageSize) 30737117f1b4Smrg{ 30747117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 30757117f1b4Smrg 30767117f1b4Smrg if (dimensions == 1) { 30777117f1b4Smrg /* 1D compressed textures not allowed */ 30787117f1b4Smrg return GL_INVALID_ENUM; 30797117f1b4Smrg } 30807117f1b4Smrg else if (dimensions == 2) { 30817117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 30827117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 30837117f1b4Smrg } 30847117f1b4Smrg else if (target == GL_TEXTURE_2D) { 30857117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 30867117f1b4Smrg } 30877117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 30887117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 30897117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30907117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 30917117f1b4Smrg } 30927117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 30937117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 30947117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 30957117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 30967117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 30977117f1b4Smrg } 30987117f1b4Smrg else { 30997117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31007117f1b4Smrg } 31017117f1b4Smrg } 31027117f1b4Smrg else if (dimensions == 3) { 31037117f1b4Smrg /* 3D compressed textures not allowed */ 31047117f1b4Smrg return GL_INVALID_ENUM; 31057117f1b4Smrg } 31067117f1b4Smrg 31077117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 31087117f1b4Smrg 31097117f1b4Smrg /* This will detect any invalid internalFormat value */ 31107117f1b4Smrg if (!is_compressed_format(ctx, internalFormat)) 31117117f1b4Smrg return GL_INVALID_ENUM; 31127117f1b4Smrg 31137117f1b4Smrg /* This should really never fail */ 31147117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) 31157117f1b4Smrg return GL_INVALID_ENUM; 31167117f1b4Smrg 31177117f1b4Smrg if (border != 0) 31187117f1b4Smrg return GL_INVALID_VALUE; 31197117f1b4Smrg 31207117f1b4Smrg /* 31217117f1b4Smrg * XXX We should probably use the proxy texture error check function here. 31227117f1b4Smrg */ 31237117f1b4Smrg if (width < 1 || width > maxTextureSize || 3124c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) 31257117f1b4Smrg return GL_INVALID_VALUE; 31267117f1b4Smrg 31277117f1b4Smrg if ((height < 1 || height > maxTextureSize || 3128c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) 31297117f1b4Smrg && dimensions > 1) 31307117f1b4Smrg return GL_INVALID_VALUE; 31317117f1b4Smrg 31327117f1b4Smrg if ((depth < 1 || depth > maxTextureSize || 3133c1f859d4Smrg (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) 31347117f1b4Smrg && dimensions > 2) 31357117f1b4Smrg return GL_INVALID_VALUE; 31367117f1b4Smrg 31377117f1b4Smrg /* For cube map, width must equal height */ 31387117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 31397117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 31407117f1b4Smrg return GL_INVALID_VALUE; 31417117f1b4Smrg 31427117f1b4Smrg if (level < 0 || level >= maxLevels) 31437117f1b4Smrg return GL_INVALID_VALUE; 31447117f1b4Smrg 31454a49301eSmrg expectedSize = compressed_tex_size(width, height, depth, internalFormat); 31467117f1b4Smrg if (expectedSize != imageSize) 31477117f1b4Smrg return GL_INVALID_VALUE; 31487117f1b4Smrg 31497117f1b4Smrg#if FEATURE_EXT_texture_sRGB 31507117f1b4Smrg if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 31517117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 31527117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 31537117f1b4Smrg internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 31547117f1b4Smrg && border != 0) { 31557117f1b4Smrg return GL_INVALID_OPERATION; 31567117f1b4Smrg } 31577117f1b4Smrg#endif 31587117f1b4Smrg 31597117f1b4Smrg return GL_NO_ERROR; 31607117f1b4Smrg} 31617117f1b4Smrg 31627117f1b4Smrg 31637117f1b4Smrg/** 31647117f1b4Smrg * Error checking for glCompressedTexSubImage[123]D(). 31657117f1b4Smrg * \warning There are some bad assumptions here about the size of compressed 31667117f1b4Smrg * texture tiles (multiple of 4) used to test the validity of the 31677117f1b4Smrg * offset and size parameters. 31687117f1b4Smrg * \return error code or GL_NO_ERROR. 31697117f1b4Smrg */ 31707117f1b4Smrgstatic GLenum 31717117f1b4Smrgcompressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 31727117f1b4Smrg GLenum target, GLint level, 31737117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 31747117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 31757117f1b4Smrg GLenum format, GLsizei imageSize) 31767117f1b4Smrg{ 31777117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 31784a49301eSmrg GLuint bw, bh; 31797117f1b4Smrg (void) zoffset; 31807117f1b4Smrg 31817117f1b4Smrg if (dimensions == 1) { 31827117f1b4Smrg /* 1D compressed textures not allowed */ 31837117f1b4Smrg return GL_INVALID_ENUM; 31847117f1b4Smrg } 31857117f1b4Smrg else if (dimensions == 2) { 31867117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 31877117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 31887117f1b4Smrg } 31897117f1b4Smrg else if (target == GL_TEXTURE_2D) { 31907117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 31917117f1b4Smrg } 31927117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 31937117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 31947117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 31957117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 31967117f1b4Smrg } 31977117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 31987117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 31997117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 32007117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32017117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 32027117f1b4Smrg } 32037117f1b4Smrg else { 32047117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32057117f1b4Smrg } 32067117f1b4Smrg } 32077117f1b4Smrg else if (dimensions == 3) { 32087117f1b4Smrg /* 3D compressed textures not allowed */ 32097117f1b4Smrg return GL_INVALID_ENUM; 32107117f1b4Smrg } 32117117f1b4Smrg 32127117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 32137117f1b4Smrg 32147117f1b4Smrg /* this will catch any invalid compressed format token */ 32157117f1b4Smrg if (!is_compressed_format(ctx, format)) 32167117f1b4Smrg return GL_INVALID_ENUM; 32177117f1b4Smrg 32187117f1b4Smrg if (width < 1 || width > maxTextureSize) 32197117f1b4Smrg return GL_INVALID_VALUE; 32207117f1b4Smrg 32217117f1b4Smrg if ((height < 1 || height > maxTextureSize) 32227117f1b4Smrg && dimensions > 1) 32237117f1b4Smrg return GL_INVALID_VALUE; 32247117f1b4Smrg 32257117f1b4Smrg if (level < 0 || level >= maxLevels) 32267117f1b4Smrg return GL_INVALID_VALUE; 32277117f1b4Smrg 32284a49301eSmrg /* 32294a49301eSmrg * do checks which depend on compression block size 32307117f1b4Smrg */ 32314a49301eSmrg get_compressed_block_size(format, &bw, &bh); 32324a49301eSmrg 32334a49301eSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0)) 32347117f1b4Smrg return GL_INVALID_VALUE; 32357117f1b4Smrg 32364a49301eSmrg if ((width % bw != 0) && width != 2 && width != 1) 32377117f1b4Smrg return GL_INVALID_VALUE; 32387117f1b4Smrg 32394a49301eSmrg if ((height % bh != 0) && height != 2 && height != 1) 32407117f1b4Smrg return GL_INVALID_VALUE; 32417117f1b4Smrg 32424a49301eSmrg expectedSize = compressed_tex_size(width, height, depth, format); 32437117f1b4Smrg if (expectedSize != imageSize) 32447117f1b4Smrg return GL_INVALID_VALUE; 32457117f1b4Smrg 32467117f1b4Smrg return GL_NO_ERROR; 32477117f1b4Smrg} 32487117f1b4Smrg 32497117f1b4Smrg 32504a49301eSmrg/** 32514a49301eSmrg * Do second part of glCompressedTexSubImage error checking. 32524a49301eSmrg * \return GL_TRUE if error found, GL_FALSE otherwise. 32534a49301eSmrg */ 32544a49301eSmrgstatic GLboolean 32554a49301eSmrgcompressed_subtexture_error_check2(GLcontext *ctx, GLuint dims, 32564a49301eSmrg GLsizei width, GLsizei height, 32574a49301eSmrg GLsizei depth, GLenum format, 32584a49301eSmrg struct gl_texture_image *texImage) 32594a49301eSmrg{ 32604a49301eSmrg 32614a49301eSmrg if ((GLint) format != texImage->InternalFormat) { 32624a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 32634a49301eSmrg "glCompressedTexSubImage%uD(format=0x%x)", dims, format); 32644a49301eSmrg return GL_TRUE; 32654a49301eSmrg } 32664a49301eSmrg 32674a49301eSmrg if (((width == 1 || width == 2) && 3268cdc920a0Smrg width != (GLsizei) texImage->Width) || 3269cdc920a0Smrg (width > (GLsizei) texImage->Width)) { 32704a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32714a49301eSmrg "glCompressedTexSubImage%uD(width=%d)", dims, width); 32724a49301eSmrg return GL_TRUE; 32734a49301eSmrg } 32744a49301eSmrg 32754a49301eSmrg if (dims >= 2) { 32764a49301eSmrg if (((height == 1 || height == 2) && 3277cdc920a0Smrg height != (GLsizei) texImage->Height) || 3278cdc920a0Smrg (height > (GLsizei) texImage->Height)) { 32794a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32804a49301eSmrg "glCompressedTexSubImage%uD(height=%d)", dims, height); 32814a49301eSmrg return GL_TRUE; 32824a49301eSmrg } 32834a49301eSmrg } 32844a49301eSmrg 32854a49301eSmrg if (dims >= 3) { 32864a49301eSmrg if (((depth == 1 || depth == 2) && 3287cdc920a0Smrg depth != (GLsizei) texImage->Depth) || 3288cdc920a0Smrg (depth > (GLsizei) texImage->Depth)) { 32894a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32904a49301eSmrg "glCompressedTexSubImage%uD(depth=%d)", dims, depth); 32914a49301eSmrg return GL_TRUE; 32924a49301eSmrg } 32934a49301eSmrg } 32944a49301eSmrg 32954a49301eSmrg return GL_FALSE; 32964a49301eSmrg} 32974a49301eSmrg 32984a49301eSmrg 32997117f1b4Smrg 33007117f1b4Smrgvoid GLAPIENTRY 33017117f1b4Smrg_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 33027117f1b4Smrg GLenum internalFormat, GLsizei width, 33037117f1b4Smrg GLint border, GLsizei imageSize, 33047117f1b4Smrg const GLvoid *data) 33057117f1b4Smrg{ 33067117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 33077117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 33087117f1b4Smrg 33094a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 33104a49301eSmrg _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n", 33114a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 33124a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 33134a49301eSmrg width, border, imageSize, data); 33144a49301eSmrg 33157117f1b4Smrg if (target == GL_TEXTURE_1D) { 33167117f1b4Smrg /* non-proxy target */ 33177117f1b4Smrg struct gl_texture_object *texObj; 33187117f1b4Smrg struct gl_texture_image *texImage; 33197117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 33207117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 33217117f1b4Smrg if (error) { 33227117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage1D"); 33237117f1b4Smrg return; 33247117f1b4Smrg } 33257117f1b4Smrg 33264a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 33277117f1b4Smrg 33287117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33297117f1b4Smrg { 33307117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 33317117f1b4Smrg if (!texImage) { 33327117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 33337117f1b4Smrg } 33344a49301eSmrg else { 33354a49301eSmrg if (texImage->Data) { 33364a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 33374a49301eSmrg } 33384a49301eSmrg ASSERT(texImage->Data == NULL); 33394a49301eSmrg 33404a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 33414a49301eSmrg border, internalFormat); 33424a49301eSmrg 33434a49301eSmrg /* Choose actual texture format */ 33444a49301eSmrg texImage->TexFormat = 33454a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 33464a49301eSmrg GL_NONE, GL_NONE); 33474a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 33484a49301eSmrg 33494a49301eSmrg ASSERT(ctx->Driver.CompressedTexImage1D); 33504a49301eSmrg ctx->Driver.CompressedTexImage1D(ctx, target, level, 33514a49301eSmrg internalFormat, width, border, 33524a49301eSmrg imageSize, data, 33534a49301eSmrg texObj, texImage); 33547117f1b4Smrg 33554a49301eSmrg _mesa_set_fetch_functions(texImage, 1); 33567117f1b4Smrg 33574a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 33587117f1b4Smrg 33594a49301eSmrg /* state update */ 33604a49301eSmrg texObj->_Complete = GL_FALSE; 33614a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 33624a49301eSmrg } 33637117f1b4Smrg } 33647117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33657117f1b4Smrg } 33667117f1b4Smrg else if (target == GL_PROXY_TEXTURE_1D) { 33677117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 33687117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 1, target, level, 33697117f1b4Smrg internalFormat, width, 1, 1, border, imageSize); 33707117f1b4Smrg if (!error) { 33717117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 33727117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 33737117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 33747117f1b4Smrg width, 1, 1, border); 33757117f1b4Smrg } 33767117f1b4Smrg if (error) { 33777117f1b4Smrg /* if error, clear all proxy texture image parameters */ 33787117f1b4Smrg struct gl_texture_image *texImage; 33797117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 33807117f1b4Smrg if (texImage) 33817117f1b4Smrg clear_teximage_fields(texImage); 33827117f1b4Smrg } 33837117f1b4Smrg else { 33847117f1b4Smrg /* store the teximage parameters */ 33857117f1b4Smrg struct gl_texture_object *texObj; 33867117f1b4Smrg struct gl_texture_image *texImage; 33874a49301eSmrg 33884a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 33897117f1b4Smrg 33907117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33917117f1b4Smrg { 33927117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 33937117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 33947117f1b4Smrg border, internalFormat); 33957117f1b4Smrg } 33967117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33977117f1b4Smrg } 33987117f1b4Smrg } 33997117f1b4Smrg else { 34007117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 34017117f1b4Smrg return; 34027117f1b4Smrg } 34037117f1b4Smrg} 34047117f1b4Smrg 34057117f1b4Smrg 34067117f1b4Smrgvoid GLAPIENTRY 34077117f1b4Smrg_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 34087117f1b4Smrg GLenum internalFormat, GLsizei width, 34097117f1b4Smrg GLsizei height, GLint border, GLsizei imageSize, 34107117f1b4Smrg const GLvoid *data) 34117117f1b4Smrg{ 34127117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 34137117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 34147117f1b4Smrg 34154a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 34164a49301eSmrg _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n", 34174a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 34184a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 34194a49301eSmrg width, height, border, imageSize, data); 34204a49301eSmrg 34217117f1b4Smrg if (target == GL_TEXTURE_2D || 34227117f1b4Smrg (ctx->Extensions.ARB_texture_cube_map && 34237117f1b4Smrg target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 34247117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 34257117f1b4Smrg /* non-proxy target */ 34267117f1b4Smrg struct gl_texture_object *texObj; 34277117f1b4Smrg struct gl_texture_image *texImage; 34284a49301eSmrg 34297117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 34307117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 34317117f1b4Smrg if (error) { 34327117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage2D"); 34337117f1b4Smrg return; 34347117f1b4Smrg } 34357117f1b4Smrg 34364a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 34377117f1b4Smrg 34387117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34397117f1b4Smrg { 34407117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 34417117f1b4Smrg if (!texImage) { 34427117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 34437117f1b4Smrg } 34444a49301eSmrg else { 34454a49301eSmrg if (texImage->Data) { 34464a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 34474a49301eSmrg } 34484a49301eSmrg ASSERT(texImage->Data == NULL); 34494a49301eSmrg 34504a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 34514a49301eSmrg border, internalFormat); 34524a49301eSmrg 34534a49301eSmrg /* Choose actual texture format */ 34544a49301eSmrg texImage->TexFormat = 34554a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 34564a49301eSmrg GL_NONE, GL_NONE); 34574a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 34584a49301eSmrg 34594a49301eSmrg ASSERT(ctx->Driver.CompressedTexImage2D); 34604a49301eSmrg ctx->Driver.CompressedTexImage2D(ctx, target, level, 34614a49301eSmrg internalFormat, width, height, 34624a49301eSmrg border, imageSize, data, 34634a49301eSmrg texObj, texImage); 34644a49301eSmrg 34654a49301eSmrg _mesa_set_fetch_functions(texImage, 2); 34664a49301eSmrg 34674a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 34684a49301eSmrg 34694a49301eSmrg /* state update */ 34704a49301eSmrg texObj->_Complete = GL_FALSE; 34714a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 34724a49301eSmrg } 34734a49301eSmrg } 34747117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 34757117f1b4Smrg } 34767117f1b4Smrg else if (target == GL_PROXY_TEXTURE_2D || 34777117f1b4Smrg (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 34787117f1b4Smrg ctx->Extensions.ARB_texture_cube_map)) { 34797117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 34807117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 2, target, level, 34817117f1b4Smrg internalFormat, width, height, 1, border, imageSize); 34827117f1b4Smrg if (!error) { 34837117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 34847117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 34857117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 34867117f1b4Smrg width, height, 1, border); 34877117f1b4Smrg } 34887117f1b4Smrg if (error) { 34897117f1b4Smrg /* if error, clear all proxy texture image parameters */ 34907117f1b4Smrg struct gl_texture_image *texImage; 34917117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 34927117f1b4Smrg if (texImage) 34937117f1b4Smrg clear_teximage_fields(texImage); 34947117f1b4Smrg } 34957117f1b4Smrg else { 34967117f1b4Smrg /* store the teximage parameters */ 34977117f1b4Smrg struct gl_texture_object *texObj; 34987117f1b4Smrg struct gl_texture_image *texImage; 34994a49301eSmrg 35004a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 35017117f1b4Smrg 35027117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35037117f1b4Smrg { 35047117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 35057117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 35067117f1b4Smrg border, internalFormat); 35077117f1b4Smrg } 35087117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35097117f1b4Smrg } 35107117f1b4Smrg } 35117117f1b4Smrg else { 35127117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 35137117f1b4Smrg return; 35147117f1b4Smrg } 35157117f1b4Smrg} 35167117f1b4Smrg 35177117f1b4Smrg 35187117f1b4Smrgvoid GLAPIENTRY 35197117f1b4Smrg_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 35207117f1b4Smrg GLenum internalFormat, GLsizei width, 35217117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 35227117f1b4Smrg GLsizei imageSize, const GLvoid *data) 35237117f1b4Smrg{ 35247117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35257117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 35267117f1b4Smrg 35274a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 35284a49301eSmrg _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n", 35294a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 35304a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 35314a49301eSmrg width, height, depth, border, imageSize, data); 35324a49301eSmrg 35337117f1b4Smrg if (target == GL_TEXTURE_3D) { 35347117f1b4Smrg /* non-proxy target */ 35357117f1b4Smrg struct gl_texture_object *texObj; 35367117f1b4Smrg struct gl_texture_image *texImage; 35377117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 35387117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 35397117f1b4Smrg if (error) { 35407117f1b4Smrg _mesa_error(ctx, error, "glCompressedTexImage3D"); 35417117f1b4Smrg return; 35427117f1b4Smrg } 35437117f1b4Smrg 35444a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 35454a49301eSmrg 35467117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35477117f1b4Smrg { 35487117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 35497117f1b4Smrg if (!texImage) { 35507117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 35517117f1b4Smrg } 35524a49301eSmrg else { 35534a49301eSmrg if (texImage->Data) { 35544a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 35554a49301eSmrg } 35564a49301eSmrg ASSERT(texImage->Data == NULL); 35574a49301eSmrg 35584a49301eSmrg _mesa_init_teximage_fields(ctx, target, texImage, 35594a49301eSmrg width, height, depth, 35604a49301eSmrg border, internalFormat); 35614a49301eSmrg 35624a49301eSmrg /* Choose actual texture format */ 35634a49301eSmrg texImage->TexFormat = 35644a49301eSmrg ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 35654a49301eSmrg GL_NONE, GL_NONE); 35664a49301eSmrg ASSERT(texImage->TexFormat != MESA_FORMAT_NONE); 35674a49301eSmrg 35684a49301eSmrg ASSERT(ctx->Driver.CompressedTexImage3D); 35694a49301eSmrg ctx->Driver.CompressedTexImage3D(ctx, target, level, 35704a49301eSmrg internalFormat, 35714a49301eSmrg width, height, depth, 35724a49301eSmrg border, imageSize, data, 35734a49301eSmrg texObj, texImage); 35744a49301eSmrg 35754a49301eSmrg _mesa_set_fetch_functions(texImage, 3); 35764a49301eSmrg 35774a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 35784a49301eSmrg 35794a49301eSmrg /* state update */ 35804a49301eSmrg texObj->_Complete = GL_FALSE; 35814a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 35824a49301eSmrg } 35834a49301eSmrg } 35847117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35857117f1b4Smrg } 35867117f1b4Smrg else if (target == GL_PROXY_TEXTURE_3D) { 35877117f1b4Smrg /* Proxy texture: check for errors and update proxy state */ 35887117f1b4Smrg GLenum error = compressed_texture_error_check(ctx, 3, target, level, 35897117f1b4Smrg internalFormat, width, height, depth, border, imageSize); 35907117f1b4Smrg if (!error) { 35917117f1b4Smrg ASSERT(ctx->Driver.TestProxyTexImage); 35927117f1b4Smrg error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 35937117f1b4Smrg internalFormat, GL_NONE, GL_NONE, 35947117f1b4Smrg width, height, depth, border); 35957117f1b4Smrg } 35967117f1b4Smrg if (error) { 35977117f1b4Smrg /* if error, clear all proxy texture image parameters */ 35987117f1b4Smrg struct gl_texture_image *texImage; 35997117f1b4Smrg texImage = _mesa_get_proxy_tex_image(ctx, target, level); 36007117f1b4Smrg if (texImage) 36017117f1b4Smrg clear_teximage_fields(texImage); 36027117f1b4Smrg } 36037117f1b4Smrg else { 36047117f1b4Smrg /* store the teximage parameters */ 36057117f1b4Smrg struct gl_texture_object *texObj; 36067117f1b4Smrg struct gl_texture_image *texImage; 36074a49301eSmrg 36084a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 36094a49301eSmrg 36107117f1b4Smrg _mesa_lock_texture(ctx, texObj); 36117117f1b4Smrg { 36127117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 36137117f1b4Smrg _mesa_init_teximage_fields(ctx, target, texImage, width, height, 36147117f1b4Smrg depth, border, internalFormat); 36157117f1b4Smrg } 36167117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36177117f1b4Smrg } 36187117f1b4Smrg } 36197117f1b4Smrg else { 36207117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 36217117f1b4Smrg return; 36227117f1b4Smrg } 36237117f1b4Smrg} 36247117f1b4Smrg 36257117f1b4Smrg 36264a49301eSmrg/** 36274a49301eSmrg * Common helper for glCompressedTexSubImage1/2/3D(). 36284a49301eSmrg */ 36294a49301eSmrgstatic void 36304a49301eSmrgcompressed_tex_sub_image(GLuint dims, GLenum target, GLint level, 36314a49301eSmrg GLint xoffset, GLint yoffset, GLint zoffset, 36324a49301eSmrg GLsizei width, GLsizei height, GLsizei depth, 36334a49301eSmrg GLenum format, GLsizei imageSize, const GLvoid *data) 36347117f1b4Smrg{ 36357117f1b4Smrg struct gl_texture_object *texObj; 36367117f1b4Smrg struct gl_texture_image *texImage; 36377117f1b4Smrg GLenum error; 36387117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 36397117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 36407117f1b4Smrg 36414a49301eSmrg error = compressed_subtexture_error_check(ctx, dims, target, level, 36427117f1b4Smrg xoffset, 0, 0, /* pos */ 36434a49301eSmrg width, height, depth, /* size */ 36447117f1b4Smrg format, imageSize); 36457117f1b4Smrg if (error) { 36464a49301eSmrg _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims); 36477117f1b4Smrg return; 36487117f1b4Smrg } 36497117f1b4Smrg 36504a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 36514a49301eSmrg 36527117f1b4Smrg _mesa_lock_texture(ctx, texObj); 36537117f1b4Smrg { 36547117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 36557117f1b4Smrg assert(texImage); 36567117f1b4Smrg 36574a49301eSmrg if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, 36584a49301eSmrg format, texImage)) { 36594a49301eSmrg /* error was recorded */ 36604a49301eSmrg } 36614a49301eSmrg else if (width > 0 && height > 0 && depth > 0) { 36624a49301eSmrg switch (dims) { 36634a49301eSmrg case 1: 36644a49301eSmrg if (ctx->Driver.CompressedTexSubImage1D) { 36654a49301eSmrg ctx->Driver.CompressedTexSubImage1D(ctx, target, level, 36664a49301eSmrg xoffset, width, 36674a49301eSmrg format, imageSize, data, 36684a49301eSmrg texObj, texImage); 36694a49301eSmrg } 36704a49301eSmrg break; 36714a49301eSmrg case 2: 36724a49301eSmrg if (ctx->Driver.CompressedTexSubImage2D) { 36734a49301eSmrg ctx->Driver.CompressedTexSubImage2D(ctx, target, level, 36744a49301eSmrg xoffset, yoffset, 36754a49301eSmrg width, height, 36764a49301eSmrg format, imageSize, data, 36774a49301eSmrg texObj, texImage); 36784a49301eSmrg } 36794a49301eSmrg break; 36804a49301eSmrg case 3: 36814a49301eSmrg if (ctx->Driver.CompressedTexSubImage3D) { 36824a49301eSmrg ctx->Driver.CompressedTexSubImage3D(ctx, target, level, 36834a49301eSmrg xoffset, yoffset, zoffset, 36844a49301eSmrg width, height, depth, 36854a49301eSmrg format, imageSize, data, 36864a49301eSmrg texObj, texImage); 36874a49301eSmrg } 36884a49301eSmrg break; 36894a49301eSmrg default: 36904a49301eSmrg ; 36914a49301eSmrg } 36927117f1b4Smrg 36934a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 36947117f1b4Smrg 36954a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 36967117f1b4Smrg } 36977117f1b4Smrg } 36987117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36997117f1b4Smrg} 37007117f1b4Smrg 37017117f1b4Smrg 37024a49301eSmrgvoid GLAPIENTRY 37034a49301eSmrg_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 37044a49301eSmrg GLsizei width, GLenum format, 37054a49301eSmrg GLsizei imageSize, const GLvoid *data) 37064a49301eSmrg{ 37074a49301eSmrg compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1, 37084a49301eSmrg format, imageSize, data); 37094a49301eSmrg} 37104a49301eSmrg 37114a49301eSmrg 37127117f1b4Smrgvoid GLAPIENTRY 37137117f1b4Smrg_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 37147117f1b4Smrg GLint yoffset, GLsizei width, GLsizei height, 37157117f1b4Smrg GLenum format, GLsizei imageSize, 37167117f1b4Smrg const GLvoid *data) 37177117f1b4Smrg{ 37184a49301eSmrg compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0, 37194a49301eSmrg width, height, 1, format, imageSize, data); 37207117f1b4Smrg} 37217117f1b4Smrg 37227117f1b4Smrg 37237117f1b4Smrgvoid GLAPIENTRY 37247117f1b4Smrg_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 37257117f1b4Smrg GLint yoffset, GLint zoffset, GLsizei width, 37267117f1b4Smrg GLsizei height, GLsizei depth, GLenum format, 37277117f1b4Smrg GLsizei imageSize, const GLvoid *data) 37287117f1b4Smrg{ 37294a49301eSmrg compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset, 37304a49301eSmrg width, height, depth, format, imageSize, data); 37317117f1b4Smrg} 37327117f1b4Smrg 37337117f1b4Smrg 3734