teximage.c revision 3464ebd5
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" 364a49301eSmrg#include "enums.h" 377117f1b4Smrg#include "fbobject.h" 387117f1b4Smrg#include "framebuffer.h" 394a49301eSmrg#include "hash.h" 407117f1b4Smrg#include "image.h" 417117f1b4Smrg#include "imports.h" 427117f1b4Smrg#include "macros.h" 433464ebd5Sriastradh#include "mfeatures.h" 447117f1b4Smrg#include "state.h" 457117f1b4Smrg#include "texcompress.h" 464a49301eSmrg#include "texfetch.h" 477117f1b4Smrg#include "teximage.h" 487117f1b4Smrg#include "texstate.h" 493464ebd5Sriastradh#include "texpal.h" 507117f1b4Smrg#include "mtypes.h" 517117f1b4Smrg 527117f1b4Smrg 53c1f859d4Smrg/** 54c1f859d4Smrg * State changes which we care about for glCopyTex[Sub]Image() calls. 55c1f859d4Smrg * In particular, we care about pixel transfer state and buffer state 56c1f859d4Smrg * (such as glReadBuffer to make sure we read from the right renderbuffer). 57c1f859d4Smrg */ 583464ebd5Sriastradh#define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL) 59c1f859d4Smrg 60c1f859d4Smrg 61c1f859d4Smrg 627117f1b4Smrg/** 637117f1b4Smrg * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE 647117f1b4Smrg * elsewhere. 657117f1b4Smrg */ 667117f1b4Smrgvoid * 677117f1b4Smrg_mesa_alloc_texmemory(GLsizei bytes) 687117f1b4Smrg{ 697117f1b4Smrg return _mesa_align_malloc(bytes, 512); 707117f1b4Smrg} 717117f1b4Smrg 727117f1b4Smrg 737117f1b4Smrg/** 747117f1b4Smrg * Free texture memory allocated with _mesa_alloc_texmemory() 757117f1b4Smrg */ 767117f1b4Smrgvoid 777117f1b4Smrg_mesa_free_texmemory(void *m) 787117f1b4Smrg{ 797117f1b4Smrg _mesa_align_free(m); 807117f1b4Smrg} 817117f1b4Smrg 827117f1b4Smrg 837117f1b4Smrg/** 847117f1b4Smrg * Return the simple base format for a given internal texture format. 857117f1b4Smrg * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. 867117f1b4Smrg * 877117f1b4Smrg * \param ctx GL context. 887117f1b4Smrg * \param internalFormat the internal texture format token or 1, 2, 3, or 4. 897117f1b4Smrg * 907117f1b4Smrg * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, 917117f1b4Smrg * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. 927117f1b4Smrg * 937117f1b4Smrg * This is the format which is used during texture application (i.e. the 947117f1b4Smrg * texture format and env mode determine the arithmetic used. 954a49301eSmrg * 964a49301eSmrg * XXX this could be static 977117f1b4Smrg */ 987117f1b4SmrgGLint 993464ebd5Sriastradh_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) 1007117f1b4Smrg{ 1017117f1b4Smrg switch (internalFormat) { 1027117f1b4Smrg case GL_ALPHA: 1037117f1b4Smrg case GL_ALPHA4: 1047117f1b4Smrg case GL_ALPHA8: 1057117f1b4Smrg case GL_ALPHA12: 1067117f1b4Smrg case GL_ALPHA16: 1077117f1b4Smrg return GL_ALPHA; 1087117f1b4Smrg case 1: 1097117f1b4Smrg case GL_LUMINANCE: 1107117f1b4Smrg case GL_LUMINANCE4: 1117117f1b4Smrg case GL_LUMINANCE8: 1127117f1b4Smrg case GL_LUMINANCE12: 1137117f1b4Smrg case GL_LUMINANCE16: 1147117f1b4Smrg return GL_LUMINANCE; 1157117f1b4Smrg case 2: 1167117f1b4Smrg case GL_LUMINANCE_ALPHA: 1177117f1b4Smrg case GL_LUMINANCE4_ALPHA4: 1187117f1b4Smrg case GL_LUMINANCE6_ALPHA2: 1197117f1b4Smrg case GL_LUMINANCE8_ALPHA8: 1207117f1b4Smrg case GL_LUMINANCE12_ALPHA4: 1217117f1b4Smrg case GL_LUMINANCE12_ALPHA12: 1227117f1b4Smrg case GL_LUMINANCE16_ALPHA16: 1237117f1b4Smrg return GL_LUMINANCE_ALPHA; 1247117f1b4Smrg case GL_INTENSITY: 1257117f1b4Smrg case GL_INTENSITY4: 1267117f1b4Smrg case GL_INTENSITY8: 1277117f1b4Smrg case GL_INTENSITY12: 1287117f1b4Smrg case GL_INTENSITY16: 1297117f1b4Smrg return GL_INTENSITY; 1307117f1b4Smrg case 3: 1317117f1b4Smrg case GL_RGB: 1327117f1b4Smrg case GL_R3_G3_B2: 1337117f1b4Smrg case GL_RGB4: 1347117f1b4Smrg case GL_RGB5: 1357117f1b4Smrg case GL_RGB8: 1367117f1b4Smrg case GL_RGB10: 1377117f1b4Smrg case GL_RGB12: 1387117f1b4Smrg case GL_RGB16: 1397117f1b4Smrg return GL_RGB; 1407117f1b4Smrg case 4: 1417117f1b4Smrg case GL_RGBA: 1427117f1b4Smrg case GL_RGBA2: 1437117f1b4Smrg case GL_RGBA4: 1447117f1b4Smrg case GL_RGB5_A1: 1457117f1b4Smrg case GL_RGBA8: 1467117f1b4Smrg case GL_RGB10_A2: 1477117f1b4Smrg case GL_RGBA12: 1487117f1b4Smrg case GL_RGBA16: 1497117f1b4Smrg return GL_RGBA; 1507117f1b4Smrg default: 1517117f1b4Smrg ; /* fallthrough */ 1527117f1b4Smrg } 1537117f1b4Smrg 1543464ebd5Sriastradh if (ctx->Extensions.EXT_texture_format_BGRA8888) { 1553464ebd5Sriastradh switch (internalFormat) { 1563464ebd5Sriastradh case GL_BGRA_EXT: 1573464ebd5Sriastradh return GL_RGBA; 1583464ebd5Sriastradh default: 1593464ebd5Sriastradh ; /* fallthrough */ 1603464ebd5Sriastradh } 1613464ebd5Sriastradh } 1623464ebd5Sriastradh 1637117f1b4Smrg if (ctx->Extensions.EXT_paletted_texture) { 1647117f1b4Smrg switch (internalFormat) { 1657117f1b4Smrg case GL_COLOR_INDEX: 1667117f1b4Smrg case GL_COLOR_INDEX1_EXT: 1677117f1b4Smrg case GL_COLOR_INDEX2_EXT: 1687117f1b4Smrg case GL_COLOR_INDEX4_EXT: 1697117f1b4Smrg case GL_COLOR_INDEX8_EXT: 1707117f1b4Smrg case GL_COLOR_INDEX12_EXT: 1717117f1b4Smrg case GL_COLOR_INDEX16_EXT: 1727117f1b4Smrg return GL_COLOR_INDEX; 1737117f1b4Smrg default: 1747117f1b4Smrg ; /* fallthrough */ 1757117f1b4Smrg } 1767117f1b4Smrg } 1777117f1b4Smrg 178c1f859d4Smrg if (ctx->Extensions.ARB_depth_texture) { 1797117f1b4Smrg switch (internalFormat) { 1807117f1b4Smrg case GL_DEPTH_COMPONENT: 181c1f859d4Smrg case GL_DEPTH_COMPONENT16: 182c1f859d4Smrg case GL_DEPTH_COMPONENT24: 183c1f859d4Smrg case GL_DEPTH_COMPONENT32: 1847117f1b4Smrg return GL_DEPTH_COMPONENT; 1857117f1b4Smrg default: 1867117f1b4Smrg ; /* fallthrough */ 1877117f1b4Smrg } 1887117f1b4Smrg } 1897117f1b4Smrg 1904a49301eSmrg switch (internalFormat) { 1914a49301eSmrg case GL_COMPRESSED_ALPHA: 1924a49301eSmrg return GL_ALPHA; 1934a49301eSmrg case GL_COMPRESSED_LUMINANCE: 1944a49301eSmrg return GL_LUMINANCE; 1954a49301eSmrg case GL_COMPRESSED_LUMINANCE_ALPHA: 1964a49301eSmrg return GL_LUMINANCE_ALPHA; 1974a49301eSmrg case GL_COMPRESSED_INTENSITY: 1984a49301eSmrg return GL_INTENSITY; 1994a49301eSmrg case GL_COMPRESSED_RGB: 2004a49301eSmrg return GL_RGB; 2014a49301eSmrg case GL_COMPRESSED_RGBA: 2024a49301eSmrg return GL_RGBA; 2034a49301eSmrg default: 2044a49301eSmrg ; /* fallthrough */ 2057117f1b4Smrg } 2067117f1b4Smrg 2077117f1b4Smrg if (ctx->Extensions.TDFX_texture_compression_FXT1) { 2087117f1b4Smrg switch (internalFormat) { 2097117f1b4Smrg case GL_COMPRESSED_RGB_FXT1_3DFX: 2107117f1b4Smrg return GL_RGB; 2117117f1b4Smrg case GL_COMPRESSED_RGBA_FXT1_3DFX: 2127117f1b4Smrg return GL_RGBA; 2137117f1b4Smrg default: 2147117f1b4Smrg ; /* fallthrough */ 2157117f1b4Smrg } 2167117f1b4Smrg } 2177117f1b4Smrg 2187117f1b4Smrg if (ctx->Extensions.EXT_texture_compression_s3tc) { 2197117f1b4Smrg switch (internalFormat) { 2207117f1b4Smrg case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 2217117f1b4Smrg return GL_RGB; 2227117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 2237117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 2247117f1b4Smrg case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 2257117f1b4Smrg return GL_RGBA; 2267117f1b4Smrg default: 2277117f1b4Smrg ; /* fallthrough */ 2287117f1b4Smrg } 2297117f1b4Smrg } 2307117f1b4Smrg 2317117f1b4Smrg if (ctx->Extensions.S3_s3tc) { 2327117f1b4Smrg switch (internalFormat) { 2337117f1b4Smrg case GL_RGB_S3TC: 2347117f1b4Smrg case GL_RGB4_S3TC: 2357117f1b4Smrg return GL_RGB; 2367117f1b4Smrg case GL_RGBA_S3TC: 2377117f1b4Smrg case GL_RGBA4_S3TC: 2387117f1b4Smrg return GL_RGBA; 2397117f1b4Smrg default: 2407117f1b4Smrg ; /* fallthrough */ 2417117f1b4Smrg } 2427117f1b4Smrg } 2437117f1b4Smrg 2447117f1b4Smrg if (ctx->Extensions.MESA_ycbcr_texture) { 2457117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) 2467117f1b4Smrg return GL_YCBCR_MESA; 2477117f1b4Smrg } 2487117f1b4Smrg 2497117f1b4Smrg if (ctx->Extensions.ARB_texture_float) { 2507117f1b4Smrg switch (internalFormat) { 2517117f1b4Smrg case GL_ALPHA16F_ARB: 2527117f1b4Smrg case GL_ALPHA32F_ARB: 2537117f1b4Smrg return GL_ALPHA; 2547117f1b4Smrg case GL_RGBA16F_ARB: 2557117f1b4Smrg case GL_RGBA32F_ARB: 2567117f1b4Smrg return GL_RGBA; 2577117f1b4Smrg case GL_RGB16F_ARB: 2587117f1b4Smrg case GL_RGB32F_ARB: 2597117f1b4Smrg return GL_RGB; 2607117f1b4Smrg case GL_INTENSITY16F_ARB: 2617117f1b4Smrg case GL_INTENSITY32F_ARB: 2627117f1b4Smrg return GL_INTENSITY; 2637117f1b4Smrg case GL_LUMINANCE16F_ARB: 2647117f1b4Smrg case GL_LUMINANCE32F_ARB: 2657117f1b4Smrg return GL_LUMINANCE; 2667117f1b4Smrg case GL_LUMINANCE_ALPHA16F_ARB: 2677117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 2687117f1b4Smrg return GL_LUMINANCE_ALPHA; 2697117f1b4Smrg default: 2707117f1b4Smrg ; /* fallthrough */ 2717117f1b4Smrg } 2727117f1b4Smrg } 2737117f1b4Smrg 2744a49301eSmrg if (ctx->Extensions.ATI_envmap_bumpmap) { 2754a49301eSmrg switch (internalFormat) { 2764a49301eSmrg case GL_DUDV_ATI: 2774a49301eSmrg case GL_DU8DV8_ATI: 2784a49301eSmrg return GL_DUDV_ATI; 2794a49301eSmrg default: 2804a49301eSmrg ; /* fallthrough */ 2814a49301eSmrg } 2824a49301eSmrg } 2834a49301eSmrg 2843464ebd5Sriastradh if (ctx->Extensions.EXT_texture_snorm) { 2854a49301eSmrg switch (internalFormat) { 2863464ebd5Sriastradh case GL_RED_SNORM: 2873464ebd5Sriastradh case GL_R8_SNORM: 2883464ebd5Sriastradh case GL_R16_SNORM: 2893464ebd5Sriastradh return GL_RED; 2903464ebd5Sriastradh case GL_RG_SNORM: 2913464ebd5Sriastradh case GL_RG8_SNORM: 2923464ebd5Sriastradh case GL_RG16_SNORM: 2933464ebd5Sriastradh return GL_RG; 2943464ebd5Sriastradh case GL_RGB_SNORM: 2953464ebd5Sriastradh case GL_RGB8_SNORM: 2963464ebd5Sriastradh case GL_RGB16_SNORM: 2973464ebd5Sriastradh return GL_RGB; 2984a49301eSmrg case GL_RGBA_SNORM: 2994a49301eSmrg case GL_RGBA8_SNORM: 3003464ebd5Sriastradh case GL_RGBA16_SNORM: 3014a49301eSmrg return GL_RGBA; 3023464ebd5Sriastradh case GL_ALPHA_SNORM: 3033464ebd5Sriastradh case GL_ALPHA8_SNORM: 3043464ebd5Sriastradh case GL_ALPHA16_SNORM: 3053464ebd5Sriastradh return GL_ALPHA; 3063464ebd5Sriastradh case GL_LUMINANCE_SNORM: 3073464ebd5Sriastradh case GL_LUMINANCE8_SNORM: 3083464ebd5Sriastradh case GL_LUMINANCE16_SNORM: 3093464ebd5Sriastradh return GL_LUMINANCE; 3103464ebd5Sriastradh case GL_LUMINANCE_ALPHA_SNORM: 3113464ebd5Sriastradh case GL_LUMINANCE8_ALPHA8_SNORM: 3123464ebd5Sriastradh case GL_LUMINANCE16_ALPHA16_SNORM: 3133464ebd5Sriastradh return GL_LUMINANCE_ALPHA; 3143464ebd5Sriastradh case GL_INTENSITY_SNORM: 3153464ebd5Sriastradh case GL_INTENSITY8_SNORM: 3163464ebd5Sriastradh case GL_INTENSITY16_SNORM: 3173464ebd5Sriastradh return GL_INTENSITY; 3184a49301eSmrg default: 3194a49301eSmrg ; /* fallthrough */ 3204a49301eSmrg } 3214a49301eSmrg } 3224a49301eSmrg 3237117f1b4Smrg if (ctx->Extensions.EXT_packed_depth_stencil) { 3247117f1b4Smrg switch (internalFormat) { 3257117f1b4Smrg case GL_DEPTH_STENCIL_EXT: 3267117f1b4Smrg case GL_DEPTH24_STENCIL8_EXT: 3277117f1b4Smrg return GL_DEPTH_STENCIL_EXT; 3287117f1b4Smrg default: 3297117f1b4Smrg ; /* fallthrough */ 3307117f1b4Smrg } 3317117f1b4Smrg } 3327117f1b4Smrg 3337117f1b4Smrg#if FEATURE_EXT_texture_sRGB 3347117f1b4Smrg if (ctx->Extensions.EXT_texture_sRGB) { 3357117f1b4Smrg switch (internalFormat) { 3367117f1b4Smrg case GL_SRGB_EXT: 3377117f1b4Smrg case GL_SRGB8_EXT: 3387117f1b4Smrg case GL_COMPRESSED_SRGB_EXT: 3397117f1b4Smrg case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 3407117f1b4Smrg return GL_RGB; 3417117f1b4Smrg case GL_SRGB_ALPHA_EXT: 3427117f1b4Smrg case GL_SRGB8_ALPHA8_EXT: 3437117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_EXT: 3447117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 3457117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 3467117f1b4Smrg case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 3477117f1b4Smrg return GL_RGBA; 3487117f1b4Smrg case GL_SLUMINANCE_ALPHA_EXT: 3497117f1b4Smrg case GL_SLUMINANCE8_ALPHA8_EXT: 3507117f1b4Smrg case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 3517117f1b4Smrg return GL_LUMINANCE_ALPHA; 3527117f1b4Smrg case GL_SLUMINANCE_EXT: 3537117f1b4Smrg case GL_SLUMINANCE8_EXT: 3543464ebd5Sriastradh case GL_COMPRESSED_SLUMINANCE_EXT: 3557117f1b4Smrg return GL_LUMINANCE; 3567117f1b4Smrg default: 3573464ebd5Sriastradh ; /* fallthrough */ 3587117f1b4Smrg } 3597117f1b4Smrg } 3607117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */ 3617117f1b4Smrg 3623464ebd5Sriastradh if (ctx->Extensions.EXT_texture_integer) { 3633464ebd5Sriastradh switch (internalFormat) { 3643464ebd5Sriastradh case GL_RGBA8UI_EXT: 3653464ebd5Sriastradh case GL_RGBA16UI_EXT: 3663464ebd5Sriastradh case GL_RGBA32UI_EXT: 3673464ebd5Sriastradh case GL_RGBA8I_EXT: 3683464ebd5Sriastradh case GL_RGBA16I_EXT: 3693464ebd5Sriastradh case GL_RGBA32I_EXT: 3703464ebd5Sriastradh return GL_RGBA; 3713464ebd5Sriastradh case GL_RGB8UI_EXT: 3723464ebd5Sriastradh case GL_RGB16UI_EXT: 3733464ebd5Sriastradh case GL_RGB32UI_EXT: 3743464ebd5Sriastradh case GL_RGB8I_EXT: 3753464ebd5Sriastradh case GL_RGB16I_EXT: 3763464ebd5Sriastradh case GL_RGB32I_EXT: 3773464ebd5Sriastradh return GL_RGB; 3783464ebd5Sriastradh case GL_ALPHA8UI_EXT: 3793464ebd5Sriastradh case GL_ALPHA16UI_EXT: 3803464ebd5Sriastradh case GL_ALPHA32UI_EXT: 3813464ebd5Sriastradh case GL_ALPHA8I_EXT: 3823464ebd5Sriastradh case GL_ALPHA16I_EXT: 3833464ebd5Sriastradh case GL_ALPHA32I_EXT: 3843464ebd5Sriastradh return GL_ALPHA; 3853464ebd5Sriastradh case GL_INTENSITY8UI_EXT: 3863464ebd5Sriastradh case GL_INTENSITY16UI_EXT: 3873464ebd5Sriastradh case GL_INTENSITY32UI_EXT: 3883464ebd5Sriastradh case GL_INTENSITY8I_EXT: 3893464ebd5Sriastradh case GL_INTENSITY16I_EXT: 3903464ebd5Sriastradh case GL_INTENSITY32I_EXT: 3913464ebd5Sriastradh return GL_INTENSITY; 3923464ebd5Sriastradh case GL_LUMINANCE8UI_EXT: 3933464ebd5Sriastradh case GL_LUMINANCE16UI_EXT: 3943464ebd5Sriastradh case GL_LUMINANCE32UI_EXT: 3953464ebd5Sriastradh case GL_LUMINANCE8I_EXT: 3963464ebd5Sriastradh case GL_LUMINANCE16I_EXT: 3973464ebd5Sriastradh case GL_LUMINANCE32I_EXT: 3983464ebd5Sriastradh return GL_LUMINANCE; 3993464ebd5Sriastradh case GL_LUMINANCE_ALPHA8UI_EXT: 4003464ebd5Sriastradh case GL_LUMINANCE_ALPHA16UI_EXT: 4013464ebd5Sriastradh case GL_LUMINANCE_ALPHA32UI_EXT: 4023464ebd5Sriastradh case GL_LUMINANCE_ALPHA8I_EXT: 4033464ebd5Sriastradh case GL_LUMINANCE_ALPHA16I_EXT: 4043464ebd5Sriastradh case GL_LUMINANCE_ALPHA32I_EXT: 4053464ebd5Sriastradh return GL_LUMINANCE_ALPHA; 4063464ebd5Sriastradh default: 4073464ebd5Sriastradh ; /* fallthrough */ 4083464ebd5Sriastradh } 4093464ebd5Sriastradh } 4107117f1b4Smrg 4113464ebd5Sriastradh if (ctx->Extensions.ARB_texture_rg) { 4123464ebd5Sriastradh switch (internalFormat) { 4133464ebd5Sriastradh case GL_R16F: 4143464ebd5Sriastradh /* R16F depends on both ARB_half_float_pixel and ARB_texture_float. 4153464ebd5Sriastradh */ 4163464ebd5Sriastradh if (!ctx->Extensions.ARB_half_float_pixel) 4173464ebd5Sriastradh break; 4183464ebd5Sriastradh /* FALLTHROUGH */ 4193464ebd5Sriastradh case GL_R32F: 4203464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_float) 4213464ebd5Sriastradh break; 4223464ebd5Sriastradh return GL_RED; 4233464ebd5Sriastradh case GL_R8I: 4243464ebd5Sriastradh case GL_R8UI: 4253464ebd5Sriastradh case GL_R16I: 4263464ebd5Sriastradh case GL_R16UI: 4273464ebd5Sriastradh case GL_R32I: 4283464ebd5Sriastradh case GL_R32UI: 4293464ebd5Sriastradh if (!ctx->Extensions.EXT_texture_integer) 4303464ebd5Sriastradh break; 4313464ebd5Sriastradh /* FALLTHROUGH */ 4323464ebd5Sriastradh case GL_R8: 4333464ebd5Sriastradh case GL_R16: 4343464ebd5Sriastradh case GL_RED: 4353464ebd5Sriastradh case GL_COMPRESSED_RED: 4363464ebd5Sriastradh return GL_RED; 4373464ebd5Sriastradh 4383464ebd5Sriastradh case GL_RG16F: 4393464ebd5Sriastradh /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float. 4403464ebd5Sriastradh */ 4413464ebd5Sriastradh if (!ctx->Extensions.ARB_half_float_pixel) 4423464ebd5Sriastradh break; 4433464ebd5Sriastradh /* FALLTHROUGH */ 4443464ebd5Sriastradh case GL_RG32F: 4453464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_float) 4463464ebd5Sriastradh break; 4473464ebd5Sriastradh return GL_RG; 4483464ebd5Sriastradh case GL_RG8I: 4493464ebd5Sriastradh case GL_RG8UI: 4503464ebd5Sriastradh case GL_RG16I: 4513464ebd5Sriastradh case GL_RG16UI: 4523464ebd5Sriastradh case GL_RG32I: 4533464ebd5Sriastradh case GL_RG32UI: 4543464ebd5Sriastradh if (!ctx->Extensions.EXT_texture_integer) 4553464ebd5Sriastradh break; 4563464ebd5Sriastradh /* FALLTHROUGH */ 4573464ebd5Sriastradh case GL_RG: 4583464ebd5Sriastradh case GL_RG8: 4593464ebd5Sriastradh case GL_RG16: 4603464ebd5Sriastradh case GL_COMPRESSED_RG: 4613464ebd5Sriastradh return GL_RG; 4623464ebd5Sriastradh default: 4633464ebd5Sriastradh ; /* fallthrough */ 4643464ebd5Sriastradh } 4653464ebd5Sriastradh } 4667117f1b4Smrg 4673464ebd5Sriastradh if (ctx->Extensions.EXT_texture_shared_exponent) { 4683464ebd5Sriastradh switch (internalFormat) { 4693464ebd5Sriastradh case GL_RGB9_E5_EXT: 4703464ebd5Sriastradh return GL_RGB; 4713464ebd5Sriastradh default: 4723464ebd5Sriastradh ; /* fallthrough */ 4733464ebd5Sriastradh } 4743464ebd5Sriastradh } 4757117f1b4Smrg 4763464ebd5Sriastradh if (ctx->Extensions.EXT_packed_float) { 4773464ebd5Sriastradh switch (internalFormat) { 4783464ebd5Sriastradh case GL_R11F_G11F_B10F_EXT: 4793464ebd5Sriastradh return GL_RGB; 4803464ebd5Sriastradh default: 4813464ebd5Sriastradh ; /* fallthrough */ 4827117f1b4Smrg } 4837117f1b4Smrg } 4843464ebd5Sriastradh 4853464ebd5Sriastradh if (ctx->Extensions.ARB_depth_buffer_float) { 4863464ebd5Sriastradh switch (internalFormat) { 4873464ebd5Sriastradh case GL_DEPTH_COMPONENT32F: 4883464ebd5Sriastradh return GL_DEPTH_COMPONENT; 4893464ebd5Sriastradh case GL_DEPTH32F_STENCIL8: 4903464ebd5Sriastradh return GL_DEPTH_STENCIL; 4913464ebd5Sriastradh default: 4923464ebd5Sriastradh ; /* fallthrough */ 4933464ebd5Sriastradh } 4943464ebd5Sriastradh } 4953464ebd5Sriastradh 4963464ebd5Sriastradh if (ctx->Extensions.ARB_texture_compression_rgtc) { 4973464ebd5Sriastradh switch (internalFormat) { 4983464ebd5Sriastradh case GL_COMPRESSED_RED_RGTC1: 4993464ebd5Sriastradh case GL_COMPRESSED_SIGNED_RED_RGTC1: 5003464ebd5Sriastradh return GL_RED; 5013464ebd5Sriastradh case GL_COMPRESSED_RG_RGTC2: 5023464ebd5Sriastradh case GL_COMPRESSED_SIGNED_RG_RGTC2: 5033464ebd5Sriastradh return GL_RG; 5043464ebd5Sriastradh default: 5053464ebd5Sriastradh ; /* fallthrough */ 5063464ebd5Sriastradh } 5073464ebd5Sriastradh } 5083464ebd5Sriastradh 5093464ebd5Sriastradh if (ctx->Extensions.EXT_texture_compression_latc) { 5103464ebd5Sriastradh switch (internalFormat) { 5113464ebd5Sriastradh case GL_COMPRESSED_LUMINANCE_LATC1_EXT: 5123464ebd5Sriastradh case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: 5133464ebd5Sriastradh return GL_LUMINANCE; 5143464ebd5Sriastradh case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: 5153464ebd5Sriastradh case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: 5163464ebd5Sriastradh return GL_LUMINANCE_ALPHA; 5173464ebd5Sriastradh default: 5183464ebd5Sriastradh ; /* fallthrough */ 5193464ebd5Sriastradh } 5203464ebd5Sriastradh } 5213464ebd5Sriastradh 5223464ebd5Sriastradh if (ctx->Extensions.ATI_texture_compression_3dc) { 5233464ebd5Sriastradh switch (internalFormat) { 5243464ebd5Sriastradh case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: 5253464ebd5Sriastradh return GL_LUMINANCE_ALPHA; 5263464ebd5Sriastradh default: 5273464ebd5Sriastradh ; /* fallthrough */ 5283464ebd5Sriastradh } 5293464ebd5Sriastradh } 5303464ebd5Sriastradh 5313464ebd5Sriastradh if (ctx->API == API_OPENGLES) { 5323464ebd5Sriastradh switch (internalFormat) { 5333464ebd5Sriastradh case GL_PALETTE4_RGB8_OES: 5343464ebd5Sriastradh case GL_PALETTE4_R5_G6_B5_OES: 5353464ebd5Sriastradh case GL_PALETTE8_RGB8_OES: 5363464ebd5Sriastradh case GL_PALETTE8_R5_G6_B5_OES: 5373464ebd5Sriastradh return GL_RGB; 5383464ebd5Sriastradh case GL_PALETTE4_RGBA8_OES: 5393464ebd5Sriastradh case GL_PALETTE8_RGB5_A1_OES: 5403464ebd5Sriastradh case GL_PALETTE4_RGBA4_OES: 5413464ebd5Sriastradh case GL_PALETTE4_RGB5_A1_OES: 5423464ebd5Sriastradh case GL_PALETTE8_RGBA8_OES: 5433464ebd5Sriastradh case GL_PALETTE8_RGBA4_OES: 5443464ebd5Sriastradh return GL_RGBA; 5453464ebd5Sriastradh default: 5463464ebd5Sriastradh ; /* fallthrough */ 5473464ebd5Sriastradh } 5483464ebd5Sriastradh } 5493464ebd5Sriastradh 5503464ebd5Sriastradh return -1; /* error */ 5517117f1b4Smrg} 5527117f1b4Smrg 5537117f1b4Smrg 554c1f859d4Smrg/** 555c1f859d4Smrg * For cube map faces, return a face index in [0,5]. 556c1f859d4Smrg * For other targets return 0; 557c1f859d4Smrg */ 558c1f859d4SmrgGLuint 559c1f859d4Smrg_mesa_tex_target_to_face(GLenum target) 5607117f1b4Smrg{ 5617117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 5627117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 5637117f1b4Smrg return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 5647117f1b4Smrg else 5657117f1b4Smrg return 0; 5667117f1b4Smrg} 5677117f1b4Smrg 5687117f1b4Smrg 5697117f1b4Smrg 5707117f1b4Smrg/** 5717117f1b4Smrg * Store a gl_texture_image pointer in a gl_texture_object structure 5727117f1b4Smrg * according to the target and level parameters. 5737117f1b4Smrg * 5747117f1b4Smrg * \param tObj texture object. 5757117f1b4Smrg * \param target texture target. 5767117f1b4Smrg * \param level image level. 5777117f1b4Smrg * \param texImage texture image. 5787117f1b4Smrg * 5797117f1b4Smrg * This was basically prompted by the introduction of cube maps. 5807117f1b4Smrg */ 5817117f1b4Smrgvoid 5827117f1b4Smrg_mesa_set_tex_image(struct gl_texture_object *tObj, 5837117f1b4Smrg GLenum target, GLint level, 5847117f1b4Smrg struct gl_texture_image *texImage) 5857117f1b4Smrg{ 5864a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 5874a49301eSmrg 5887117f1b4Smrg ASSERT(tObj); 5897117f1b4Smrg ASSERT(texImage); 5904a49301eSmrg ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0); 5914a49301eSmrg 5924a49301eSmrg tObj->Image[face][level] = texImage; 5934a49301eSmrg 5947117f1b4Smrg /* Set the 'back' pointer */ 5957117f1b4Smrg texImage->TexObject = tObj; 5967117f1b4Smrg} 5977117f1b4Smrg 5987117f1b4Smrg 5997117f1b4Smrg/** 6007117f1b4Smrg * Allocate a texture image structure. 6017117f1b4Smrg * 6027117f1b4Smrg * Called via ctx->Driver.NewTextureImage() unless overriden by a device 6037117f1b4Smrg * driver. 6047117f1b4Smrg * 6057117f1b4Smrg * \return a pointer to gl_texture_image struct with all fields initialized to 6067117f1b4Smrg * zero. 6077117f1b4Smrg */ 6087117f1b4Smrgstruct gl_texture_image * 6093464ebd5Sriastradh_mesa_new_texture_image( struct gl_context *ctx ) 6107117f1b4Smrg{ 6117117f1b4Smrg (void) ctx; 6127117f1b4Smrg return CALLOC_STRUCT(gl_texture_image); 6137117f1b4Smrg} 6147117f1b4Smrg 6157117f1b4Smrg 6167117f1b4Smrg/** 6177117f1b4Smrg * Free texture image data. 6187117f1b4Smrg * This function is a fallback called via ctx->Driver.FreeTexImageData(). 6197117f1b4Smrg * 6204a49301eSmrg * \param texImage texture image. 6217117f1b4Smrg * 6227117f1b4Smrg * Free the texture image data if it's not marked as client data. 6237117f1b4Smrg */ 6247117f1b4Smrgvoid 6253464ebd5Sriastradh_mesa_free_texture_image_data(struct gl_context *ctx, 6267117f1b4Smrg struct gl_texture_image *texImage) 6277117f1b4Smrg{ 6287117f1b4Smrg (void) ctx; 6297117f1b4Smrg 6307117f1b4Smrg if (texImage->Data && !texImage->IsClientData) { 6317117f1b4Smrg /* free the old texture data */ 6327117f1b4Smrg _mesa_free_texmemory(texImage->Data); 6337117f1b4Smrg } 6347117f1b4Smrg 6357117f1b4Smrg texImage->Data = NULL; 6367117f1b4Smrg} 6377117f1b4Smrg 6387117f1b4Smrg 6397117f1b4Smrg/** 6407117f1b4Smrg * Free texture image. 6417117f1b4Smrg * 6424a49301eSmrg * \param texImage texture image. 6437117f1b4Smrg * 6447117f1b4Smrg * Free the texture image structure and the associated image data. 6457117f1b4Smrg */ 6467117f1b4Smrgvoid 6473464ebd5Sriastradh_mesa_delete_texture_image(struct gl_context *ctx, 6483464ebd5Sriastradh struct gl_texture_image *texImage) 6497117f1b4Smrg{ 6507117f1b4Smrg /* Free texImage->Data and/or any other driver-specific texture 6517117f1b4Smrg * image storage. 6527117f1b4Smrg */ 6537117f1b4Smrg ASSERT(ctx->Driver.FreeTexImageData); 6547117f1b4Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 6557117f1b4Smrg 6567117f1b4Smrg ASSERT(texImage->Data == NULL); 6577117f1b4Smrg if (texImage->ImageOffsets) 658cdc920a0Smrg free(texImage->ImageOffsets); 659cdc920a0Smrg free(texImage); 6607117f1b4Smrg} 6617117f1b4Smrg 6627117f1b4Smrg 6637117f1b4Smrg/** 6647117f1b4Smrg * Test if a target is a proxy target. 6657117f1b4Smrg * 6667117f1b4Smrg * \param target texture target. 6677117f1b4Smrg * 6687117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 6697117f1b4Smrg */ 6707117f1b4SmrgGLboolean 6717117f1b4Smrg_mesa_is_proxy_texture(GLenum target) 6727117f1b4Smrg{ 6733464ebd5Sriastradh /* NUM_TEXTURE_TARGETS should match number of terms below, 6743464ebd5Sriastradh * except there's no proxy for GL_TEXTURE_BUFFER. 6753464ebd5Sriastradh */ 6763464ebd5Sriastradh assert(NUM_TEXTURE_TARGETS == 8); 6774a49301eSmrg 6787117f1b4Smrg return (target == GL_PROXY_TEXTURE_1D || 6797117f1b4Smrg target == GL_PROXY_TEXTURE_2D || 6807117f1b4Smrg target == GL_PROXY_TEXTURE_3D || 6817117f1b4Smrg target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 682c1f859d4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV || 683c1f859d4Smrg target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 684c1f859d4Smrg target == GL_PROXY_TEXTURE_2D_ARRAY_EXT); 6857117f1b4Smrg} 6867117f1b4Smrg 6877117f1b4Smrg 6887117f1b4Smrg/** 6893464ebd5Sriastradh * Return the proxy target which corresponds to the given texture target 6903464ebd5Sriastradh */ 6913464ebd5Sriastradhstatic GLenum 6923464ebd5Sriastradhget_proxy_target(GLenum target) 6933464ebd5Sriastradh{ 6943464ebd5Sriastradh switch (target) { 6953464ebd5Sriastradh case GL_TEXTURE_1D: 6963464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 6973464ebd5Sriastradh return GL_PROXY_TEXTURE_1D; 6983464ebd5Sriastradh case GL_TEXTURE_2D: 6993464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 7003464ebd5Sriastradh return GL_PROXY_TEXTURE_2D; 7013464ebd5Sriastradh case GL_TEXTURE_3D: 7023464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 7033464ebd5Sriastradh return GL_PROXY_TEXTURE_3D; 7043464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 7053464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 7063464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 7073464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 7083464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 7093464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 7103464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_ARB: 7113464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 7123464ebd5Sriastradh return GL_PROXY_TEXTURE_CUBE_MAP_ARB; 7133464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 7143464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE_NV: 7153464ebd5Sriastradh return GL_PROXY_TEXTURE_RECTANGLE_NV; 7163464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 7173464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 7183464ebd5Sriastradh return GL_PROXY_TEXTURE_1D_ARRAY_EXT; 7193464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 7203464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 7213464ebd5Sriastradh return GL_PROXY_TEXTURE_2D_ARRAY_EXT; 7223464ebd5Sriastradh default: 7233464ebd5Sriastradh _mesa_problem(NULL, "unexpected target in get_proxy_target()"); 7243464ebd5Sriastradh return 0; 7253464ebd5Sriastradh } 7263464ebd5Sriastradh} 7273464ebd5Sriastradh 7283464ebd5Sriastradh 7293464ebd5Sriastradh/** 7303464ebd5Sriastradh * Get the texture object that corresponds to the target of the given 7313464ebd5Sriastradh * texture unit. 7327117f1b4Smrg * 7337117f1b4Smrg * \param ctx GL context. 7347117f1b4Smrg * \param texUnit texture unit. 7357117f1b4Smrg * \param target texture target. 7367117f1b4Smrg * 7377117f1b4Smrg * \return pointer to the texture object on success, or NULL on failure. 7387117f1b4Smrg * 7397117f1b4Smrg * \sa gl_texture_unit. 7407117f1b4Smrg */ 7417117f1b4Smrgstruct gl_texture_object * 7423464ebd5Sriastradh_mesa_select_tex_object(struct gl_context *ctx, 7433464ebd5Sriastradh const struct gl_texture_unit *texUnit, 7447117f1b4Smrg GLenum target) 7457117f1b4Smrg{ 7463464ebd5Sriastradh const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array || 7473464ebd5Sriastradh ctx->Extensions.EXT_texture_array); 7483464ebd5Sriastradh 7497117f1b4Smrg switch (target) { 7507117f1b4Smrg case GL_TEXTURE_1D: 751c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 7527117f1b4Smrg case GL_PROXY_TEXTURE_1D: 753c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 7547117f1b4Smrg case GL_TEXTURE_2D: 755c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 7567117f1b4Smrg case GL_PROXY_TEXTURE_2D: 757c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 7587117f1b4Smrg case GL_TEXTURE_3D: 759c1f859d4Smrg return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 7607117f1b4Smrg case GL_PROXY_TEXTURE_3D: 761c1f859d4Smrg return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 7627117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 7637117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 7647117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 7657117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 7667117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 7677117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 7687117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 7697117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 770c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 7717117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 7727117f1b4Smrg return ctx->Extensions.ARB_texture_cube_map 773c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 7747117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 7757117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 776c1f859d4Smrg ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 7777117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 7787117f1b4Smrg return ctx->Extensions.NV_texture_rectangle 779c1f859d4Smrg ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 780c1f859d4Smrg case GL_TEXTURE_1D_ARRAY_EXT: 7813464ebd5Sriastradh return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 782c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 7833464ebd5Sriastradh return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 784c1f859d4Smrg case GL_TEXTURE_2D_ARRAY_EXT: 7853464ebd5Sriastradh return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 786c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 7873464ebd5Sriastradh return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 7883464ebd5Sriastradh case GL_TEXTURE_BUFFER: 7893464ebd5Sriastradh return ctx->Extensions.ARB_texture_buffer_object 7903464ebd5Sriastradh ? texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL; 7917117f1b4Smrg default: 7927117f1b4Smrg _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 7937117f1b4Smrg return NULL; 7947117f1b4Smrg } 7957117f1b4Smrg} 7967117f1b4Smrg 7977117f1b4Smrg 7987117f1b4Smrg/** 7994a49301eSmrg * Return pointer to texture object for given target on current texture unit. 8004a49301eSmrg */ 8014a49301eSmrgstruct gl_texture_object * 8023464ebd5Sriastradh_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target) 8034a49301eSmrg{ 8044a49301eSmrg struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 8054a49301eSmrg return _mesa_select_tex_object(ctx, texUnit, target); 8064a49301eSmrg} 8074a49301eSmrg 8084a49301eSmrg 8094a49301eSmrg/** 8104a49301eSmrg * Get a texture image pointer from a texture object, given a texture 8114a49301eSmrg * target and mipmap level. The target and level parameters should 8124a49301eSmrg * have already been error-checked. 8137117f1b4Smrg * 8147117f1b4Smrg * \param ctx GL context. 8154a49301eSmrg * \param texObj texture unit. 8167117f1b4Smrg * \param target texture target. 8177117f1b4Smrg * \param level image level. 8187117f1b4Smrg * 8194a49301eSmrg * \return pointer to the texture image structure, or NULL on failure. 8207117f1b4Smrg */ 8217117f1b4Smrgstruct gl_texture_image * 8223464ebd5Sriastradh_mesa_select_tex_image(struct gl_context *ctx, 8233464ebd5Sriastradh const struct gl_texture_object *texObj, 8247117f1b4Smrg GLenum target, GLint level) 8257117f1b4Smrg{ 8264a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 8277117f1b4Smrg 8284a49301eSmrg ASSERT(texObj); 8294a49301eSmrg ASSERT(level >= 0); 8304a49301eSmrg ASSERT(level < MAX_TEXTURE_LEVELS); 831c1f859d4Smrg 8324a49301eSmrg return texObj->Image[face][level]; 8337117f1b4Smrg} 8347117f1b4Smrg 8357117f1b4Smrg 8367117f1b4Smrg/** 8377117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 8387117f1b4Smrg * it and install it. Only return NULL if passed a bad parameter or run 8397117f1b4Smrg * out of memory. 8407117f1b4Smrg */ 8417117f1b4Smrgstruct gl_texture_image * 8423464ebd5Sriastradh_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj, 8437117f1b4Smrg GLenum target, GLint level) 8447117f1b4Smrg{ 8457117f1b4Smrg struct gl_texture_image *texImage; 8467117f1b4Smrg 8477117f1b4Smrg if (!texObj) 8487117f1b4Smrg return NULL; 8497117f1b4Smrg 8507117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 8517117f1b4Smrg if (!texImage) { 8527117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 8537117f1b4Smrg if (!texImage) { 8547117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 8557117f1b4Smrg return NULL; 8567117f1b4Smrg } 8577117f1b4Smrg 8587117f1b4Smrg _mesa_set_tex_image(texObj, target, level, texImage); 8597117f1b4Smrg } 8607117f1b4Smrg 8617117f1b4Smrg return texImage; 8627117f1b4Smrg} 8637117f1b4Smrg 8647117f1b4Smrg 8657117f1b4Smrg/** 8667117f1b4Smrg * Return pointer to the specified proxy texture image. 8677117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit. 8687117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid 8697117f1b4Smrg * level, or out of memory. 8707117f1b4Smrg */ 8717117f1b4Smrgstruct gl_texture_image * 8723464ebd5Sriastradh_mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level) 8737117f1b4Smrg{ 8747117f1b4Smrg struct gl_texture_image *texImage; 8754a49301eSmrg GLuint texIndex; 8767117f1b4Smrg 8777117f1b4Smrg if (level < 0 ) 8787117f1b4Smrg return NULL; 8797117f1b4Smrg 8807117f1b4Smrg switch (target) { 8817117f1b4Smrg case GL_PROXY_TEXTURE_1D: 8827117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 8837117f1b4Smrg return NULL; 8844a49301eSmrg texIndex = TEXTURE_1D_INDEX; 8854a49301eSmrg break; 8867117f1b4Smrg case GL_PROXY_TEXTURE_2D: 8877117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 8887117f1b4Smrg return NULL; 8894a49301eSmrg texIndex = TEXTURE_2D_INDEX; 8904a49301eSmrg break; 8917117f1b4Smrg case GL_PROXY_TEXTURE_3D: 8927117f1b4Smrg if (level >= ctx->Const.Max3DTextureLevels) 8937117f1b4Smrg return NULL; 8944a49301eSmrg texIndex = TEXTURE_3D_INDEX; 8954a49301eSmrg break; 8967117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP: 8977117f1b4Smrg if (level >= ctx->Const.MaxCubeTextureLevels) 8987117f1b4Smrg return NULL; 8994a49301eSmrg texIndex = TEXTURE_CUBE_INDEX; 9004a49301eSmrg break; 9017117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 9027117f1b4Smrg if (level > 0) 9037117f1b4Smrg return NULL; 9044a49301eSmrg texIndex = TEXTURE_RECT_INDEX; 9054a49301eSmrg break; 906c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 907c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 908c1f859d4Smrg return NULL; 9094a49301eSmrg texIndex = TEXTURE_1D_ARRAY_INDEX; 9104a49301eSmrg break; 911c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 912c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 913c1f859d4Smrg return NULL; 9144a49301eSmrg texIndex = TEXTURE_2D_ARRAY_INDEX; 9154a49301eSmrg break; 9167117f1b4Smrg default: 9177117f1b4Smrg return NULL; 9187117f1b4Smrg } 9194a49301eSmrg 9204a49301eSmrg texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 9214a49301eSmrg if (!texImage) { 9224a49301eSmrg texImage = ctx->Driver.NewTextureImage(ctx); 9234a49301eSmrg if (!texImage) { 9244a49301eSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 9254a49301eSmrg return NULL; 9264a49301eSmrg } 9274a49301eSmrg ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 9284a49301eSmrg /* Set the 'back' pointer */ 9294a49301eSmrg texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 9304a49301eSmrg } 9314a49301eSmrg return texImage; 9327117f1b4Smrg} 9337117f1b4Smrg 9347117f1b4Smrg 9357117f1b4Smrg/** 9367117f1b4Smrg * Get the maximum number of allowed mipmap levels. 9377117f1b4Smrg * 9387117f1b4Smrg * \param ctx GL context. 9397117f1b4Smrg * \param target texture target. 9407117f1b4Smrg * 9417117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given 9427117f1b4Smrg * texture target, or zero if passed a bad target. 9437117f1b4Smrg * 9447117f1b4Smrg * \sa gl_constants. 9457117f1b4Smrg */ 9467117f1b4SmrgGLint 9473464ebd5Sriastradh_mesa_max_texture_levels(struct gl_context *ctx, GLenum target) 9487117f1b4Smrg{ 9497117f1b4Smrg switch (target) { 9507117f1b4Smrg case GL_TEXTURE_1D: 9517117f1b4Smrg case GL_PROXY_TEXTURE_1D: 9527117f1b4Smrg case GL_TEXTURE_2D: 9537117f1b4Smrg case GL_PROXY_TEXTURE_2D: 9547117f1b4Smrg return ctx->Const.MaxTextureLevels; 9557117f1b4Smrg case GL_TEXTURE_3D: 9567117f1b4Smrg case GL_PROXY_TEXTURE_3D: 9577117f1b4Smrg return ctx->Const.Max3DTextureLevels; 9587117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 9597117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 9607117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 9617117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 9627117f1b4Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 9637117f1b4Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 9647117f1b4Smrg case GL_TEXTURE_CUBE_MAP_ARB: 9657117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 9664a49301eSmrg return ctx->Extensions.ARB_texture_cube_map 9674a49301eSmrg ? ctx->Const.MaxCubeTextureLevels : 0; 9687117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 9697117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 9704a49301eSmrg return ctx->Extensions.NV_texture_rectangle ? 1 : 0; 9714a49301eSmrg case GL_TEXTURE_1D_ARRAY_EXT: 9724a49301eSmrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 9734a49301eSmrg case GL_TEXTURE_2D_ARRAY_EXT: 9744a49301eSmrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 9753464ebd5Sriastradh return (ctx->Extensions.MESA_texture_array || 9763464ebd5Sriastradh ctx->Extensions.EXT_texture_array) 9774a49301eSmrg ? ctx->Const.MaxTextureLevels : 0; 9783464ebd5Sriastradh case GL_TEXTURE_BUFFER: 9793464ebd5Sriastradh /* fall-through */ 9807117f1b4Smrg default: 9817117f1b4Smrg return 0; /* bad target */ 9827117f1b4Smrg } 9837117f1b4Smrg} 9847117f1b4Smrg 9857117f1b4Smrg 9863464ebd5Sriastradh/** 9873464ebd5Sriastradh * Return number of dimensions per mipmap level for the given texture target. 9883464ebd5Sriastradh */ 9893464ebd5SriastradhGLint 9903464ebd5Sriastradh_mesa_get_texture_dimensions(GLenum target) 9913464ebd5Sriastradh{ 9923464ebd5Sriastradh switch (target) { 9933464ebd5Sriastradh case GL_TEXTURE_1D: 9943464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 9953464ebd5Sriastradh return 1; 9963464ebd5Sriastradh case GL_TEXTURE_2D: 9973464ebd5Sriastradh case GL_TEXTURE_RECTANGLE: 9983464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP: 9993464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 10003464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE: 10013464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 10023464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 10033464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 10043464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 10053464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 10063464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 10073464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 10083464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY: 10093464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY: 10103464ebd5Sriastradh return 2; 10113464ebd5Sriastradh case GL_TEXTURE_3D: 10123464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 10133464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY: 10143464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY: 10153464ebd5Sriastradh return 3; 10163464ebd5Sriastradh case GL_TEXTURE_BUFFER: 10173464ebd5Sriastradh /* fall-through */ 10183464ebd5Sriastradh default: 10193464ebd5Sriastradh _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()", 10203464ebd5Sriastradh target); 10213464ebd5Sriastradh return 2; 10223464ebd5Sriastradh } 10233464ebd5Sriastradh} 10243464ebd5Sriastradh 10253464ebd5Sriastradh 10263464ebd5Sriastradh 10277117f1b4Smrg 10287117f1b4Smrg#if 000 /* not used anymore */ 10297117f1b4Smrg/* 10307117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer. In this case we 10317117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL 10327117f1b4Smrg * spec. 10337117f1b4Smrg */ 10347117f1b4Smrgstatic GLubyte * 10357117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format) 10367117f1b4Smrg{ 10377117f1b4Smrg const GLint components = _mesa_components_in_format(format); 10387117f1b4Smrg const GLint numPixels = width * height * depth; 10397117f1b4Smrg GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 10407117f1b4Smrg 10417117f1b4Smrg#ifdef DEBUG 10427117f1b4Smrg /* 10437117f1b4Smrg * Let's see if anyone finds this. If glTexImage2D() is called with 10447117f1b4Smrg * a NULL image pointer then load the texture image with something 10457117f1b4Smrg * interesting instead of leaving it indeterminate. 10467117f1b4Smrg */ 10477117f1b4Smrg if (data) { 10487117f1b4Smrg static const char message[8][32] = { 10497117f1b4Smrg " X X XXXXX XXX X ", 10507117f1b4Smrg " XX XX X X X X X ", 10517117f1b4Smrg " X X X X X X X ", 10527117f1b4Smrg " X X XXXX XXX XXXXX ", 10537117f1b4Smrg " X X X X X X ", 10547117f1b4Smrg " X X X X X X X ", 10557117f1b4Smrg " X X XXXXX XXX X X ", 10567117f1b4Smrg " " 10577117f1b4Smrg }; 10587117f1b4Smrg 10597117f1b4Smrg GLubyte *imgPtr = data; 10607117f1b4Smrg GLint h, i, j, k; 10617117f1b4Smrg for (h = 0; h < depth; h++) { 10627117f1b4Smrg for (i = 0; i < height; i++) { 10637117f1b4Smrg GLint srcRow = 7 - (i % 8); 10647117f1b4Smrg for (j = 0; j < width; j++) { 10657117f1b4Smrg GLint srcCol = j % 32; 10667117f1b4Smrg GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 10677117f1b4Smrg for (k = 0; k < components; k++) { 10687117f1b4Smrg *imgPtr++ = texel; 10697117f1b4Smrg } 10707117f1b4Smrg } 10717117f1b4Smrg } 10727117f1b4Smrg } 10737117f1b4Smrg } 10747117f1b4Smrg#endif 10757117f1b4Smrg 10767117f1b4Smrg return data; 10777117f1b4Smrg} 10787117f1b4Smrg#endif 10797117f1b4Smrg 10807117f1b4Smrg 10817117f1b4Smrg 10827117f1b4Smrg/** 10837117f1b4Smrg * Reset the fields of a gl_texture_image struct to zero. 10847117f1b4Smrg * 10857117f1b4Smrg * \param img texture image structure. 10867117f1b4Smrg * 10877117f1b4Smrg * This is called when a proxy texture test fails, we set all the 10887117f1b4Smrg * image members (except DriverData) to zero. 10897117f1b4Smrg * It's also used in glTexImage[123]D as a safeguard to be sure all 10907117f1b4Smrg * required fields get initialized properly by the Driver.TexImage[123]D 10917117f1b4Smrg * functions. 10927117f1b4Smrg */ 10937117f1b4Smrgstatic void 10947117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img) 10957117f1b4Smrg{ 10967117f1b4Smrg ASSERT(img); 10977117f1b4Smrg img->_BaseFormat = 0; 10987117f1b4Smrg img->InternalFormat = 0; 10997117f1b4Smrg img->Border = 0; 11007117f1b4Smrg img->Width = 0; 11017117f1b4Smrg img->Height = 0; 11027117f1b4Smrg img->Depth = 0; 11037117f1b4Smrg img->RowStride = 0; 11047117f1b4Smrg if (img->ImageOffsets) { 1105cdc920a0Smrg free(img->ImageOffsets); 11067117f1b4Smrg img->ImageOffsets = NULL; 11077117f1b4Smrg } 11087117f1b4Smrg img->Width2 = 0; 11097117f1b4Smrg img->Height2 = 0; 11107117f1b4Smrg img->Depth2 = 0; 11117117f1b4Smrg img->WidthLog2 = 0; 11127117f1b4Smrg img->HeightLog2 = 0; 11137117f1b4Smrg img->DepthLog2 = 0; 11147117f1b4Smrg img->Data = NULL; 11154a49301eSmrg img->TexFormat = MESA_FORMAT_NONE; 11167117f1b4Smrg img->FetchTexelc = NULL; 11177117f1b4Smrg img->FetchTexelf = NULL; 11187117f1b4Smrg} 11197117f1b4Smrg 11207117f1b4Smrg 11217117f1b4Smrg/** 11227117f1b4Smrg * Initialize basic fields of the gl_texture_image struct. 11237117f1b4Smrg * 11247117f1b4Smrg * \param ctx GL context. 11257117f1b4Smrg * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 11267117f1b4Smrg * \param img texture image structure to be initialized. 11277117f1b4Smrg * \param width image width. 11287117f1b4Smrg * \param height image height. 11297117f1b4Smrg * \param depth image depth. 11307117f1b4Smrg * \param border image border. 11317117f1b4Smrg * \param internalFormat internal format. 11323464ebd5Sriastradh * \param format the actual hardware format (one of MESA_FORMAT_*) 11337117f1b4Smrg * 11347117f1b4Smrg * Fills in the fields of \p img with the given information. 11357117f1b4Smrg * Note: width, height and depth include the border. 11367117f1b4Smrg */ 11377117f1b4Smrgvoid 11383464ebd5Sriastradh_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, 11397117f1b4Smrg struct gl_texture_image *img, 11407117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 11413464ebd5Sriastradh GLint border, GLenum internalFormat, 11423464ebd5Sriastradh gl_format format) 11437117f1b4Smrg{ 11443464ebd5Sriastradh GLint i, dims; 11457117f1b4Smrg 11467117f1b4Smrg ASSERT(img); 11477117f1b4Smrg ASSERT(width >= 0); 11487117f1b4Smrg ASSERT(height >= 0); 11497117f1b4Smrg ASSERT(depth >= 0); 11507117f1b4Smrg 11517117f1b4Smrg img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 11527117f1b4Smrg ASSERT(img->_BaseFormat > 0); 11537117f1b4Smrg img->InternalFormat = internalFormat; 11547117f1b4Smrg img->Border = border; 11557117f1b4Smrg img->Width = width; 11567117f1b4Smrg img->Height = height; 11577117f1b4Smrg img->Depth = depth; 11584a49301eSmrg 11597117f1b4Smrg img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 11603464ebd5Sriastradh img->WidthLog2 = _mesa_logbase2(img->Width2); 11614a49301eSmrg 11624a49301eSmrg if (height == 1) { /* 1-D texture */ 11634a49301eSmrg img->Height2 = 1; 11647117f1b4Smrg img->HeightLog2 = 0; 11654a49301eSmrg } 11664a49301eSmrg else { 11674a49301eSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 11683464ebd5Sriastradh img->HeightLog2 = _mesa_logbase2(img->Height2); 11694a49301eSmrg } 11704a49301eSmrg 11714a49301eSmrg if (depth == 1) { /* 2-D texture */ 11724a49301eSmrg img->Depth2 = 1; 11737117f1b4Smrg img->DepthLog2 = 0; 11744a49301eSmrg } 11754a49301eSmrg else { 11764a49301eSmrg img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 11773464ebd5Sriastradh img->DepthLog2 = _mesa_logbase2(img->Depth2); 11784a49301eSmrg } 11794a49301eSmrg 11807117f1b4Smrg img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 11817117f1b4Smrg 1182c1f859d4Smrg if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 1183c1f859d4Smrg (height == 1 || _mesa_is_pow_two(img->Height2)) && 1184c1f859d4Smrg (depth == 1 || _mesa_is_pow_two(img->Depth2))) 11857117f1b4Smrg img->_IsPowerOfTwo = GL_TRUE; 11867117f1b4Smrg else 11877117f1b4Smrg img->_IsPowerOfTwo = GL_FALSE; 11887117f1b4Smrg 11897117f1b4Smrg /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 11907117f1b4Smrg img->RowStride = width; 11917117f1b4Smrg /* Allocate the ImageOffsets array and initialize to typical values. 11927117f1b4Smrg * We allocate the array for 1D/2D textures too in order to avoid special- 11937117f1b4Smrg * case code in the texstore routines. 11947117f1b4Smrg */ 11954a49301eSmrg if (img->ImageOffsets) 1196cdc920a0Smrg free(img->ImageOffsets); 1197cdc920a0Smrg img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); 11987117f1b4Smrg for (i = 0; i < depth; i++) { 11997117f1b4Smrg img->ImageOffsets[i] = i * width * height; 12007117f1b4Smrg } 12017117f1b4Smrg 12027117f1b4Smrg /* Compute Width/Height/DepthScale for mipmap lod computation */ 12037117f1b4Smrg if (target == GL_TEXTURE_RECTANGLE_NV) { 12047117f1b4Smrg /* scale = 1.0 since texture coords directly map to texels */ 12057117f1b4Smrg img->WidthScale = 1.0; 12067117f1b4Smrg img->HeightScale = 1.0; 12077117f1b4Smrg img->DepthScale = 1.0; 12087117f1b4Smrg } 12097117f1b4Smrg else { 12107117f1b4Smrg img->WidthScale = (GLfloat) img->Width; 12117117f1b4Smrg img->HeightScale = (GLfloat) img->Height; 12127117f1b4Smrg img->DepthScale = (GLfloat) img->Depth; 12137117f1b4Smrg } 12144a49301eSmrg 12153464ebd5Sriastradh img->TexFormat = format; 12163464ebd5Sriastradh 12173464ebd5Sriastradh dims = _mesa_get_texture_dimensions(target); 12183464ebd5Sriastradh 12193464ebd5Sriastradh _mesa_set_fetch_functions(img, dims); 12204a49301eSmrg} 12214a49301eSmrg 12224a49301eSmrg 12234a49301eSmrg/** 12244a49301eSmrg * Free and clear fields of the gl_texture_image struct. 12254a49301eSmrg * 12264a49301eSmrg * \param ctx GL context. 12274a49301eSmrg * \param texImage texture image structure to be cleared. 12284a49301eSmrg * 12294a49301eSmrg * After the call, \p texImage will have no data associated with it. Its 12304a49301eSmrg * fields are cleared so that its parent object will test incomplete. 12314a49301eSmrg */ 12324a49301eSmrgvoid 12333464ebd5Sriastradh_mesa_clear_texture_image(struct gl_context *ctx, 12343464ebd5Sriastradh struct gl_texture_image *texImage) 12354a49301eSmrg{ 12364a49301eSmrg ctx->Driver.FreeTexImageData(ctx, texImage); 12374a49301eSmrg clear_teximage_fields(texImage); 12387117f1b4Smrg} 12397117f1b4Smrg 12407117f1b4Smrg 12417117f1b4Smrg/** 12427117f1b4Smrg * This is the fallback for Driver.TestProxyTexImage(). Test the texture 12437117f1b4Smrg * level, width, height and depth against the ctx->Const limits for textures. 12447117f1b4Smrg * 12457117f1b4Smrg * A hardware driver might override this function if, for example, the 12467117f1b4Smrg * max 3D texture size is 512x512x64 (i.e. not a cube). 12477117f1b4Smrg * 12487117f1b4Smrg * Note that width, height, depth == 0 is not an error. However, a 12497117f1b4Smrg * texture with zero width/height/depth will be considered "incomplete" 12507117f1b4Smrg * and texturing will effectively be disabled. 12517117f1b4Smrg * 12527117f1b4Smrg * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 12537117f1b4Smrg * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 12547117f1b4Smrg * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 12557117f1b4Smrg * \param level as passed to glTexImage 12567117f1b4Smrg * \param internalFormat as passed to glTexImage 12577117f1b4Smrg * \param format as passed to glTexImage 12587117f1b4Smrg * \param type as passed to glTexImage 12597117f1b4Smrg * \param width as passed to glTexImage 12607117f1b4Smrg * \param height as passed to glTexImage 12617117f1b4Smrg * \param depth as passed to glTexImage 12627117f1b4Smrg * \param border as passed to glTexImage 12637117f1b4Smrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 12647117f1b4Smrg */ 12657117f1b4SmrgGLboolean 12663464ebd5Sriastradh_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, 12677117f1b4Smrg GLint internalFormat, GLenum format, GLenum type, 12687117f1b4Smrg GLint width, GLint height, GLint depth, GLint border) 12697117f1b4Smrg{ 12707117f1b4Smrg GLint maxSize; 12717117f1b4Smrg 12727117f1b4Smrg (void) internalFormat; 12737117f1b4Smrg (void) format; 12747117f1b4Smrg (void) type; 12757117f1b4Smrg 12767117f1b4Smrg switch (target) { 12777117f1b4Smrg case GL_PROXY_TEXTURE_1D: 12787117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 12793464ebd5Sriastradh if (width < 2 * border || width > 2 + maxSize) 12803464ebd5Sriastradh return GL_FALSE; 12813464ebd5Sriastradh if (level >= ctx->Const.MaxTextureLevels) 12827117f1b4Smrg return GL_FALSE; 12833464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 12843464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 12853464ebd5Sriastradh return GL_FALSE; 12867117f1b4Smrg } 12877117f1b4Smrg return GL_TRUE; 12883464ebd5Sriastradh 12897117f1b4Smrg case GL_PROXY_TEXTURE_2D: 12907117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 12913464ebd5Sriastradh if (width < 2 * border || width > 2 + maxSize) 12923464ebd5Sriastradh return GL_FALSE; 12933464ebd5Sriastradh if (height < 2 * border || height > 2 + maxSize) 12943464ebd5Sriastradh return GL_FALSE; 12953464ebd5Sriastradh if (level >= ctx->Const.MaxTextureLevels) 12967117f1b4Smrg return GL_FALSE; 12973464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 12983464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 12993464ebd5Sriastradh return GL_FALSE; 13003464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 13013464ebd5Sriastradh return GL_FALSE; 13027117f1b4Smrg } 13037117f1b4Smrg return GL_TRUE; 13043464ebd5Sriastradh 13057117f1b4Smrg case GL_PROXY_TEXTURE_3D: 13067117f1b4Smrg maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 13073464ebd5Sriastradh if (width < 2 * border || width > 2 + maxSize) 13083464ebd5Sriastradh return GL_FALSE; 13093464ebd5Sriastradh if (height < 2 * border || height > 2 + maxSize) 13103464ebd5Sriastradh return GL_FALSE; 13113464ebd5Sriastradh if (depth < 2 * border || depth > 2 + maxSize) 13127117f1b4Smrg return GL_FALSE; 13133464ebd5Sriastradh if (level >= ctx->Const.Max3DTextureLevels) 13143464ebd5Sriastradh return GL_FALSE; 13153464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 13163464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 13173464ebd5Sriastradh return GL_FALSE; 13183464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 13193464ebd5Sriastradh return GL_FALSE; 13203464ebd5Sriastradh if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) 13213464ebd5Sriastradh return GL_FALSE; 13227117f1b4Smrg } 13237117f1b4Smrg return GL_TRUE; 13243464ebd5Sriastradh 13257117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 13263464ebd5Sriastradh maxSize = ctx->Const.MaxTextureRectSize; 13273464ebd5Sriastradh if (width < 0 || width > maxSize) 13283464ebd5Sriastradh return GL_FALSE; 13293464ebd5Sriastradh if (height < 0 || height > maxSize) 13303464ebd5Sriastradh return GL_FALSE; 13313464ebd5Sriastradh if (level != 0) 13327117f1b4Smrg return GL_FALSE; 13337117f1b4Smrg return GL_TRUE; 13343464ebd5Sriastradh 13357117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 13367117f1b4Smrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 13373464ebd5Sriastradh if (width < 2 * border || width > 2 + maxSize) 13383464ebd5Sriastradh return GL_FALSE; 13393464ebd5Sriastradh if (height < 2 * border || height > 2 + maxSize) 13407117f1b4Smrg return GL_FALSE; 13413464ebd5Sriastradh if (level >= ctx->Const.MaxCubeTextureLevels) 13423464ebd5Sriastradh return GL_FALSE; 13433464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 13443464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 13453464ebd5Sriastradh return GL_FALSE; 13463464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 13473464ebd5Sriastradh return GL_FALSE; 13487117f1b4Smrg } 13497117f1b4Smrg return GL_TRUE; 13503464ebd5Sriastradh 1351c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1352c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 13533464ebd5Sriastradh if (width < 2 * border || width > 2 + maxSize) 1354c1f859d4Smrg return GL_FALSE; 13553464ebd5Sriastradh if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) 13563464ebd5Sriastradh return GL_FALSE; 13573464ebd5Sriastradh if (level >= ctx->Const.MaxTextureLevels) 1358c1f859d4Smrg return GL_FALSE; 13593464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 13603464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 13613464ebd5Sriastradh return GL_FALSE; 1362c1f859d4Smrg } 1363c1f859d4Smrg return GL_TRUE; 13643464ebd5Sriastradh 1365c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1366c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 13673464ebd5Sriastradh if (width < 2 * border || width > 2 + maxSize) 1368c1f859d4Smrg return GL_FALSE; 13693464ebd5Sriastradh if (height < 2 * border || height > 2 + maxSize) 13703464ebd5Sriastradh return GL_FALSE; 13713464ebd5Sriastradh if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) 13723464ebd5Sriastradh return GL_FALSE; 13733464ebd5Sriastradh if (level >= ctx->Const.MaxTextureLevels) 1374c1f859d4Smrg return GL_FALSE; 13753464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 13763464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 13773464ebd5Sriastradh return GL_FALSE; 13783464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 13793464ebd5Sriastradh return GL_FALSE; 1380c1f859d4Smrg } 1381c1f859d4Smrg return GL_TRUE; 13823464ebd5Sriastradh 13837117f1b4Smrg default: 13847117f1b4Smrg _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 13857117f1b4Smrg return GL_FALSE; 13867117f1b4Smrg } 13877117f1b4Smrg} 13887117f1b4Smrg 13897117f1b4Smrg 13907117f1b4Smrg/** 13913464ebd5Sriastradh * Check if the memory used by the texture would exceed the driver's limit. 13923464ebd5Sriastradh * This lets us support a max 3D texture size of 8K (for example) but 13933464ebd5Sriastradh * prevents allocating a full 8K x 8K x 8K texture. 13943464ebd5Sriastradh * XXX this could be rolled into the proxy texture size test (above) but 13953464ebd5Sriastradh * we don't have the actual texture internal format at that point. 13967117f1b4Smrg */ 13977117f1b4Smrgstatic GLboolean 13983464ebd5Sriastradhlegal_texture_size(struct gl_context *ctx, gl_format format, 13993464ebd5Sriastradh GLint width, GLint height, GLint depth) 14007117f1b4Smrg{ 14013464ebd5Sriastradh uint64_t bytes = _mesa_format_image_size64(format, width, height, depth); 14023464ebd5Sriastradh uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */ 14033464ebd5Sriastradh return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes; 14047117f1b4Smrg} 14057117f1b4Smrg 14067117f1b4Smrg 14073464ebd5Sriastradh 14087117f1b4Smrg/** 14093464ebd5Sriastradh * Helper function to determine whether a target and specific compression 14103464ebd5Sriastradh * format are supported. 14117117f1b4Smrg */ 14127117f1b4Smrgstatic GLboolean 14133464ebd5Sriastradhtarget_can_be_compressed(const struct gl_context *ctx, GLenum target, 14143464ebd5Sriastradh GLenum intFormat) 14157117f1b4Smrg{ 14163464ebd5Sriastradh (void) intFormat; /* not used yet */ 14177117f1b4Smrg 14183464ebd5Sriastradh switch (target) { 14193464ebd5Sriastradh case GL_TEXTURE_2D: 14203464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 14213464ebd5Sriastradh return GL_TRUE; /* true for any compressed format so far */ 14223464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 14233464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 14243464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 14253464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 14263464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 14273464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 14283464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 14293464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 14303464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 14313464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 14323464ebd5Sriastradh return (ctx->Extensions.MESA_texture_array || 14333464ebd5Sriastradh ctx->Extensions.EXT_texture_array); 14343464ebd5Sriastradh default: 14353464ebd5Sriastradh return GL_FALSE; 14363464ebd5Sriastradh } 14373464ebd5Sriastradh} 14387117f1b4Smrg 14397117f1b4Smrg 14403464ebd5Sriastradh/** 14413464ebd5Sriastradh * Check if the given texture target value is legal for a 14423464ebd5Sriastradh * glTexImage1/2/3D call. 14433464ebd5Sriastradh */ 14443464ebd5Sriastradhstatic GLboolean 14453464ebd5Sriastradhlegal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) 14463464ebd5Sriastradh{ 14473464ebd5Sriastradh switch (dims) { 14483464ebd5Sriastradh case 1: 14493464ebd5Sriastradh switch (target) { 14503464ebd5Sriastradh case GL_TEXTURE_1D: 14513464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 14523464ebd5Sriastradh return GL_TRUE; 14533464ebd5Sriastradh default: 14543464ebd5Sriastradh return GL_FALSE; 14557117f1b4Smrg } 14563464ebd5Sriastradh case 2: 14573464ebd5Sriastradh switch (target) { 14583464ebd5Sriastradh case GL_TEXTURE_2D: 14593464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 14603464ebd5Sriastradh return GL_TRUE; 14613464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 14623464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 14633464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 14643464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 14653464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 14663464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 14673464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 14683464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 14693464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 14703464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE_NV: 14713464ebd5Sriastradh return ctx->Extensions.NV_texture_rectangle; 14723464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 14733464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 14743464ebd5Sriastradh return (ctx->Extensions.MESA_texture_array || 14753464ebd5Sriastradh ctx->Extensions.EXT_texture_array); 14763464ebd5Sriastradh default: 14773464ebd5Sriastradh return GL_FALSE; 14787117f1b4Smrg } 14793464ebd5Sriastradh case 3: 14803464ebd5Sriastradh switch (target) { 14813464ebd5Sriastradh case GL_TEXTURE_3D: 14823464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 14837117f1b4Smrg return GL_TRUE; 14843464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 14853464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 14863464ebd5Sriastradh return (ctx->Extensions.MESA_texture_array || 14873464ebd5Sriastradh ctx->Extensions.EXT_texture_array); 14883464ebd5Sriastradh default: 14893464ebd5Sriastradh return GL_FALSE; 14907117f1b4Smrg } 14913464ebd5Sriastradh default: 14923464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims); 14933464ebd5Sriastradh return GL_FALSE; 14947117f1b4Smrg } 14953464ebd5Sriastradh} 14963464ebd5Sriastradh 14973464ebd5Sriastradh 14983464ebd5Sriastradh/** 14993464ebd5Sriastradh * Check if the given texture target value is legal for a 15003464ebd5Sriastradh * glTexSubImage, glCopyTexSubImage or glCopyTexImage call. 15013464ebd5Sriastradh * The difference compared to legal_teximage_target() above is that 15023464ebd5Sriastradh * proxy targets are not supported. 15033464ebd5Sriastradh */ 15043464ebd5Sriastradhstatic GLboolean 15053464ebd5Sriastradhlegal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) 15063464ebd5Sriastradh{ 15073464ebd5Sriastradh switch (dims) { 15083464ebd5Sriastradh case 1: 15093464ebd5Sriastradh return target == GL_TEXTURE_1D; 15103464ebd5Sriastradh case 2: 15113464ebd5Sriastradh switch (target) { 15123464ebd5Sriastradh case GL_TEXTURE_2D: 15133464ebd5Sriastradh return GL_TRUE; 15143464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 15153464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 15163464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 15173464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 15183464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 15193464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 15203464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 15213464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 15223464ebd5Sriastradh return ctx->Extensions.NV_texture_rectangle; 15233464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 15243464ebd5Sriastradh return (ctx->Extensions.MESA_texture_array || 15253464ebd5Sriastradh ctx->Extensions.EXT_texture_array); 15263464ebd5Sriastradh default: 15273464ebd5Sriastradh return GL_FALSE; 1528c1f859d4Smrg } 15293464ebd5Sriastradh case 3: 15303464ebd5Sriastradh switch (target) { 15313464ebd5Sriastradh case GL_TEXTURE_3D: 15327117f1b4Smrg return GL_TRUE; 15333464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 15343464ebd5Sriastradh return (ctx->Extensions.MESA_texture_array || 15353464ebd5Sriastradh ctx->Extensions.EXT_texture_array); 15363464ebd5Sriastradh default: 15373464ebd5Sriastradh return GL_FALSE; 15387117f1b4Smrg } 15393464ebd5Sriastradh default: 15403464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()", 15413464ebd5Sriastradh dims); 15423464ebd5Sriastradh return GL_FALSE; 15437117f1b4Smrg } 15443464ebd5Sriastradh} 15453464ebd5Sriastradh 15463464ebd5Sriastradh 15473464ebd5Sriastradh/** 15483464ebd5Sriastradh * Test the glTexImage[123]D() parameters for errors. 15493464ebd5Sriastradh * 15503464ebd5Sriastradh * \param ctx GL context. 15513464ebd5Sriastradh * \param dimensions texture image dimensions (must be 1, 2 or 3). 15523464ebd5Sriastradh * \param target texture target given by the user. 15533464ebd5Sriastradh * \param level image level given by the user. 15543464ebd5Sriastradh * \param internalFormat internal format given by the user. 15553464ebd5Sriastradh * \param format pixel data format given by the user. 15563464ebd5Sriastradh * \param type pixel data type given by the user. 15573464ebd5Sriastradh * \param width image width given by the user. 15583464ebd5Sriastradh * \param height image height given by the user. 15593464ebd5Sriastradh * \param depth image depth given by the user. 15603464ebd5Sriastradh * \param border image border given by the user. 15613464ebd5Sriastradh * 15623464ebd5Sriastradh * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 15633464ebd5Sriastradh * 15643464ebd5Sriastradh * Verifies each of the parameters against the constants specified in 15653464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 15663464ebd5Sriastradh * to the OpenGL specification. 15673464ebd5Sriastradh */ 15683464ebd5Sriastradhstatic GLboolean 15693464ebd5Sriastradhtexture_error_check( struct gl_context *ctx, 15703464ebd5Sriastradh GLuint dimensions, GLenum target, 15713464ebd5Sriastradh GLint level, GLint internalFormat, 15723464ebd5Sriastradh GLenum format, GLenum type, 15733464ebd5Sriastradh GLint width, GLint height, 15743464ebd5Sriastradh GLint depth, GLint border ) 15753464ebd5Sriastradh{ 15763464ebd5Sriastradh const GLenum proxyTarget = get_proxy_target(target); 15773464ebd5Sriastradh const GLboolean isProxy = target == proxyTarget; 15783464ebd5Sriastradh GLboolean sizeOK = GL_TRUE; 15793464ebd5Sriastradh GLboolean colorFormat, indexFormat; 15803464ebd5Sriastradh 15813464ebd5Sriastradh /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 15823464ebd5Sriastradh if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 15833464ebd5Sriastradh if (!isProxy) { 15843464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 15853464ebd5Sriastradh "glTexImage%dD(level=%d)", dimensions, level); 1586c1f859d4Smrg } 15873464ebd5Sriastradh return GL_TRUE; 15883464ebd5Sriastradh } 15893464ebd5Sriastradh 15903464ebd5Sriastradh /* Check border */ 15913464ebd5Sriastradh if (border < 0 || border > 1 || 15923464ebd5Sriastradh ((target == GL_TEXTURE_RECTANGLE_NV || 15933464ebd5Sriastradh target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 15943464ebd5Sriastradh if (!isProxy) { 15953464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 15963464ebd5Sriastradh "glTexImage%dD(border=%d)", dimensions, border); 15977117f1b4Smrg } 15983464ebd5Sriastradh return GL_TRUE; 15997117f1b4Smrg } 16003464ebd5Sriastradh 16013464ebd5Sriastradh if (width < 0 || height < 0 || depth < 0) { 16023464ebd5Sriastradh if (!isProxy) { 16033464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 16043464ebd5Sriastradh "glTexImage%dD(width, height or depth < 0)", dimensions); 16053464ebd5Sriastradh } 16067117f1b4Smrg return GL_TRUE; 16077117f1b4Smrg } 16087117f1b4Smrg 16093464ebd5Sriastradh /* Do this simple check before calling the TestProxyTexImage() function */ 16103464ebd5Sriastradh if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 16113464ebd5Sriastradh sizeOK = (width == height); 16123464ebd5Sriastradh } 16133464ebd5Sriastradh 16143464ebd5Sriastradh /* 16153464ebd5Sriastradh * Use the proxy texture driver hook to see if the size/level/etc are 16163464ebd5Sriastradh * legal. 16173464ebd5Sriastradh */ 16183464ebd5Sriastradh sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, 16197117f1b4Smrg internalFormat, format, 16207117f1b4Smrg type, width, height, 16217117f1b4Smrg depth, border); 16227117f1b4Smrg if (!sizeOK) { 16237117f1b4Smrg if (!isProxy) { 16247117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16257117f1b4Smrg "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 16267117f1b4Smrg dimensions, level, width, height, depth); 16277117f1b4Smrg } 16287117f1b4Smrg return GL_TRUE; 16297117f1b4Smrg } 16307117f1b4Smrg 16317117f1b4Smrg /* Check internalFormat */ 16327117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 16337117f1b4Smrg if (!isProxy) { 16347117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 16354a49301eSmrg "glTexImage%dD(internalFormat=%s)", 16364a49301eSmrg dimensions, _mesa_lookup_enum_by_nr(internalFormat)); 16377117f1b4Smrg } 16387117f1b4Smrg return GL_TRUE; 16397117f1b4Smrg } 16407117f1b4Smrg 16417117f1b4Smrg /* Check incoming image format and type */ 16427117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 16433464ebd5Sriastradh /* Normally, GL_INVALID_OPERATION is generated by a format/type 16443464ebd5Sriastradh * mismatch (see the 1.2 spec page 94, sec 3.6.4.). But with the 16453464ebd5Sriastradh * GL_EXT_texture_integer extension, some combinations should generate 16463464ebd5Sriastradh * GL_INVALID_ENUM instead (grr!). 16477117f1b4Smrg */ 16487117f1b4Smrg if (!isProxy) { 16493464ebd5Sriastradh GLenum error = _mesa_is_integer_format(format) 16503464ebd5Sriastradh ? GL_INVALID_ENUM : GL_INVALID_OPERATION; 16513464ebd5Sriastradh _mesa_error(ctx, error, 16524a49301eSmrg "glTexImage%dD(incompatible format 0x%x, type 0x%x)", 16534a49301eSmrg dimensions, format, type); 16547117f1b4Smrg } 16557117f1b4Smrg return GL_TRUE; 16567117f1b4Smrg } 16577117f1b4Smrg 16587117f1b4Smrg /* make sure internal format and format basically agree */ 1659c1f859d4Smrg colorFormat = _mesa_is_color_format(format); 16604a49301eSmrg indexFormat = _mesa_is_index_format(format); 1661c1f859d4Smrg if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 16624a49301eSmrg (_mesa_is_index_format(internalFormat) && !indexFormat) || 16634a49301eSmrg (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || 16644a49301eSmrg (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || 16654a49301eSmrg (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || 16664a49301eSmrg (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) { 16677117f1b4Smrg if (!isProxy) 16687117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 16694a49301eSmrg "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)", 16704a49301eSmrg dimensions, internalFormat, format); 16717117f1b4Smrg return GL_TRUE; 16727117f1b4Smrg } 16737117f1b4Smrg 16747117f1b4Smrg /* additional checks for ycbcr textures */ 16757117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) { 16767117f1b4Smrg ASSERT(ctx->Extensions.MESA_ycbcr_texture); 16777117f1b4Smrg if (type != GL_UNSIGNED_SHORT_8_8_MESA && 16787117f1b4Smrg type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 16797117f1b4Smrg char message[100]; 16803464ebd5Sriastradh _mesa_snprintf(message, sizeof(message), 16813464ebd5Sriastradh "glTexImage%dD(format/type YCBCR mismatch", dimensions); 16823464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s", message); 16837117f1b4Smrg return GL_TRUE; /* error */ 16847117f1b4Smrg } 16857117f1b4Smrg if (target != GL_TEXTURE_2D && 16867117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 16877117f1b4Smrg target != GL_TEXTURE_RECTANGLE_NV && 16887117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 16897117f1b4Smrg if (!isProxy) 16907117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 16917117f1b4Smrg return GL_TRUE; 16927117f1b4Smrg } 16937117f1b4Smrg if (border != 0) { 16947117f1b4Smrg if (!isProxy) { 16957117f1b4Smrg char message[100]; 16963464ebd5Sriastradh _mesa_snprintf(message, sizeof(message), 16973464ebd5Sriastradh "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)", 16983464ebd5Sriastradh dimensions, border); 16993464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "%s", message); 17007117f1b4Smrg } 17017117f1b4Smrg return GL_TRUE; 17027117f1b4Smrg } 17037117f1b4Smrg } 17047117f1b4Smrg 17057117f1b4Smrg /* additional checks for depth textures */ 17067117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 17073464ebd5Sriastradh /* Only 1D, 2D, rect and array textures supported, not 3D or cubes */ 17087117f1b4Smrg if (target != GL_TEXTURE_1D && 17097117f1b4Smrg target != GL_PROXY_TEXTURE_1D && 17107117f1b4Smrg target != GL_TEXTURE_2D && 17117117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 17123464ebd5Sriastradh target != GL_TEXTURE_1D_ARRAY && 17133464ebd5Sriastradh target != GL_PROXY_TEXTURE_1D_ARRAY && 17143464ebd5Sriastradh target != GL_TEXTURE_2D_ARRAY && 17153464ebd5Sriastradh target != GL_PROXY_TEXTURE_2D_ARRAY && 17167117f1b4Smrg target != GL_TEXTURE_RECTANGLE_ARB && 17177117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 17187117f1b4Smrg if (!isProxy) 17197117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 17207117f1b4Smrg "glTexImage(target/internalFormat)"); 17217117f1b4Smrg return GL_TRUE; 17227117f1b4Smrg } 17237117f1b4Smrg } 17247117f1b4Smrg 17257117f1b4Smrg /* additional checks for compressed textures */ 17263464ebd5Sriastradh if (_mesa_is_compressed_format(ctx, internalFormat)) { 17273464ebd5Sriastradh if (!target_can_be_compressed(ctx, target, internalFormat)) { 17283464ebd5Sriastradh if (!isProxy) 17293464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, 17303464ebd5Sriastradh "glTexImage%dD(target)", dimensions); 17317117f1b4Smrg return GL_TRUE; 17327117f1b4Smrg } 17337117f1b4Smrg if (border != 0) { 17347117f1b4Smrg if (!isProxy) { 17357117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 17363464ebd5Sriastradh "glTexImage%dD(border!=0)", dimensions); 17377117f1b4Smrg } 17387117f1b4Smrg return GL_TRUE; 17397117f1b4Smrg } 17407117f1b4Smrg } 17417117f1b4Smrg 17423464ebd5Sriastradh /* additional checks for integer textures */ 17433464ebd5Sriastradh if (ctx->Extensions.EXT_texture_integer && 17443464ebd5Sriastradh (_mesa_is_integer_format(format) != 17453464ebd5Sriastradh _mesa_is_integer_format(internalFormat))) { 17463464ebd5Sriastradh if (!isProxy) { 17473464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 17483464ebd5Sriastradh "glTexImage%dD(integer/non-integer format mismatch)", 17493464ebd5Sriastradh dimensions); 17503464ebd5Sriastradh } 17513464ebd5Sriastradh return GL_TRUE; 17523464ebd5Sriastradh } 17533464ebd5Sriastradh 17547117f1b4Smrg /* if we get here, the parameters are OK */ 17557117f1b4Smrg return GL_FALSE; 17567117f1b4Smrg} 17577117f1b4Smrg 17587117f1b4Smrg 17597117f1b4Smrg/** 17607117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors. 17617117f1b4Smrg * 17627117f1b4Smrg * \param ctx GL context. 17637117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 17647117f1b4Smrg * \param target texture target given by the user. 17657117f1b4Smrg * \param level image level given by the user. 17667117f1b4Smrg * \param xoffset sub-image x offset given by the user. 17677117f1b4Smrg * \param yoffset sub-image y offset given by the user. 17687117f1b4Smrg * \param zoffset sub-image z offset given by the user. 17697117f1b4Smrg * \param format pixel data format given by the user. 17707117f1b4Smrg * \param type pixel data type given by the user. 17717117f1b4Smrg * \param width image width given by the user. 17727117f1b4Smrg * \param height image height given by the user. 17737117f1b4Smrg * \param depth image depth given by the user. 17747117f1b4Smrg * 17757117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 17767117f1b4Smrg * 17777117f1b4Smrg * Verifies each of the parameters against the constants specified in 17783464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 17793464ebd5Sriastradh * to the OpenGL specification. 17807117f1b4Smrg */ 17817117f1b4Smrgstatic GLboolean 17823464ebd5Sriastradhsubtexture_error_check( struct gl_context *ctx, GLuint dimensions, 17837117f1b4Smrg GLenum target, GLint level, 17847117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 17857117f1b4Smrg GLint width, GLint height, GLint depth, 17867117f1b4Smrg GLenum format, GLenum type ) 17877117f1b4Smrg{ 17887117f1b4Smrg /* Basic level check */ 17897117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 17907117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 17917117f1b4Smrg return GL_TRUE; 17927117f1b4Smrg } 17937117f1b4Smrg 17943464ebd5Sriastradh /* Check for negative sizes */ 17957117f1b4Smrg if (width < 0) { 17967117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 17977117f1b4Smrg "glTexSubImage%dD(width=%d)", dimensions, width); 17987117f1b4Smrg return GL_TRUE; 17997117f1b4Smrg } 18007117f1b4Smrg if (height < 0 && dimensions > 1) { 18017117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18027117f1b4Smrg "glTexSubImage%dD(height=%d)", dimensions, height); 18037117f1b4Smrg return GL_TRUE; 18047117f1b4Smrg } 18057117f1b4Smrg if (depth < 0 && dimensions > 2) { 18067117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 18077117f1b4Smrg "glTexSubImage%dD(depth=%d)", dimensions, depth); 18087117f1b4Smrg return GL_TRUE; 18097117f1b4Smrg } 18107117f1b4Smrg 18117117f1b4Smrg if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 18123464ebd5Sriastradh /* As with the glTexImage2D check above, the error code here 18133464ebd5Sriastradh * depends on texture integer. 18143464ebd5Sriastradh */ 18153464ebd5Sriastradh GLenum error = _mesa_is_integer_format(format) 18163464ebd5Sriastradh ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 18173464ebd5Sriastradh _mesa_error(ctx, error, 18184a49301eSmrg "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)", 18194a49301eSmrg dimensions, format, type); 18207117f1b4Smrg return GL_TRUE; 18217117f1b4Smrg } 18227117f1b4Smrg 18237117f1b4Smrg return GL_FALSE; 18247117f1b4Smrg} 18257117f1b4Smrg 18264a49301eSmrg 18274a49301eSmrg/** 18284a49301eSmrg * Do second part of glTexSubImage which depends on the destination texture. 18294a49301eSmrg * \return GL_TRUE if error recorded, GL_FALSE otherwise 18304a49301eSmrg */ 18317117f1b4Smrgstatic GLboolean 18323464ebd5Sriastradhsubtexture_error_check2( struct gl_context *ctx, GLuint dimensions, 18337117f1b4Smrg GLenum target, GLint level, 18347117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 18357117f1b4Smrg GLint width, GLint height, GLint depth, 18367117f1b4Smrg GLenum format, GLenum type, 18377117f1b4Smrg const struct gl_texture_image *destTex ) 18387117f1b4Smrg{ 18397117f1b4Smrg if (!destTex) { 18407117f1b4Smrg /* undefined image level */ 18417117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 18427117f1b4Smrg return GL_TRUE; 18437117f1b4Smrg } 18447117f1b4Smrg 18457117f1b4Smrg if (xoffset < -((GLint)destTex->Border)) { 18467117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 18477117f1b4Smrg dimensions); 18487117f1b4Smrg return GL_TRUE; 18497117f1b4Smrg } 18507117f1b4Smrg if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 18517117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 18527117f1b4Smrg dimensions); 18537117f1b4Smrg return GL_TRUE; 18547117f1b4Smrg } 18557117f1b4Smrg if (dimensions > 1) { 18567117f1b4Smrg if (yoffset < -((GLint)destTex->Border)) { 18577117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 18587117f1b4Smrg dimensions); 18597117f1b4Smrg return GL_TRUE; 18607117f1b4Smrg } 18617117f1b4Smrg if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 18627117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 18637117f1b4Smrg dimensions); 18647117f1b4Smrg return GL_TRUE; 18657117f1b4Smrg } 18667117f1b4Smrg } 18677117f1b4Smrg if (dimensions > 2) { 18687117f1b4Smrg if (zoffset < -((GLint)destTex->Border)) { 18697117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 18707117f1b4Smrg return GL_TRUE; 18717117f1b4Smrg } 18727117f1b4Smrg if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 18737117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 18747117f1b4Smrg return GL_TRUE; 18757117f1b4Smrg } 18767117f1b4Smrg } 18777117f1b4Smrg 18784a49301eSmrg if (_mesa_is_format_compressed(destTex->TexFormat)) { 18794a49301eSmrg GLuint bw, bh; 18807117f1b4Smrg 18814a49301eSmrg /* do tests which depend on compression block size */ 18824a49301eSmrg _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); 18834a49301eSmrg 18844a49301eSmrg /* offset must be multiple of block size */ 18854a49301eSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0)) { 18867117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18873464ebd5Sriastradh "glTexSubImage%dD(xoffset = %d, yoffset = %d)", 18884a49301eSmrg dimensions, xoffset, yoffset); 18897117f1b4Smrg return GL_TRUE; 18907117f1b4Smrg } 18914a49301eSmrg /* size must be multiple of bw by bh or equal to whole texture size */ 18924a49301eSmrg if ((width % bw != 0) && (GLuint) width != destTex->Width) { 18937117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18943464ebd5Sriastradh "glTexSubImage%dD(width = %d)", dimensions, width); 18957117f1b4Smrg return GL_TRUE; 18967117f1b4Smrg } 18974a49301eSmrg if ((height % bh != 0) && (GLuint) height != destTex->Height) { 18987117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 18993464ebd5Sriastradh "glTexSubImage%dD(height = %d)", dimensions, height); 19007117f1b4Smrg return GL_TRUE; 19017117f1b4Smrg } 19027117f1b4Smrg } 19037117f1b4Smrg 19047117f1b4Smrg return GL_FALSE; 19057117f1b4Smrg} 19067117f1b4Smrg 19077117f1b4Smrg 19087117f1b4Smrg/** 19097117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors. 19107117f1b4Smrg * 19117117f1b4Smrg * \param ctx GL context. 19127117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 19137117f1b4Smrg * \param target texture target given by the user. 19147117f1b4Smrg * \param level image level given by the user. 19157117f1b4Smrg * \param internalFormat internal format given by the user. 19167117f1b4Smrg * \param width image width given by the user. 19177117f1b4Smrg * \param height image height given by the user. 19187117f1b4Smrg * \param border texture border. 19197117f1b4Smrg * 19207117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 19217117f1b4Smrg * 19227117f1b4Smrg * Verifies each of the parameters against the constants specified in 19233464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 19243464ebd5Sriastradh * to the OpenGL specification. 19257117f1b4Smrg */ 19267117f1b4Smrgstatic GLboolean 19273464ebd5Sriastradhcopytexture_error_check( struct gl_context *ctx, GLuint dimensions, 19287117f1b4Smrg GLenum target, GLint level, GLint internalFormat, 19297117f1b4Smrg GLint width, GLint height, GLint border ) 19307117f1b4Smrg{ 19313464ebd5Sriastradh const GLenum proxyTarget = get_proxy_target(target); 19323464ebd5Sriastradh const GLenum type = GL_FLOAT; 19337117f1b4Smrg GLboolean sizeOK; 19347117f1b4Smrg GLint format; 19357117f1b4Smrg 19363464ebd5Sriastradh /* check target */ 19373464ebd5Sriastradh if (!legal_texsubimage_target(ctx, dimensions, target)) { 19383464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)", 19393464ebd5Sriastradh dimensions, _mesa_lookup_enum_by_nr(target)); 19403464ebd5Sriastradh return GL_TRUE; 19413464ebd5Sriastradh } 19423464ebd5Sriastradh 19437117f1b4Smrg /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 19447117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 19457117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19467117f1b4Smrg "glCopyTexImage%dD(level=%d)", dimensions, level); 19477117f1b4Smrg return GL_TRUE; 19487117f1b4Smrg } 19497117f1b4Smrg 19507117f1b4Smrg /* Check that the source buffer is complete */ 19517117f1b4Smrg if (ctx->ReadBuffer->Name) { 19523464ebd5Sriastradh if (ctx->ReadBuffer->_Status == 0) { 19533464ebd5Sriastradh _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 19543464ebd5Sriastradh } 19557117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 19567117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 19577117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 19587117f1b4Smrg return GL_TRUE; 19597117f1b4Smrg } 19607117f1b4Smrg } 19617117f1b4Smrg 19627117f1b4Smrg /* Check border */ 19637117f1b4Smrg if (border < 0 || border > 1 || 19647117f1b4Smrg ((target == GL_TEXTURE_RECTANGLE_NV || 19657117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 19667117f1b4Smrg return GL_TRUE; 19677117f1b4Smrg } 19687117f1b4Smrg 19697117f1b4Smrg format = _mesa_base_tex_format(ctx, internalFormat); 19707117f1b4Smrg if (format < 0) { 19717117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19727117f1b4Smrg "glCopyTexImage%dD(internalFormat)", dimensions); 19737117f1b4Smrg return GL_TRUE; 19747117f1b4Smrg } 19757117f1b4Smrg 19767117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, format)) { 19777117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 19787117f1b4Smrg "glCopyTexImage%dD(missing readbuffer)", dimensions); 19797117f1b4Smrg return GL_TRUE; 19807117f1b4Smrg } 19817117f1b4Smrg 19823464ebd5Sriastradh /* Do size, level checking */ 19833464ebd5Sriastradh sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) 19843464ebd5Sriastradh ? (width == height) : 1; 19857117f1b4Smrg 19863464ebd5Sriastradh sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, 19873464ebd5Sriastradh internalFormat, format, 19883464ebd5Sriastradh type, width, height, 19893464ebd5Sriastradh 1, border); 19907117f1b4Smrg 19917117f1b4Smrg if (!sizeOK) { 19927117f1b4Smrg if (dimensions == 1) { 19937117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19947117f1b4Smrg "glCopyTexImage1D(width=%d)", width); 19957117f1b4Smrg } 19967117f1b4Smrg else { 19977117f1b4Smrg ASSERT(dimensions == 2); 19987117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 19997117f1b4Smrg "glCopyTexImage2D(width=%d, height=%d)", width, height); 20007117f1b4Smrg } 20017117f1b4Smrg return GL_TRUE; 20027117f1b4Smrg } 20037117f1b4Smrg 20043464ebd5Sriastradh if (_mesa_is_compressed_format(ctx, internalFormat)) { 20053464ebd5Sriastradh if (!target_can_be_compressed(ctx, target, internalFormat)) { 20067117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, 20073464ebd5Sriastradh "glCopyTexImage%dD(target)", dimensions); 20087117f1b4Smrg return GL_TRUE; 20097117f1b4Smrg } 20107117f1b4Smrg if (border != 0) { 20117117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20123464ebd5Sriastradh "glCopyTexImage%dD(border!=0)", dimensions); 20137117f1b4Smrg return GL_TRUE; 20147117f1b4Smrg } 20157117f1b4Smrg } 20164a49301eSmrg else if (_mesa_is_depth_format(internalFormat)) { 20177117f1b4Smrg /* make sure we have depth/stencil buffers */ 20187117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 20197117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20203464ebd5Sriastradh "glCopyTexImage%dD(no depth)", dimensions); 20217117f1b4Smrg return GL_TRUE; 20227117f1b4Smrg } 20237117f1b4Smrg } 20244a49301eSmrg else if (_mesa_is_depthstencil_format(internalFormat)) { 20257117f1b4Smrg /* make sure we have depth/stencil buffers */ 20267117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 20277117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 20283464ebd5Sriastradh "glCopyTexImage%dD(no depth/stencil buffer)", dimensions); 20297117f1b4Smrg return GL_TRUE; 20307117f1b4Smrg } 20317117f1b4Smrg } 20327117f1b4Smrg 20337117f1b4Smrg /* if we get here, the parameters are OK */ 20347117f1b4Smrg return GL_FALSE; 20357117f1b4Smrg} 20367117f1b4Smrg 20377117f1b4Smrg 20387117f1b4Smrg/** 20397117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors. 2040c1f859d4Smrg * Note that this is the first part of error checking. 2041c1f859d4Smrg * See also copytexsubimage_error_check2() below for the second part. 20427117f1b4Smrg * 20437117f1b4Smrg * \param ctx GL context. 20447117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 20457117f1b4Smrg * \param target texture target given by the user. 20467117f1b4Smrg * \param level image level given by the user. 20477117f1b4Smrg * 20487117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 20497117f1b4Smrg */ 20507117f1b4Smrgstatic GLboolean 20513464ebd5Sriastradhcopytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, 2052c1f859d4Smrg GLenum target, GLint level) 20537117f1b4Smrg{ 20547117f1b4Smrg /* Check that the source buffer is complete */ 20557117f1b4Smrg if (ctx->ReadBuffer->Name) { 20563464ebd5Sriastradh if (ctx->ReadBuffer->_Status == 0) { 20573464ebd5Sriastradh _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 20583464ebd5Sriastradh } 20597117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 20607117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 20617117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 20627117f1b4Smrg return GL_TRUE; 20637117f1b4Smrg } 20647117f1b4Smrg } 20657117f1b4Smrg 20663464ebd5Sriastradh /* check target (proxies not allowed) */ 20673464ebd5Sriastradh if (!legal_texsubimage_target(ctx, dimensions, target)) { 20683464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%uD(target=%s)", 20693464ebd5Sriastradh dimensions, _mesa_lookup_enum_by_nr(target)); 20703464ebd5Sriastradh return GL_TRUE; 20717117f1b4Smrg } 20727117f1b4Smrg 20737117f1b4Smrg /* Check level */ 20747117f1b4Smrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 20757117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 20767117f1b4Smrg "glCopyTexSubImage%dD(level=%d)", dimensions, level); 20777117f1b4Smrg return GL_TRUE; 20787117f1b4Smrg } 20797117f1b4Smrg 20807117f1b4Smrg return GL_FALSE; 20817117f1b4Smrg} 20827117f1b4Smrg 2083c1f859d4Smrg 2084c1f859d4Smrg/** 2085c1f859d4Smrg * Second part of error checking for glCopyTexSubImage[12]D(). 2086c1f859d4Smrg * \param xoffset sub-image x offset given by the user. 2087c1f859d4Smrg * \param yoffset sub-image y offset given by the user. 2088c1f859d4Smrg * \param zoffset sub-image z offset given by the user. 2089c1f859d4Smrg * \param width image width given by the user. 2090c1f859d4Smrg * \param height image height given by the user. 2091c1f859d4Smrg */ 20927117f1b4Smrgstatic GLboolean 20933464ebd5Sriastradhcopytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, 20947117f1b4Smrg GLenum target, GLint level, 20957117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 20967117f1b4Smrg GLsizei width, GLsizei height, 20977117f1b4Smrg const struct gl_texture_image *teximage ) 20987117f1b4Smrg{ 2099c1f859d4Smrg /* check that dest tex image exists */ 21007117f1b4Smrg if (!teximage) { 21017117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 21027117f1b4Smrg "glCopyTexSubImage%dD(undefined texture level: %d)", 21037117f1b4Smrg dimensions, level); 21047117f1b4Smrg return GL_TRUE; 21057117f1b4Smrg } 21067117f1b4Smrg 2107c1f859d4Smrg /* Check size */ 2108c1f859d4Smrg if (width < 0) { 2109c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 2110c1f859d4Smrg "glCopyTexSubImage%dD(width=%d)", dimensions, width); 2111c1f859d4Smrg return GL_TRUE; 2112c1f859d4Smrg } 2113c1f859d4Smrg if (dimensions > 1 && height < 0) { 2114c1f859d4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 2115c1f859d4Smrg "glCopyTexSubImage%dD(height=%d)", dimensions, height); 2116c1f859d4Smrg return GL_TRUE; 2117c1f859d4Smrg } 2118c1f859d4Smrg 2119c1f859d4Smrg /* check x/y offsets */ 21207117f1b4Smrg if (xoffset < -((GLint)teximage->Border)) { 21217117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21227117f1b4Smrg "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 21237117f1b4Smrg return GL_TRUE; 21247117f1b4Smrg } 21257117f1b4Smrg if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 21267117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21277117f1b4Smrg "glCopyTexSubImage%dD(xoffset+width)", dimensions); 21287117f1b4Smrg return GL_TRUE; 21297117f1b4Smrg } 21307117f1b4Smrg if (dimensions > 1) { 21317117f1b4Smrg if (yoffset < -((GLint)teximage->Border)) { 21327117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21337117f1b4Smrg "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 21347117f1b4Smrg return GL_TRUE; 21357117f1b4Smrg } 21367117f1b4Smrg /* NOTE: we're adding the border here, not subtracting! */ 21377117f1b4Smrg if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 21387117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21397117f1b4Smrg "glCopyTexSubImage%dD(yoffset+height)", dimensions); 21407117f1b4Smrg return GL_TRUE; 21417117f1b4Smrg } 21427117f1b4Smrg } 21437117f1b4Smrg 2144c1f859d4Smrg /* check z offset */ 21457117f1b4Smrg if (dimensions > 2) { 21467117f1b4Smrg if (zoffset < -((GLint)teximage->Border)) { 21477117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21487117f1b4Smrg "glCopyTexSubImage%dD(zoffset)", dimensions); 21497117f1b4Smrg return GL_TRUE; 21507117f1b4Smrg } 21517117f1b4Smrg if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 21527117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21537117f1b4Smrg "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 21547117f1b4Smrg return GL_TRUE; 21557117f1b4Smrg } 21567117f1b4Smrg } 21577117f1b4Smrg 21584a49301eSmrg if (_mesa_is_format_compressed(teximage->TexFormat)) { 21597117f1b4Smrg /* offset must be multiple of 4 */ 21607117f1b4Smrg if ((xoffset & 3) || (yoffset & 3)) { 21617117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21623464ebd5Sriastradh "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions); 21637117f1b4Smrg return GL_TRUE; 21647117f1b4Smrg } 21657117f1b4Smrg /* size must be multiple of 4 */ 21667117f1b4Smrg if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 21677117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21683464ebd5Sriastradh "glCopyTexSubImage%dD(width)", dimensions); 21697117f1b4Smrg return GL_TRUE; 21707117f1b4Smrg } 21717117f1b4Smrg if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 21727117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 21733464ebd5Sriastradh "glCopyTexSubImage%dD(height)", dimensions); 21747117f1b4Smrg return GL_TRUE; 21757117f1b4Smrg } 21767117f1b4Smrg } 21777117f1b4Smrg 21787117f1b4Smrg if (teximage->InternalFormat == GL_YCBCR_MESA) { 21797117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 21807117f1b4Smrg return GL_TRUE; 21817117f1b4Smrg } 21827117f1b4Smrg 21837117f1b4Smrg if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 21847117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2185c1f859d4Smrg "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 2186c1f859d4Smrg dimensions, teximage->_BaseFormat); 21877117f1b4Smrg return GL_TRUE; 21887117f1b4Smrg } 21897117f1b4Smrg 21907117f1b4Smrg if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 21917117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer) { 21927117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 21933464ebd5Sriastradh "glCopyTexSubImage%dD(no depth buffer)", 21947117f1b4Smrg dimensions); 21957117f1b4Smrg return GL_TRUE; 21967117f1b4Smrg } 21977117f1b4Smrg } 21987117f1b4Smrg else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 21997117f1b4Smrg if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 22007117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 22013464ebd5Sriastradh "glCopyTexSubImage%dD(no depth/stencil buffer)", 22027117f1b4Smrg dimensions); 22037117f1b4Smrg return GL_TRUE; 22047117f1b4Smrg } 22057117f1b4Smrg } 22067117f1b4Smrg 22073464ebd5Sriastradh /* If copying into an integer texture, the source buffer must also be 22083464ebd5Sriastradh * integer-valued. 22093464ebd5Sriastradh */ 22103464ebd5Sriastradh if (_mesa_is_format_integer_color(teximage->TexFormat)) { 22113464ebd5Sriastradh struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 22123464ebd5Sriastradh if (!_mesa_is_format_integer_color(rb->Format)) { 22133464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 22143464ebd5Sriastradh "glCopyTexSubImage%dD(source buffer is not integer format)", 22153464ebd5Sriastradh dimensions); 22163464ebd5Sriastradh return GL_TRUE; 22173464ebd5Sriastradh } 22183464ebd5Sriastradh } 22193464ebd5Sriastradh 22207117f1b4Smrg /* if we get here, the parameters are OK */ 22217117f1b4Smrg return GL_FALSE; 22227117f1b4Smrg} 22237117f1b4Smrg 22247117f1b4Smrg 22254a49301eSmrg/** Callback info for walking over FBO hash table */ 22264a49301eSmrgstruct cb_info 22277117f1b4Smrg{ 22283464ebd5Sriastradh struct gl_context *ctx; 22297117f1b4Smrg struct gl_texture_object *texObj; 22304a49301eSmrg GLuint level, face; 22314a49301eSmrg}; 22327117f1b4Smrg 22337117f1b4Smrg 22347117f1b4Smrg/** 22354a49301eSmrg * Check render to texture callback. Called from _mesa_HashWalk(). 22367117f1b4Smrg */ 22377117f1b4Smrgstatic void 22384a49301eSmrgcheck_rtt_cb(GLuint key, void *data, void *userData) 22397117f1b4Smrg{ 22404a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 22414a49301eSmrg const struct cb_info *info = (struct cb_info *) userData; 22423464ebd5Sriastradh struct gl_context *ctx = info->ctx; 22434a49301eSmrg const struct gl_texture_object *texObj = info->texObj; 22444a49301eSmrg const GLuint level = info->level, face = info->face; 22454a49301eSmrg 22464a49301eSmrg /* If this is a user-created FBO */ 22474a49301eSmrg if (fb->Name) { 22487117f1b4Smrg GLuint i; 22494a49301eSmrg /* check if any of the FBO's attachments point to 'texObj' */ 22507117f1b4Smrg for (i = 0; i < BUFFER_COUNT; i++) { 22514a49301eSmrg struct gl_renderbuffer_attachment *att = fb->Attachment + i; 22527117f1b4Smrg if (att->Type == GL_TEXTURE && 22537117f1b4Smrg att->Texture == texObj && 22547117f1b4Smrg att->TextureLevel == level && 22557117f1b4Smrg att->CubeMapFace == face) { 22563464ebd5Sriastradh ASSERT(_mesa_get_attachment_teximage(att)); 22577117f1b4Smrg /* Tell driver about the new renderbuffer texture */ 22587117f1b4Smrg ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 22594a49301eSmrg /* Mark fb status as indeterminate to force re-validation */ 22604a49301eSmrg fb->_Status = 0; 22617117f1b4Smrg } 22627117f1b4Smrg } 22637117f1b4Smrg } 22647117f1b4Smrg} 22657117f1b4Smrg 22667117f1b4Smrg 22674a49301eSmrg/** 22684a49301eSmrg * When a texture image is specified we have to check if it's bound to 22694a49301eSmrg * any framebuffer objects (render to texture) in order to detect changes 22704a49301eSmrg * in size or format since that effects FBO completeness. 22714a49301eSmrg * Any FBOs rendering into the texture must be re-validated. 22724a49301eSmrg */ 22734a49301eSmrgstatic void 22743464ebd5Sriastradhupdate_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj, 22754a49301eSmrg GLuint face, GLuint level) 22764a49301eSmrg{ 22774a49301eSmrg /* Only check this texture if it's been marked as RenderToTexture */ 22784a49301eSmrg if (texObj->_RenderToTexture) { 22794a49301eSmrg struct cb_info info; 22804a49301eSmrg info.ctx = ctx; 22814a49301eSmrg info.texObj = texObj; 22824a49301eSmrg info.level = level; 22834a49301eSmrg info.face = face; 22844a49301eSmrg _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 22854a49301eSmrg } 22864a49301eSmrg} 22874a49301eSmrg 22884a49301eSmrg 22894a49301eSmrg/** 22904a49301eSmrg * If the texture object's GenerateMipmap flag is set and we've 22914a49301eSmrg * changed the texture base level image, regenerate the rest of the 22924a49301eSmrg * mipmap levels now. 22934a49301eSmrg */ 22944a49301eSmrgstatic INLINE void 22953464ebd5Sriastradhcheck_gen_mipmap(struct gl_context *ctx, GLenum target, 22964a49301eSmrg struct gl_texture_object *texObj, GLint level) 22974a49301eSmrg{ 22984a49301eSmrg ASSERT(target != GL_TEXTURE_CUBE_MAP); 22994a49301eSmrg if (texObj->GenerateMipmap && 23004a49301eSmrg level == texObj->BaseLevel && 23014a49301eSmrg level < texObj->MaxLevel) { 23024a49301eSmrg ASSERT(ctx->Driver.GenerateMipmap); 23034a49301eSmrg ctx->Driver.GenerateMipmap(ctx, target, texObj); 23044a49301eSmrg } 23054a49301eSmrg} 23064a49301eSmrg 23074a49301eSmrg 23084a49301eSmrg/** Debug helper: override the user-requested internal format */ 23094a49301eSmrgstatic GLenum 23104a49301eSmrgoverride_internal_format(GLenum internalFormat, GLint width, GLint height) 23114a49301eSmrg{ 23124a49301eSmrg#if 0 23134a49301eSmrg if (internalFormat == GL_RGBA16F_ARB || 23144a49301eSmrg internalFormat == GL_RGBA32F_ARB) { 23154a49301eSmrg printf("Convert rgba float tex to int %d x %d\n", width, height); 23164a49301eSmrg return GL_RGBA; 23174a49301eSmrg } 23184a49301eSmrg else if (internalFormat == GL_RGB16F_ARB || 23194a49301eSmrg internalFormat == GL_RGB32F_ARB) { 23204a49301eSmrg printf("Convert rgb float tex to int %d x %d\n", width, height); 23214a49301eSmrg return GL_RGB; 23224a49301eSmrg } 23234a49301eSmrg else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 23244a49301eSmrg internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 23254a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 23264a49301eSmrg return GL_LUMINANCE_ALPHA; 23274a49301eSmrg } 23284a49301eSmrg else if (internalFormat == GL_LUMINANCE16F_ARB || 23294a49301eSmrg internalFormat == GL_LUMINANCE32F_ARB) { 23304a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 23314a49301eSmrg return GL_LUMINANCE; 23324a49301eSmrg } 23334a49301eSmrg else if (internalFormat == GL_ALPHA16F_ARB || 23344a49301eSmrg internalFormat == GL_ALPHA32F_ARB) { 23354a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 23364a49301eSmrg return GL_ALPHA; 23374a49301eSmrg } 23384a49301eSmrg /* 23394a49301eSmrg else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 23404a49301eSmrg internalFormat = GL_RGBA; 23414a49301eSmrg } 23424a49301eSmrg */ 23434a49301eSmrg else { 23444a49301eSmrg return internalFormat; 23454a49301eSmrg } 23464a49301eSmrg#else 23474a49301eSmrg return internalFormat; 23484a49301eSmrg#endif 23494a49301eSmrg} 23504a49301eSmrg 23517117f1b4Smrg 23523464ebd5Sriastradh/** 23533464ebd5Sriastradh * Choose the actual hardware format for a texture image. 23543464ebd5Sriastradh * Try to use the same format as the previous image level when possible. 23553464ebd5Sriastradh * Otherwise, ask the driver for the best format. 23563464ebd5Sriastradh * It's important to try to choose a consistant format for all levels 23573464ebd5Sriastradh * for efficient texture memory layout/allocation. In particular, this 23583464ebd5Sriastradh * comes up during automatic mipmap generation. 23597117f1b4Smrg */ 23603464ebd5Sriastradhgl_format 23613464ebd5Sriastradh_mesa_choose_texture_format(struct gl_context *ctx, 23623464ebd5Sriastradh struct gl_texture_object *texObj, 23633464ebd5Sriastradh GLenum target, GLint level, 23643464ebd5Sriastradh GLenum internalFormat, GLenum format, GLenum type) 23657117f1b4Smrg{ 23663464ebd5Sriastradh gl_format f; 23673464ebd5Sriastradh 23683464ebd5Sriastradh /* see if we've already chosen a format for the previous level */ 23693464ebd5Sriastradh if (level > 0) { 23703464ebd5Sriastradh struct gl_texture_image *prevImage = 23713464ebd5Sriastradh _mesa_select_tex_image(ctx, texObj, target, level - 1); 23723464ebd5Sriastradh /* See if the prev level is defined and has an internal format which 23733464ebd5Sriastradh * matches the new internal format. 23743464ebd5Sriastradh */ 23753464ebd5Sriastradh if (prevImage && 23763464ebd5Sriastradh prevImage->Width > 0 && 23773464ebd5Sriastradh prevImage->InternalFormat == internalFormat) { 23783464ebd5Sriastradh /* use the same format */ 23793464ebd5Sriastradh ASSERT(prevImage->TexFormat != MESA_FORMAT_NONE); 23803464ebd5Sriastradh return prevImage->TexFormat; 23813464ebd5Sriastradh } 23823464ebd5Sriastradh } 23833464ebd5Sriastradh 23843464ebd5Sriastradh /* choose format from scratch */ 23853464ebd5Sriastradh f = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 23863464ebd5Sriastradh ASSERT(f != MESA_FORMAT_NONE); 23873464ebd5Sriastradh return f; 23883464ebd5Sriastradh} 23893464ebd5Sriastradh 23903464ebd5Sriastradh 23913464ebd5Sriastradh/** 23923464ebd5Sriastradh * Common code to implement all the glTexImage1D/2D/3D functions. 23933464ebd5Sriastradh */ 23943464ebd5Sriastradhstatic void 23953464ebd5Sriastradhteximage(struct gl_context *ctx, GLuint dims, 23963464ebd5Sriastradh GLenum target, GLint level, GLint internalFormat, 23973464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 23983464ebd5Sriastradh GLint border, GLenum format, GLenum type, 23993464ebd5Sriastradh const GLvoid *pixels) 24003464ebd5Sriastradh{ 24013464ebd5Sriastradh GLboolean error; 24023464ebd5Sriastradh 24037117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 24047117f1b4Smrg 24054a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 24063464ebd5Sriastradh _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n", 24073464ebd5Sriastradh dims, 24084a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 24093464ebd5Sriastradh _mesa_lookup_enum_by_nr(internalFormat), 24103464ebd5Sriastradh width, height, depth, border, 24114a49301eSmrg _mesa_lookup_enum_by_nr(format), 24124a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 24134a49301eSmrg 24143464ebd5Sriastradh internalFormat = override_internal_format(internalFormat, width, height); 24154a49301eSmrg 24163464ebd5Sriastradh /* target error checking */ 24173464ebd5Sriastradh if (!legal_teximage_target(ctx, dims, target)) { 24183464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)", 24193464ebd5Sriastradh dims, _mesa_lookup_enum_by_nr(target)); 24203464ebd5Sriastradh return; 24217117f1b4Smrg } 24227117f1b4Smrg 24233464ebd5Sriastradh /* general error checking */ 24243464ebd5Sriastradh error = texture_error_check(ctx, dims, target, level, internalFormat, 24253464ebd5Sriastradh format, type, width, height, depth, border); 24263464ebd5Sriastradh 24273464ebd5Sriastradh if (_mesa_is_proxy_texture(target)) { 24283464ebd5Sriastradh /* Proxy texture: just clear or set state depending on error checking */ 24293464ebd5Sriastradh struct gl_texture_image *texImage = 24303464ebd5Sriastradh _mesa_get_proxy_tex_image(ctx, target, level); 24313464ebd5Sriastradh 24323464ebd5Sriastradh if (error) { 24333464ebd5Sriastradh /* when error, clear all proxy texture image parameters */ 24343464ebd5Sriastradh if (texImage) 24353464ebd5Sriastradh clear_teximage_fields(texImage); 24363464ebd5Sriastradh } 24373464ebd5Sriastradh else { 24383464ebd5Sriastradh /* no error, set the tex image parameters */ 24393464ebd5Sriastradh struct gl_texture_object *texObj = 24403464ebd5Sriastradh _mesa_get_current_tex_object(ctx, target); 24413464ebd5Sriastradh gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, 24423464ebd5Sriastradh target, level, 24433464ebd5Sriastradh internalFormat, 24443464ebd5Sriastradh format, type); 24453464ebd5Sriastradh 24463464ebd5Sriastradh if (legal_texture_size(ctx, texFormat, width, height, depth)) { 24473464ebd5Sriastradh _mesa_init_teximage_fields(ctx, target, texImage, width, height, 24483464ebd5Sriastradh depth, border, internalFormat, 24493464ebd5Sriastradh texFormat); 24503464ebd5Sriastradh } 24513464ebd5Sriastradh else if (texImage) { 24523464ebd5Sriastradh clear_teximage_fields(texImage); 24533464ebd5Sriastradh } 24543464ebd5Sriastradh } 24553464ebd5Sriastradh } 24563464ebd5Sriastradh else { 24577117f1b4Smrg /* non-proxy target */ 24583464ebd5Sriastradh const GLuint face = _mesa_tex_target_to_face(target); 24597117f1b4Smrg struct gl_texture_object *texObj; 24607117f1b4Smrg struct gl_texture_image *texImage; 24617117f1b4Smrg 24623464ebd5Sriastradh if (error) { 24637117f1b4Smrg return; /* error was recorded */ 24647117f1b4Smrg } 24657117f1b4Smrg 24663464ebd5Sriastradh if (ctx->NewState & _NEW_PIXEL) 24677117f1b4Smrg _mesa_update_state(ctx); 24687117f1b4Smrg 24694a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 24703464ebd5Sriastradh 24717117f1b4Smrg _mesa_lock_texture(ctx, texObj); 24727117f1b4Smrg { 24737117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 24743464ebd5Sriastradh 24757117f1b4Smrg if (!texImage) { 24763464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); 24777117f1b4Smrg } 24784a49301eSmrg else { 24793464ebd5Sriastradh gl_format texFormat; 24803464ebd5Sriastradh 24814a49301eSmrg if (texImage->Data) { 24824a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 24834a49301eSmrg } 24844a49301eSmrg 24854a49301eSmrg ASSERT(texImage->Data == NULL); 24863464ebd5Sriastradh texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 24873464ebd5Sriastradh internalFormat, format, 24883464ebd5Sriastradh type); 24893464ebd5Sriastradh 24903464ebd5Sriastradh if (legal_texture_size(ctx, texFormat, width, height, depth)) { 24913464ebd5Sriastradh _mesa_init_teximage_fields(ctx, target, texImage, 24923464ebd5Sriastradh width, height, depth, 24933464ebd5Sriastradh border, internalFormat, texFormat); 24943464ebd5Sriastradh 24953464ebd5Sriastradh /* Give the texture to the driver. <pixels> may be null. */ 24963464ebd5Sriastradh ASSERT(ctx->Driver.TexImage3D); 24973464ebd5Sriastradh switch (dims) { 24983464ebd5Sriastradh case 1: 24993464ebd5Sriastradh ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 25003464ebd5Sriastradh width, border, format, 25013464ebd5Sriastradh type, pixels, &ctx->Unpack, texObj, 25023464ebd5Sriastradh texImage); 25033464ebd5Sriastradh break; 25043464ebd5Sriastradh case 2: 25053464ebd5Sriastradh ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 25063464ebd5Sriastradh width, height, border, format, 25073464ebd5Sriastradh type, pixels, &ctx->Unpack, texObj, 25083464ebd5Sriastradh texImage); 25093464ebd5Sriastradh break; 25103464ebd5Sriastradh case 3: 25113464ebd5Sriastradh ctx->Driver.TexImage3D(ctx, target, level, internalFormat, 25123464ebd5Sriastradh width, height, depth, border, format, 25133464ebd5Sriastradh type, pixels, &ctx->Unpack, texObj, 25143464ebd5Sriastradh texImage); 25153464ebd5Sriastradh break; 25163464ebd5Sriastradh default: 25173464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in teximage()", dims); 25183464ebd5Sriastradh } 25194a49301eSmrg 25203464ebd5Sriastradh check_gen_mipmap(ctx, target, texObj, level); 25214a49301eSmrg 25223464ebd5Sriastradh update_fbo_texture(ctx, texObj, face, level); 25234a49301eSmrg 25243464ebd5Sriastradh /* state update */ 25253464ebd5Sriastradh texObj->_Complete = GL_FALSE; 25263464ebd5Sriastradh ctx->NewState |= _NEW_TEXTURE; 25273464ebd5Sriastradh } 25283464ebd5Sriastradh else { 25293464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); 25303464ebd5Sriastradh } 25313464ebd5Sriastradh } 25323464ebd5Sriastradh } 25333464ebd5Sriastradh _mesa_unlock_texture(ctx, texObj); 25343464ebd5Sriastradh } 25353464ebd5Sriastradh} 25367117f1b4Smrg 25374a49301eSmrg 25383464ebd5Sriastradh/* 25393464ebd5Sriastradh * Called from the API. Note that width includes the border. 25403464ebd5Sriastradh */ 25413464ebd5Sriastradhvoid GLAPIENTRY 25423464ebd5Sriastradh_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 25433464ebd5Sriastradh GLsizei width, GLint border, GLenum format, 25443464ebd5Sriastradh GLenum type, const GLvoid *pixels ) 25453464ebd5Sriastradh{ 25463464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 25473464ebd5Sriastradh teximage(ctx, 1, target, level, internalFormat, width, 1, 1, 25483464ebd5Sriastradh border, format, type, pixels); 25497117f1b4Smrg} 25507117f1b4Smrg 25517117f1b4Smrg 25527117f1b4Smrgvoid GLAPIENTRY 25537117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 25547117f1b4Smrg GLsizei width, GLsizei height, GLint border, 25557117f1b4Smrg GLenum format, GLenum type, 25567117f1b4Smrg const GLvoid *pixels ) 25577117f1b4Smrg{ 25587117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25593464ebd5Sriastradh teximage(ctx, 2, target, level, internalFormat, width, height, 1, 25603464ebd5Sriastradh border, format, type, pixels); 25617117f1b4Smrg} 25627117f1b4Smrg 25637117f1b4Smrg 25647117f1b4Smrg/* 25657117f1b4Smrg * Called by the API or display list executor. 25667117f1b4Smrg * Note that width and height include the border. 25677117f1b4Smrg */ 25687117f1b4Smrgvoid GLAPIENTRY 25697117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 25707117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 25717117f1b4Smrg GLint border, GLenum format, GLenum type, 25727117f1b4Smrg const GLvoid *pixels ) 25737117f1b4Smrg{ 25747117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 25753464ebd5Sriastradh teximage(ctx, 3, target, level, internalFormat, width, height, depth, 25763464ebd5Sriastradh border, format, type, pixels); 25777117f1b4Smrg} 25787117f1b4Smrg 25797117f1b4Smrg 25807117f1b4Smrgvoid GLAPIENTRY 25817117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 25827117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 25837117f1b4Smrg GLint border, GLenum format, GLenum type, 25847117f1b4Smrg const GLvoid *pixels ) 25857117f1b4Smrg{ 25867117f1b4Smrg _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 25877117f1b4Smrg depth, border, format, type, pixels); 25887117f1b4Smrg} 25897117f1b4Smrg 25907117f1b4Smrg 2591cdc920a0Smrg#if FEATURE_OES_EGL_image 2592cdc920a0Smrgvoid GLAPIENTRY 2593cdc920a0Smrg_mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) 2594cdc920a0Smrg{ 2595cdc920a0Smrg struct gl_texture_object *texObj; 2596cdc920a0Smrg struct gl_texture_image *texImage; 2597cdc920a0Smrg GET_CURRENT_CONTEXT(ctx); 2598cdc920a0Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2599cdc920a0Smrg 26003464ebd5Sriastradh if (!ctx->Extensions.OES_EGL_image) { 26013464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 26023464ebd5Sriastradh "glEGLImageTargetTexture2DOES(unsupported)"); 26033464ebd5Sriastradh return; 26043464ebd5Sriastradh } 26053464ebd5Sriastradh 2606cdc920a0Smrg if (target != GL_TEXTURE_2D) { 2607cdc920a0Smrg _mesa_error(ctx, GL_INVALID_ENUM, 2608cdc920a0Smrg "glEGLImageTargetTexture2D(target=%d)", target); 2609cdc920a0Smrg return; 2610cdc920a0Smrg } 2611cdc920a0Smrg 26123464ebd5Sriastradh if (ctx->NewState & _NEW_PIXEL) 2613cdc920a0Smrg _mesa_update_state(ctx); 2614cdc920a0Smrg 2615cdc920a0Smrg texObj = _mesa_get_current_tex_object(ctx, target); 2616cdc920a0Smrg _mesa_lock_texture(ctx, texObj); 2617cdc920a0Smrg 2618cdc920a0Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 2619cdc920a0Smrg if (!texImage) { 2620cdc920a0Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D"); 2621cdc920a0Smrg } else { 2622cdc920a0Smrg if (texImage->Data) 2623cdc920a0Smrg ctx->Driver.FreeTexImageData( ctx, texImage ); 2624cdc920a0Smrg 2625cdc920a0Smrg ASSERT(texImage->Data == NULL); 2626cdc920a0Smrg ctx->Driver.EGLImageTargetTexture2D(ctx, target, 2627cdc920a0Smrg texObj, texImage, image); 2628cdc920a0Smrg 2629cdc920a0Smrg /* state update */ 2630cdc920a0Smrg texObj->_Complete = GL_FALSE; 2631cdc920a0Smrg ctx->NewState |= _NEW_TEXTURE; 2632cdc920a0Smrg } 2633cdc920a0Smrg _mesa_unlock_texture(ctx, texObj); 2634cdc920a0Smrg 2635cdc920a0Smrg} 2636cdc920a0Smrg#endif 2637cdc920a0Smrg 26387117f1b4Smrg 26393464ebd5Sriastradh 26403464ebd5Sriastradh/** 26413464ebd5Sriastradh * Implement all the glTexSubImage1/2/3D() functions. 26423464ebd5Sriastradh */ 26433464ebd5Sriastradhstatic void 26443464ebd5Sriastradhtexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 26453464ebd5Sriastradh GLint xoffset, GLint yoffset, GLint zoffset, 26463464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 26473464ebd5Sriastradh GLenum format, GLenum type, const GLvoid *pixels ) 26487117f1b4Smrg{ 26497117f1b4Smrg struct gl_texture_object *texObj; 26504a49301eSmrg struct gl_texture_image *texImage; 26513464ebd5Sriastradh 26527117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 26537117f1b4Smrg 26544a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 26553464ebd5Sriastradh _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n", 26563464ebd5Sriastradh dims, 26574a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 26583464ebd5Sriastradh xoffset, yoffset, zoffset, width, height, depth, 26593464ebd5Sriastradh _mesa_lookup_enum_by_nr(format), 26604a49301eSmrg _mesa_lookup_enum_by_nr(type), pixels); 26614a49301eSmrg 26623464ebd5Sriastradh /* check target (proxies not allowed) */ 26633464ebd5Sriastradh if (!legal_texsubimage_target(ctx, dims, target)) { 26643464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", 26653464ebd5Sriastradh dims, _mesa_lookup_enum_by_nr(target)); 26663464ebd5Sriastradh return; 26673464ebd5Sriastradh } 26687117f1b4Smrg 26693464ebd5Sriastradh if (ctx->NewState & _NEW_PIXEL) 26703464ebd5Sriastradh _mesa_update_state(ctx); 26717117f1b4Smrg 26723464ebd5Sriastradh if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset, 26733464ebd5Sriastradh width, height, depth, format, type)) { 26747117f1b4Smrg return; /* error was detected */ 26757117f1b4Smrg } 26767117f1b4Smrg 26774a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 26787117f1b4Smrg 26797117f1b4Smrg _mesa_lock_texture(ctx, texObj); 26807117f1b4Smrg { 26817117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 26827117f1b4Smrg 26833464ebd5Sriastradh if (subtexture_error_check2(ctx, dims, target, level, 26843464ebd5Sriastradh xoffset, yoffset, zoffset, 26853464ebd5Sriastradh width, height, depth, 26864a49301eSmrg format, type, texImage)) { 26874a49301eSmrg /* error was recorded */ 26887117f1b4Smrg } 26893464ebd5Sriastradh else if (width > 0 && height > 0 && depth > 0) { 26903464ebd5Sriastradh /* If we have a border, offset=-1 is legal. Bias by border width. */ 26913464ebd5Sriastradh switch (dims) { 26923464ebd5Sriastradh case 3: 26933464ebd5Sriastradh zoffset += texImage->Border; 26943464ebd5Sriastradh /* fall-through */ 26953464ebd5Sriastradh case 2: 26963464ebd5Sriastradh yoffset += texImage->Border; 26973464ebd5Sriastradh /* fall-through */ 26983464ebd5Sriastradh case 1: 26993464ebd5Sriastradh xoffset += texImage->Border; 27003464ebd5Sriastradh } 27017117f1b4Smrg 27023464ebd5Sriastradh switch (dims) { 27033464ebd5Sriastradh case 1: 27043464ebd5Sriastradh ctx->Driver.TexSubImage1D(ctx, target, level, 27053464ebd5Sriastradh xoffset, width, 27063464ebd5Sriastradh format, type, pixels, 27073464ebd5Sriastradh &ctx->Unpack, texObj, texImage ); 27083464ebd5Sriastradh break; 27093464ebd5Sriastradh case 2: 27103464ebd5Sriastradh ctx->Driver.TexSubImage2D(ctx, target, level, 27113464ebd5Sriastradh xoffset, yoffset, width, height, 27123464ebd5Sriastradh format, type, pixels, 27133464ebd5Sriastradh &ctx->Unpack, texObj, texImage ); 27143464ebd5Sriastradh break; 27153464ebd5Sriastradh case 3: 27163464ebd5Sriastradh ctx->Driver.TexSubImage3D(ctx, target, level, 27173464ebd5Sriastradh xoffset, yoffset, zoffset, 27183464ebd5Sriastradh width, height, depth, 27193464ebd5Sriastradh format, type, pixels, 27203464ebd5Sriastradh &ctx->Unpack, texObj, texImage ); 27213464ebd5Sriastradh break; 27223464ebd5Sriastradh default: 27233464ebd5Sriastradh _mesa_problem(ctx, "unexpected dims in subteximage()"); 27243464ebd5Sriastradh } 27257117f1b4Smrg 27264a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 27277117f1b4Smrg 27284a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 27294a49301eSmrg } 27307117f1b4Smrg } 27317117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 27327117f1b4Smrg} 27337117f1b4Smrg 27347117f1b4Smrg 27357117f1b4Smrgvoid GLAPIENTRY 27363464ebd5Sriastradh_mesa_TexSubImage1D( GLenum target, GLint level, 27373464ebd5Sriastradh GLint xoffset, GLsizei width, 27387117f1b4Smrg GLenum format, GLenum type, 27397117f1b4Smrg const GLvoid *pixels ) 27407117f1b4Smrg{ 27417117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27423464ebd5Sriastradh texsubimage(ctx, 1, target, level, 27433464ebd5Sriastradh xoffset, 0, 0, 27443464ebd5Sriastradh width, 1, 1, 27453464ebd5Sriastradh format, type, pixels); 27467117f1b4Smrg} 27477117f1b4Smrg 27487117f1b4Smrg 27497117f1b4Smrgvoid GLAPIENTRY 27503464ebd5Sriastradh_mesa_TexSubImage2D( GLenum target, GLint level, 27513464ebd5Sriastradh GLint xoffset, GLint yoffset, 27523464ebd5Sriastradh GLsizei width, GLsizei height, 27537117f1b4Smrg GLenum format, GLenum type, 27547117f1b4Smrg const GLvoid *pixels ) 27557117f1b4Smrg{ 27567117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27573464ebd5Sriastradh texsubimage(ctx, 2, target, level, 27583464ebd5Sriastradh xoffset, yoffset, 0, 27593464ebd5Sriastradh width, height, 1, 27603464ebd5Sriastradh format, type, pixels); 27617117f1b4Smrg} 27627117f1b4Smrg 27637117f1b4Smrg 27647117f1b4Smrg 27657117f1b4Smrgvoid GLAPIENTRY 27663464ebd5Sriastradh_mesa_TexSubImage3D( GLenum target, GLint level, 27673464ebd5Sriastradh GLint xoffset, GLint yoffset, GLint zoffset, 27683464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 27693464ebd5Sriastradh GLenum format, GLenum type, 27703464ebd5Sriastradh const GLvoid *pixels ) 27717117f1b4Smrg{ 27723464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 27733464ebd5Sriastradh texsubimage(ctx, 3, target, level, 27743464ebd5Sriastradh xoffset, yoffset, zoffset, 27753464ebd5Sriastradh width, height, depth, 27763464ebd5Sriastradh format, type, pixels); 27777117f1b4Smrg} 27787117f1b4Smrg 27797117f1b4Smrg 27807117f1b4Smrg 27813464ebd5Sriastradh/** 27823464ebd5Sriastradh * Implement the glCopyTexImage1/2D() functions. 27833464ebd5Sriastradh */ 27843464ebd5Sriastradhstatic void 27853464ebd5Sriastradhcopyteximage(struct gl_context *ctx, GLuint dims, 27863464ebd5Sriastradh GLenum target, GLint level, GLenum internalFormat, 27873464ebd5Sriastradh GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) 27887117f1b4Smrg{ 27897117f1b4Smrg struct gl_texture_object *texObj; 27907117f1b4Smrg struct gl_texture_image *texImage; 2791c1f859d4Smrg const GLuint face = _mesa_tex_target_to_face(target); 27923464ebd5Sriastradh 27937117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 27947117f1b4Smrg 27954a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 27963464ebd5Sriastradh _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n", 27973464ebd5Sriastradh dims, 27984a49301eSmrg _mesa_lookup_enum_by_nr(target), level, 27994a49301eSmrg _mesa_lookup_enum_by_nr(internalFormat), 28004a49301eSmrg x, y, width, height, border); 28014a49301eSmrg 2802c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 28037117f1b4Smrg _mesa_update_state(ctx); 28047117f1b4Smrg 28053464ebd5Sriastradh if (copytexture_error_check(ctx, dims, target, level, internalFormat, 28063464ebd5Sriastradh width, height, border)) 28077117f1b4Smrg return; 28087117f1b4Smrg 28094a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 28107117f1b4Smrg 28117117f1b4Smrg _mesa_lock_texture(ctx, texObj); 28127117f1b4Smrg { 28137117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 28147117f1b4Smrg 28157117f1b4Smrg if (!texImage) { 28163464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); 28177117f1b4Smrg } 28184a49301eSmrg else { 28193464ebd5Sriastradh /* choose actual hw format */ 28203464ebd5Sriastradh gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, 28213464ebd5Sriastradh target, level, 28223464ebd5Sriastradh internalFormat, 28233464ebd5Sriastradh GL_NONE, GL_NONE); 28244a49301eSmrg 28253464ebd5Sriastradh if (legal_texture_size(ctx, texFormat, width, height, 1)) { 28263464ebd5Sriastradh GLint srcX = x, srcY = y, dstX = 0, dstY = 0; 28274a49301eSmrg 28283464ebd5Sriastradh /* Free old texture image */ 28293464ebd5Sriastradh ctx->Driver.FreeTexImageData(ctx, texImage); 28304a49301eSmrg 28313464ebd5Sriastradh _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 28323464ebd5Sriastradh border, internalFormat, texFormat); 28337117f1b4Smrg 28343464ebd5Sriastradh /* Allocate texture memory (no pixel data yet) */ 28353464ebd5Sriastradh if (dims == 1) { 28363464ebd5Sriastradh ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 28373464ebd5Sriastradh width, border, GL_NONE, GL_NONE, NULL, 28383464ebd5Sriastradh &ctx->Unpack, texObj, texImage); 28393464ebd5Sriastradh } 28403464ebd5Sriastradh else { 28413464ebd5Sriastradh ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 28423464ebd5Sriastradh width, height, border, GL_NONE, GL_NONE, 28433464ebd5Sriastradh NULL, &ctx->Unpack, texObj, texImage); 28443464ebd5Sriastradh } 28457117f1b4Smrg 28463464ebd5Sriastradh if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY, 28473464ebd5Sriastradh &width, &height)) { 28483464ebd5Sriastradh if (dims == 1) 28493464ebd5Sriastradh ctx->Driver.CopyTexSubImage1D(ctx, target, level, dstX, 28503464ebd5Sriastradh srcX, srcY, width); 28513464ebd5Sriastradh 28523464ebd5Sriastradh else 28533464ebd5Sriastradh ctx->Driver.CopyTexSubImage2D(ctx, target, level, dstX, dstY, 28543464ebd5Sriastradh srcX, srcY, width, height); 28553464ebd5Sriastradh } 28564a49301eSmrg 28573464ebd5Sriastradh check_gen_mipmap(ctx, target, texObj, level); 28584a49301eSmrg 28593464ebd5Sriastradh update_fbo_texture(ctx, texObj, face, level); 28604a49301eSmrg 28613464ebd5Sriastradh /* state update */ 28623464ebd5Sriastradh texObj->_Complete = GL_FALSE; 28633464ebd5Sriastradh ctx->NewState |= _NEW_TEXTURE; 28643464ebd5Sriastradh } 28653464ebd5Sriastradh else { 28663464ebd5Sriastradh /* probably too large of image */ 28673464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); 28683464ebd5Sriastradh } 28694a49301eSmrg } 28707117f1b4Smrg } 28717117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 28727117f1b4Smrg} 28737117f1b4Smrg 28747117f1b4Smrg 28753464ebd5Sriastradh 28767117f1b4Smrgvoid GLAPIENTRY 28773464ebd5Sriastradh_mesa_CopyTexImage1D( GLenum target, GLint level, 28783464ebd5Sriastradh GLenum internalFormat, 28793464ebd5Sriastradh GLint x, GLint y, 28803464ebd5Sriastradh GLsizei width, GLint border ) 28817117f1b4Smrg{ 28827117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 28833464ebd5Sriastradh copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border); 28843464ebd5Sriastradh} 28857117f1b4Smrg 28867117f1b4Smrg 2887c1f859d4Smrg 28883464ebd5Sriastradhvoid GLAPIENTRY 28893464ebd5Sriastradh_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 28903464ebd5Sriastradh GLint x, GLint y, GLsizei width, GLsizei height, 28913464ebd5Sriastradh GLint border ) 28923464ebd5Sriastradh{ 28933464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 28943464ebd5Sriastradh copyteximage(ctx, 2, target, level, internalFormat, 28953464ebd5Sriastradh x, y, width, height, border); 28967117f1b4Smrg} 28977117f1b4Smrg 28987117f1b4Smrg 28997117f1b4Smrg 29003464ebd5Sriastradh/** 29013464ebd5Sriastradh * Implementation for glCopyTexSubImage1/2/3D() functions. 29023464ebd5Sriastradh */ 29033464ebd5Sriastradhstatic void 29043464ebd5Sriastradhcopytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 29053464ebd5Sriastradh GLint xoffset, GLint yoffset, GLint zoffset, 29063464ebd5Sriastradh GLint x, GLint y, GLsizei width, GLsizei height) 29077117f1b4Smrg{ 29087117f1b4Smrg struct gl_texture_object *texObj; 29097117f1b4Smrg struct gl_texture_image *texImage; 29103464ebd5Sriastradh 29117117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 29127117f1b4Smrg 29134a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 29143464ebd5Sriastradh _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n", 29153464ebd5Sriastradh dims, 29164a49301eSmrg _mesa_lookup_enum_by_nr(target), 29173464ebd5Sriastradh level, xoffset, yoffset, zoffset, x, y, width, height); 29184a49301eSmrg 2919c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 29207117f1b4Smrg _mesa_update_state(ctx); 29217117f1b4Smrg 29223464ebd5Sriastradh if (copytexsubimage_error_check1(ctx, dims, target, level)) 29237117f1b4Smrg return; 29247117f1b4Smrg 29254a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 29267117f1b4Smrg 29277117f1b4Smrg _mesa_lock_texture(ctx, texObj); 29287117f1b4Smrg { 29297117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 29307117f1b4Smrg 29313464ebd5Sriastradh if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset, 29323464ebd5Sriastradh zoffset, width, height, texImage)) { 29333464ebd5Sriastradh /* error was recored */ 29344a49301eSmrg } 29354a49301eSmrg else { 29363464ebd5Sriastradh /* If we have a border, offset=-1 is legal. Bias by border width. */ 29373464ebd5Sriastradh switch (dims) { 29383464ebd5Sriastradh case 3: 29393464ebd5Sriastradh zoffset += texImage->Border; 29403464ebd5Sriastradh /* fall-through */ 29413464ebd5Sriastradh case 2: 29423464ebd5Sriastradh yoffset += texImage->Border; 29433464ebd5Sriastradh /* fall-through */ 29443464ebd5Sriastradh case 1: 29453464ebd5Sriastradh xoffset += texImage->Border; 29463464ebd5Sriastradh } 29474a49301eSmrg 29484a49301eSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 29494a49301eSmrg &width, &height)) { 29503464ebd5Sriastradh switch (dims) { 29513464ebd5Sriastradh case 1: 29523464ebd5Sriastradh ctx->Driver.CopyTexSubImage1D(ctx, target, level, 29533464ebd5Sriastradh xoffset, x, y, width); 29543464ebd5Sriastradh break; 29553464ebd5Sriastradh case 2: 29563464ebd5Sriastradh ctx->Driver.CopyTexSubImage2D(ctx, target, level, 29573464ebd5Sriastradh xoffset, yoffset, 29583464ebd5Sriastradh x, y, width, height); 29593464ebd5Sriastradh break; 29603464ebd5Sriastradh case 3: 29613464ebd5Sriastradh ctx->Driver.CopyTexSubImage3D(ctx, target, level, 29623464ebd5Sriastradh xoffset, yoffset, zoffset, 29633464ebd5Sriastradh x, y, width, height); 29643464ebd5Sriastradh break; 29653464ebd5Sriastradh default: 29663464ebd5Sriastradh _mesa_problem(ctx, "bad dims in copytexsubimage()"); 29673464ebd5Sriastradh } 29687117f1b4Smrg 29694a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 2970c1f859d4Smrg 29714a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 29724a49301eSmrg } 2973c1f859d4Smrg } 29747117f1b4Smrg } 29757117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 29767117f1b4Smrg} 29777117f1b4Smrg 29787117f1b4Smrg 29797117f1b4Smrgvoid GLAPIENTRY 29803464ebd5Sriastradh_mesa_CopyTexSubImage1D( GLenum target, GLint level, 29813464ebd5Sriastradh GLint xoffset, GLint x, GLint y, GLsizei width ) 29827117f1b4Smrg{ 29837117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 29843464ebd5Sriastradh copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1); 29853464ebd5Sriastradh} 29867117f1b4Smrg 29877117f1b4Smrg 2988c1f859d4Smrg 29893464ebd5Sriastradhvoid GLAPIENTRY 29903464ebd5Sriastradh_mesa_CopyTexSubImage2D( GLenum target, GLint level, 29913464ebd5Sriastradh GLint xoffset, GLint yoffset, 29923464ebd5Sriastradh GLint x, GLint y, GLsizei width, GLsizei height ) 29933464ebd5Sriastradh{ 29943464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 29953464ebd5Sriastradh copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y, 29963464ebd5Sriastradh width, height); 29973464ebd5Sriastradh} 29984a49301eSmrg 2999c1f859d4Smrg 30004a49301eSmrg 30013464ebd5Sriastradhvoid GLAPIENTRY 30023464ebd5Sriastradh_mesa_CopyTexSubImage3D( GLenum target, GLint level, 30033464ebd5Sriastradh GLint xoffset, GLint yoffset, GLint zoffset, 30043464ebd5Sriastradh GLint x, GLint y, GLsizei width, GLsizei height ) 30053464ebd5Sriastradh{ 30063464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 30073464ebd5Sriastradh copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, 30083464ebd5Sriastradh x, y, width, height); 30097117f1b4Smrg} 30107117f1b4Smrg 30117117f1b4Smrg 30127117f1b4Smrg 30137117f1b4Smrg 30147117f1b4Smrg/**********************************************************************/ 30157117f1b4Smrg/****** Compressed Textures ******/ 30167117f1b4Smrg/**********************************************************************/ 30177117f1b4Smrg 30187117f1b4Smrg 30194a49301eSmrg/** 30204a49301eSmrg * Return expected size of a compressed texture. 30214a49301eSmrg */ 30224a49301eSmrgstatic GLuint 30234a49301eSmrgcompressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, 30244a49301eSmrg GLenum glformat) 30254a49301eSmrg{ 30264a49301eSmrg gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 30274a49301eSmrg return _mesa_format_image_size(mesaFormat, width, height, depth); 30284a49301eSmrg} 30294a49301eSmrg 30304a49301eSmrg 30314a49301eSmrg/* 30324a49301eSmrg * Return compressed texture block size, in pixels. 30334a49301eSmrg */ 30344a49301eSmrgstatic void 30354a49301eSmrgget_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) 30364a49301eSmrg{ 30374a49301eSmrg gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 30384a49301eSmrg _mesa_get_format_block_size(mesaFormat, bw, bh); 30394a49301eSmrg} 30404a49301eSmrg 30414a49301eSmrg 30427117f1b4Smrg/** 30437117f1b4Smrg * Error checking for glCompressedTexImage[123]D(). 30443464ebd5Sriastradh * \param reason returns reason for error, if any 30457117f1b4Smrg * \return error code or GL_NO_ERROR. 30467117f1b4Smrg */ 30477117f1b4Smrgstatic GLenum 30483464ebd5Sriastradhcompressed_texture_error_check(struct gl_context *ctx, GLint dimensions, 30497117f1b4Smrg GLenum target, GLint level, 30507117f1b4Smrg GLenum internalFormat, GLsizei width, 30517117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 30523464ebd5Sriastradh GLsizei imageSize, char **reason) 30537117f1b4Smrg{ 30543464ebd5Sriastradh const GLenum proxyTarget = get_proxy_target(target); 30553464ebd5Sriastradh const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 30563464ebd5Sriastradh GLint expectedSize; 30573464ebd5Sriastradh GLenum choose_format; 30583464ebd5Sriastradh GLenum choose_type; 30593464ebd5Sriastradh GLenum proxy_format; 30607117f1b4Smrg 30613464ebd5Sriastradh *reason = ""; /* no error */ 30623464ebd5Sriastradh 30633464ebd5Sriastradh if (!target_can_be_compressed(ctx, target, internalFormat)) { 30643464ebd5Sriastradh *reason = "target"; 30657117f1b4Smrg return GL_INVALID_ENUM; 30667117f1b4Smrg } 30677117f1b4Smrg 30687117f1b4Smrg /* This will detect any invalid internalFormat value */ 30693464ebd5Sriastradh if (!_mesa_is_compressed_format(ctx, internalFormat)) { 30703464ebd5Sriastradh *reason = "internalFormat"; 30717117f1b4Smrg return GL_INVALID_ENUM; 30723464ebd5Sriastradh } 30737117f1b4Smrg 30743464ebd5Sriastradh switch (internalFormat) { 30753464ebd5Sriastradh#if FEATURE_ES 30763464ebd5Sriastradh case GL_PALETTE4_RGB8_OES: 30773464ebd5Sriastradh case GL_PALETTE4_RGBA8_OES: 30783464ebd5Sriastradh case GL_PALETTE4_R5_G6_B5_OES: 30793464ebd5Sriastradh case GL_PALETTE4_RGBA4_OES: 30803464ebd5Sriastradh case GL_PALETTE4_RGB5_A1_OES: 30813464ebd5Sriastradh case GL_PALETTE8_RGB8_OES: 30823464ebd5Sriastradh case GL_PALETTE8_RGBA8_OES: 30833464ebd5Sriastradh case GL_PALETTE8_R5_G6_B5_OES: 30843464ebd5Sriastradh case GL_PALETTE8_RGBA4_OES: 30853464ebd5Sriastradh case GL_PALETTE8_RGB5_A1_OES: 30863464ebd5Sriastradh _mesa_cpal_compressed_format_type(internalFormat, &choose_format, 30873464ebd5Sriastradh &choose_type); 30883464ebd5Sriastradh proxy_format = choose_format; 30893464ebd5Sriastradh 30903464ebd5Sriastradh /* check level */ 30913464ebd5Sriastradh if (level > 0 || level < -maxLevels) { 30923464ebd5Sriastradh *reason = "level"; 30933464ebd5Sriastradh return GL_INVALID_VALUE; 30943464ebd5Sriastradh } 30953464ebd5Sriastradh 30963464ebd5Sriastradh if (dimensions != 2) { 30973464ebd5Sriastradh *reason = "compressed paletted textures must be 2D"; 30983464ebd5Sriastradh return GL_INVALID_OPERATION; 30993464ebd5Sriastradh } 31003464ebd5Sriastradh 31013464ebd5Sriastradh /* Figure out the expected texture size (in bytes). This will be 31023464ebd5Sriastradh * checked against the actual size later. 31033464ebd5Sriastradh */ 31043464ebd5Sriastradh expectedSize = _mesa_cpal_compressed_size(level, internalFormat, 31053464ebd5Sriastradh width, height); 31063464ebd5Sriastradh 31073464ebd5Sriastradh /* This is for the benefit of the TestProxyTexImage below. It expects 31083464ebd5Sriastradh * level to be non-negative. OES_compressed_paletted_texture uses a 31093464ebd5Sriastradh * weird mechanism where the level specified to glCompressedTexImage2D 31103464ebd5Sriastradh * is -(n-1) number of levels in the texture, and the data specifies the 31113464ebd5Sriastradh * complete mipmap stack. This is done to ensure the palette is the 31123464ebd5Sriastradh * same for all levels. 31133464ebd5Sriastradh */ 31143464ebd5Sriastradh level = -level; 31153464ebd5Sriastradh break; 31163464ebd5Sriastradh#endif 31177117f1b4Smrg 31183464ebd5Sriastradh default: 31193464ebd5Sriastradh choose_format = GL_NONE; 31203464ebd5Sriastradh choose_type = GL_NONE; 31213464ebd5Sriastradh proxy_format = internalFormat; 31227117f1b4Smrg 31233464ebd5Sriastradh /* check level */ 31243464ebd5Sriastradh if (level < 0 || level >= maxLevels) { 31253464ebd5Sriastradh *reason = "level"; 31263464ebd5Sriastradh return GL_INVALID_VALUE; 31273464ebd5Sriastradh } 31287117f1b4Smrg 31293464ebd5Sriastradh /* Figure out the expected texture size (in bytes). This will be 31303464ebd5Sriastradh * checked against the actual size later. 31313464ebd5Sriastradh */ 31323464ebd5Sriastradh expectedSize = compressed_tex_size(width, height, depth, internalFormat); 31333464ebd5Sriastradh break; 31343464ebd5Sriastradh } 31353464ebd5Sriastradh 31363464ebd5Sriastradh /* This should really never fail */ 31373464ebd5Sriastradh if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 31383464ebd5Sriastradh *reason = "internalFormat"; 31393464ebd5Sriastradh return GL_INVALID_ENUM; 31403464ebd5Sriastradh } 31417117f1b4Smrg 31423464ebd5Sriastradh /* No compressed formats support borders at this time */ 31433464ebd5Sriastradh if (border != 0) { 31443464ebd5Sriastradh *reason = "border != 0"; 31457117f1b4Smrg return GL_INVALID_VALUE; 31463464ebd5Sriastradh } 31477117f1b4Smrg 31487117f1b4Smrg /* For cube map, width must equal height */ 31497117f1b4Smrg if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 31503464ebd5Sriastradh target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) { 31513464ebd5Sriastradh *reason = "width != height"; 31527117f1b4Smrg return GL_INVALID_VALUE; 31533464ebd5Sriastradh } 31547117f1b4Smrg 31553464ebd5Sriastradh /* check image size against compression block size */ 31563464ebd5Sriastradh { 31573464ebd5Sriastradh gl_format texFormat = 31583464ebd5Sriastradh ctx->Driver.ChooseTextureFormat(ctx, proxy_format, 31593464ebd5Sriastradh choose_format, choose_type); 31603464ebd5Sriastradh GLuint bw, bh; 31617117f1b4Smrg 31623464ebd5Sriastradh _mesa_get_format_block_size(texFormat, &bw, &bh); 31633464ebd5Sriastradh if ((width > bw && width % bw > 0) || 31643464ebd5Sriastradh (height > bh && height % bh > 0)) { 31653464ebd5Sriastradh /* 31663464ebd5Sriastradh * Per GL_ARB_texture_compression: GL_INVALID_OPERATION is 31673464ebd5Sriastradh * generated [...] if any parameter combinations are not 31683464ebd5Sriastradh * supported by the specific compressed internal format. 31693464ebd5Sriastradh */ 31703464ebd5Sriastradh *reason = "invalid width or height for compression format"; 31713464ebd5Sriastradh return GL_INVALID_OPERATION; 31723464ebd5Sriastradh } 31733464ebd5Sriastradh } 31743464ebd5Sriastradh 31753464ebd5Sriastradh /* check image sizes */ 31763464ebd5Sriastradh if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, 31773464ebd5Sriastradh proxy_format, choose_format, 31783464ebd5Sriastradh choose_type, 31793464ebd5Sriastradh width, height, depth, border)) { 31803464ebd5Sriastradh /* See error comment above */ 31813464ebd5Sriastradh *reason = "invalid width, height or format"; 31827117f1b4Smrg return GL_INVALID_OPERATION; 31837117f1b4Smrg } 31843464ebd5Sriastradh 31853464ebd5Sriastradh /* check image size in bytes */ 31863464ebd5Sriastradh if (expectedSize != imageSize) { 31873464ebd5Sriastradh /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] 31883464ebd5Sriastradh * if <imageSize> is not consistent with the format, dimensions, and 31893464ebd5Sriastradh * contents of the specified image. 31903464ebd5Sriastradh */ 31913464ebd5Sriastradh *reason = "imageSize inconsistant with width/height/format"; 31923464ebd5Sriastradh return GL_INVALID_VALUE; 31933464ebd5Sriastradh } 31947117f1b4Smrg 31957117f1b4Smrg return GL_NO_ERROR; 31967117f1b4Smrg} 31977117f1b4Smrg 31987117f1b4Smrg 31997117f1b4Smrg/** 32007117f1b4Smrg * Error checking for glCompressedTexSubImage[123]D(). 32017117f1b4Smrg * \warning There are some bad assumptions here about the size of compressed 32027117f1b4Smrg * texture tiles (multiple of 4) used to test the validity of the 32037117f1b4Smrg * offset and size parameters. 32047117f1b4Smrg * \return error code or GL_NO_ERROR. 32057117f1b4Smrg */ 32067117f1b4Smrgstatic GLenum 32073464ebd5Sriastradhcompressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, 32087117f1b4Smrg GLenum target, GLint level, 32097117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 32107117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 32117117f1b4Smrg GLenum format, GLsizei imageSize) 32127117f1b4Smrg{ 32137117f1b4Smrg GLint expectedSize, maxLevels = 0, maxTextureSize; 32144a49301eSmrg GLuint bw, bh; 32157117f1b4Smrg (void) zoffset; 32167117f1b4Smrg 32177117f1b4Smrg if (dimensions == 1) { 32187117f1b4Smrg /* 1D compressed textures not allowed */ 32197117f1b4Smrg return GL_INVALID_ENUM; 32207117f1b4Smrg } 32217117f1b4Smrg else if (dimensions == 2) { 32227117f1b4Smrg if (target == GL_PROXY_TEXTURE_2D) { 32237117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 32247117f1b4Smrg } 32257117f1b4Smrg else if (target == GL_TEXTURE_2D) { 32267117f1b4Smrg maxLevels = ctx->Const.MaxTextureLevels; 32277117f1b4Smrg } 32287117f1b4Smrg else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 32297117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 32307117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32317117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 32327117f1b4Smrg } 32337117f1b4Smrg else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 32347117f1b4Smrg target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 32357117f1b4Smrg if (!ctx->Extensions.ARB_texture_cube_map) 32367117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32377117f1b4Smrg maxLevels = ctx->Const.MaxCubeTextureLevels; 32387117f1b4Smrg } 32397117f1b4Smrg else { 32407117f1b4Smrg return GL_INVALID_ENUM; /*target*/ 32417117f1b4Smrg } 32427117f1b4Smrg } 32437117f1b4Smrg else if (dimensions == 3) { 32447117f1b4Smrg /* 3D compressed textures not allowed */ 32457117f1b4Smrg return GL_INVALID_ENUM; 32467117f1b4Smrg } 32477117f1b4Smrg 32487117f1b4Smrg maxTextureSize = 1 << (maxLevels - 1); 32497117f1b4Smrg 32507117f1b4Smrg /* this will catch any invalid compressed format token */ 32513464ebd5Sriastradh if (!_mesa_is_compressed_format(ctx, format)) 32527117f1b4Smrg return GL_INVALID_ENUM; 32537117f1b4Smrg 32547117f1b4Smrg if (width < 1 || width > maxTextureSize) 32557117f1b4Smrg return GL_INVALID_VALUE; 32567117f1b4Smrg 32577117f1b4Smrg if ((height < 1 || height > maxTextureSize) 32587117f1b4Smrg && dimensions > 1) 32597117f1b4Smrg return GL_INVALID_VALUE; 32607117f1b4Smrg 32617117f1b4Smrg if (level < 0 || level >= maxLevels) 32627117f1b4Smrg return GL_INVALID_VALUE; 32637117f1b4Smrg 32644a49301eSmrg /* 32654a49301eSmrg * do checks which depend on compression block size 32667117f1b4Smrg */ 32674a49301eSmrg get_compressed_block_size(format, &bw, &bh); 32684a49301eSmrg 32694a49301eSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0)) 32707117f1b4Smrg return GL_INVALID_VALUE; 32717117f1b4Smrg 32724a49301eSmrg if ((width % bw != 0) && width != 2 && width != 1) 32737117f1b4Smrg return GL_INVALID_VALUE; 32747117f1b4Smrg 32754a49301eSmrg if ((height % bh != 0) && height != 2 && height != 1) 32767117f1b4Smrg return GL_INVALID_VALUE; 32777117f1b4Smrg 32784a49301eSmrg expectedSize = compressed_tex_size(width, height, depth, format); 32797117f1b4Smrg if (expectedSize != imageSize) 32807117f1b4Smrg return GL_INVALID_VALUE; 32817117f1b4Smrg 32827117f1b4Smrg return GL_NO_ERROR; 32837117f1b4Smrg} 32847117f1b4Smrg 32857117f1b4Smrg 32864a49301eSmrg/** 32874a49301eSmrg * Do second part of glCompressedTexSubImage error checking. 32884a49301eSmrg * \return GL_TRUE if error found, GL_FALSE otherwise. 32894a49301eSmrg */ 32904a49301eSmrgstatic GLboolean 32913464ebd5Sriastradhcompressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, 32924a49301eSmrg GLsizei width, GLsizei height, 32934a49301eSmrg GLsizei depth, GLenum format, 32944a49301eSmrg struct gl_texture_image *texImage) 32954a49301eSmrg{ 32964a49301eSmrg 32974a49301eSmrg if ((GLint) format != texImage->InternalFormat) { 32984a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 32994a49301eSmrg "glCompressedTexSubImage%uD(format=0x%x)", dims, format); 33004a49301eSmrg return GL_TRUE; 33014a49301eSmrg } 33024a49301eSmrg 33034a49301eSmrg if (((width == 1 || width == 2) && 3304cdc920a0Smrg width != (GLsizei) texImage->Width) || 3305cdc920a0Smrg (width > (GLsizei) texImage->Width)) { 33064a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 33074a49301eSmrg "glCompressedTexSubImage%uD(width=%d)", dims, width); 33084a49301eSmrg return GL_TRUE; 33094a49301eSmrg } 33104a49301eSmrg 33114a49301eSmrg if (dims >= 2) { 33124a49301eSmrg if (((height == 1 || height == 2) && 3313cdc920a0Smrg height != (GLsizei) texImage->Height) || 3314cdc920a0Smrg (height > (GLsizei) texImage->Height)) { 33154a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 33164a49301eSmrg "glCompressedTexSubImage%uD(height=%d)", dims, height); 33174a49301eSmrg return GL_TRUE; 33184a49301eSmrg } 33194a49301eSmrg } 33204a49301eSmrg 33214a49301eSmrg if (dims >= 3) { 33224a49301eSmrg if (((depth == 1 || depth == 2) && 3323cdc920a0Smrg depth != (GLsizei) texImage->Depth) || 3324cdc920a0Smrg (depth > (GLsizei) texImage->Depth)) { 33254a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 33264a49301eSmrg "glCompressedTexSubImage%uD(depth=%d)", dims, depth); 33274a49301eSmrg return GL_TRUE; 33284a49301eSmrg } 33294a49301eSmrg } 33304a49301eSmrg 33313464ebd5Sriastradh return GL_FALSE; 33323464ebd5Sriastradh} 33334a49301eSmrg 33344a49301eSmrg 33353464ebd5Sriastradh/** 33363464ebd5Sriastradh * Implementation of the glCompressedTexImage1/2/3D() functions. 33373464ebd5Sriastradh */ 33383464ebd5Sriastradhstatic void 33393464ebd5Sriastradhcompressedteximage(struct gl_context *ctx, GLuint dims, 33403464ebd5Sriastradh GLenum target, GLint level, 33413464ebd5Sriastradh GLenum internalFormat, GLsizei width, 33423464ebd5Sriastradh GLsizei height, GLsizei depth, GLint border, 33433464ebd5Sriastradh GLsizei imageSize, const GLvoid *data) 33443464ebd5Sriastradh{ 33453464ebd5Sriastradh GLenum error; 33463464ebd5Sriastradh char *reason = ""; 33477117f1b4Smrg 33483464ebd5Sriastradh ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 33497117f1b4Smrg 33503464ebd5Sriastradh if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 33513464ebd5Sriastradh _mesa_debug(ctx, 33523464ebd5Sriastradh "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n", 33533464ebd5Sriastradh dims, 33543464ebd5Sriastradh _mesa_lookup_enum_by_nr(target), level, 33553464ebd5Sriastradh _mesa_lookup_enum_by_nr(internalFormat), 33563464ebd5Sriastradh width, height, depth, border, imageSize, data); 33577117f1b4Smrg 33583464ebd5Sriastradh /* check target */ 33593464ebd5Sriastradh if (!legal_teximage_target(ctx, dims, target)) { 33603464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)", 33613464ebd5Sriastradh dims, _mesa_lookup_enum_by_nr(target)); 33623464ebd5Sriastradh return; 33637117f1b4Smrg } 33644a49301eSmrg 33653464ebd5Sriastradh error = compressed_texture_error_check(ctx, dims, target, level, 33663464ebd5Sriastradh internalFormat, width, height, depth, 33673464ebd5Sriastradh border, imageSize, &reason); 33687117f1b4Smrg 33693464ebd5Sriastradh if (error) { 33703464ebd5Sriastradh _mesa_error(ctx, error, "glCompressedTexImage%uD(%s)", dims, reason); 33717117f1b4Smrg return; 33727117f1b4Smrg } 33737117f1b4Smrg 33743464ebd5Sriastradh#if FEATURE_ES 33753464ebd5Sriastradh /* XXX this is kind of a hack */ 33763464ebd5Sriastradh if (dims == 2) { 33773464ebd5Sriastradh switch (internalFormat) { 33783464ebd5Sriastradh case GL_PALETTE4_RGB8_OES: 33793464ebd5Sriastradh case GL_PALETTE4_RGBA8_OES: 33803464ebd5Sriastradh case GL_PALETTE4_R5_G6_B5_OES: 33813464ebd5Sriastradh case GL_PALETTE4_RGBA4_OES: 33823464ebd5Sriastradh case GL_PALETTE4_RGB5_A1_OES: 33833464ebd5Sriastradh case GL_PALETTE8_RGB8_OES: 33843464ebd5Sriastradh case GL_PALETTE8_RGBA8_OES: 33853464ebd5Sriastradh case GL_PALETTE8_R5_G6_B5_OES: 33863464ebd5Sriastradh case GL_PALETTE8_RGBA4_OES: 33873464ebd5Sriastradh case GL_PALETTE8_RGB5_A1_OES: 33883464ebd5Sriastradh _mesa_cpal_compressed_teximage2d(target, level, internalFormat, 33893464ebd5Sriastradh width, height, imageSize, data); 33903464ebd5Sriastradh return; 33913464ebd5Sriastradh } 33923464ebd5Sriastradh } 33933464ebd5Sriastradh#endif 33947117f1b4Smrg 33953464ebd5Sriastradh if (_mesa_is_proxy_texture(target)) { 33963464ebd5Sriastradh /* Proxy texture: just check for errors and update proxy state */ 33973464ebd5Sriastradh struct gl_texture_image *texImage; 33987117f1b4Smrg 33993464ebd5Sriastradh if (!error) { 34003464ebd5Sriastradh struct gl_texture_object *texObj = 34013464ebd5Sriastradh _mesa_get_current_tex_object(ctx, target); 34023464ebd5Sriastradh gl_format texFormat = 34033464ebd5Sriastradh _mesa_choose_texture_format(ctx, texObj, target, level, 34043464ebd5Sriastradh internalFormat, GL_NONE, GL_NONE); 34053464ebd5Sriastradh if (!legal_texture_size(ctx, texFormat, width, height, depth)) { 34063464ebd5Sriastradh error = GL_OUT_OF_MEMORY; 34073464ebd5Sriastradh } 34083464ebd5Sriastradh } 34094a49301eSmrg 34103464ebd5Sriastradh texImage = _mesa_get_proxy_tex_image(ctx, target, level); 34113464ebd5Sriastradh if (texImage) { 34123464ebd5Sriastradh if (error) { 34133464ebd5Sriastradh /* if error, clear all proxy texture image parameters */ 34143464ebd5Sriastradh clear_teximage_fields(texImage); 34153464ebd5Sriastradh } 34163464ebd5Sriastradh else { 34173464ebd5Sriastradh /* no error: store the teximage parameters */ 34183464ebd5Sriastradh _mesa_init_teximage_fields(ctx, target, texImage, width, height, 34193464ebd5Sriastradh depth, border, internalFormat, 34203464ebd5Sriastradh MESA_FORMAT_NONE); 34213464ebd5Sriastradh } 34223464ebd5Sriastradh } 34233464ebd5Sriastradh } 34243464ebd5Sriastradh else { 34257117f1b4Smrg /* non-proxy target */ 34267117f1b4Smrg struct gl_texture_object *texObj; 34277117f1b4Smrg struct gl_texture_image *texImage; 34284a49301eSmrg 34297117f1b4Smrg if (error) { 34303464ebd5Sriastradh _mesa_error(ctx, error, "glCompressedTexImage%uD", dims); 34317117f1b4Smrg return; 34327117f1b4Smrg } 34337117f1b4Smrg 34344a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 34357117f1b4Smrg 34367117f1b4Smrg _mesa_lock_texture(ctx, texObj); 34377117f1b4Smrg { 34387117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 34397117f1b4Smrg if (!texImage) { 34403464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, 34413464ebd5Sriastradh "glCompressedTexImage%uD", dims); 34427117f1b4Smrg } 34434a49301eSmrg else { 34443464ebd5Sriastradh gl_format texFormat; 34453464ebd5Sriastradh 34464a49301eSmrg if (texImage->Data) { 34474a49301eSmrg ctx->Driver.FreeTexImageData( ctx, texImage ); 34484a49301eSmrg } 34494a49301eSmrg ASSERT(texImage->Data == NULL); 34504a49301eSmrg 34513464ebd5Sriastradh texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 34523464ebd5Sriastradh internalFormat, GL_NONE, 34533464ebd5Sriastradh GL_NONE); 34543464ebd5Sriastradh 34553464ebd5Sriastradh if (legal_texture_size(ctx, texFormat, width, height, depth)) { 34563464ebd5Sriastradh _mesa_init_teximage_fields(ctx, target, texImage, 34573464ebd5Sriastradh width, height, depth, 34583464ebd5Sriastradh border, internalFormat, texFormat); 34593464ebd5Sriastradh 34603464ebd5Sriastradh switch (dims) { 34613464ebd5Sriastradh case 1: 34623464ebd5Sriastradh ASSERT(ctx->Driver.CompressedTexImage1D); 34633464ebd5Sriastradh ctx->Driver.CompressedTexImage1D(ctx, target, level, 34643464ebd5Sriastradh internalFormat, 34653464ebd5Sriastradh width, 34663464ebd5Sriastradh border, imageSize, data, 34673464ebd5Sriastradh texObj, texImage); 34683464ebd5Sriastradh break; 34693464ebd5Sriastradh case 2: 34703464ebd5Sriastradh ASSERT(ctx->Driver.CompressedTexImage2D); 34713464ebd5Sriastradh ctx->Driver.CompressedTexImage2D(ctx, target, level, 34723464ebd5Sriastradh internalFormat, 34733464ebd5Sriastradh width, height, 34743464ebd5Sriastradh border, imageSize, data, 34753464ebd5Sriastradh texObj, texImage); 34763464ebd5Sriastradh break; 34773464ebd5Sriastradh case 3: 34783464ebd5Sriastradh ASSERT(ctx->Driver.CompressedTexImage3D); 34793464ebd5Sriastradh ctx->Driver.CompressedTexImage3D(ctx, target, level, 34803464ebd5Sriastradh internalFormat, 34813464ebd5Sriastradh width, height, depth, 34823464ebd5Sriastradh border, imageSize, data, 34833464ebd5Sriastradh texObj, texImage); 34843464ebd5Sriastradh break; 34853464ebd5Sriastradh default: 34863464ebd5Sriastradh _mesa_problem(ctx, "bad dims in compressedteximage"); 34873464ebd5Sriastradh } 34884a49301eSmrg 34893464ebd5Sriastradh check_gen_mipmap(ctx, target, texObj, level); 34904a49301eSmrg 34913464ebd5Sriastradh /* state update */ 34923464ebd5Sriastradh texObj->_Complete = GL_FALSE; 34933464ebd5Sriastradh ctx->NewState |= _NEW_TEXTURE; 34943464ebd5Sriastradh } 34953464ebd5Sriastradh else { 34963464ebd5Sriastradh _mesa_error(ctx, GL_OUT_OF_MEMORY, 34973464ebd5Sriastradh "glCompressedTexImage%uD", dims); 34983464ebd5Sriastradh } 34994a49301eSmrg } 35004a49301eSmrg } 35017117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 35027117f1b4Smrg } 35033464ebd5Sriastradh} 35044a49301eSmrg 35057117f1b4Smrg 35063464ebd5Sriastradhvoid GLAPIENTRY 35073464ebd5Sriastradh_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 35083464ebd5Sriastradh GLenum internalFormat, GLsizei width, 35093464ebd5Sriastradh GLint border, GLsizei imageSize, 35103464ebd5Sriastradh const GLvoid *data) 35113464ebd5Sriastradh{ 35123464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 35133464ebd5Sriastradh compressedteximage(ctx, 1, target, level, internalFormat, 35143464ebd5Sriastradh width, 1, 1, border, imageSize, data); 35153464ebd5Sriastradh} 35163464ebd5Sriastradh 35173464ebd5Sriastradh 35183464ebd5Sriastradhvoid GLAPIENTRY 35193464ebd5Sriastradh_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 35203464ebd5Sriastradh GLenum internalFormat, GLsizei width, 35213464ebd5Sriastradh GLsizei height, GLint border, GLsizei imageSize, 35223464ebd5Sriastradh const GLvoid *data) 35233464ebd5Sriastradh{ 35243464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 35253464ebd5Sriastradh compressedteximage(ctx, 2, target, level, internalFormat, 35263464ebd5Sriastradh width, height, 1, border, imageSize, data); 35277117f1b4Smrg} 35287117f1b4Smrg 35297117f1b4Smrg 35307117f1b4Smrgvoid GLAPIENTRY 35317117f1b4Smrg_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 35327117f1b4Smrg GLenum internalFormat, GLsizei width, 35337117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 35347117f1b4Smrg GLsizei imageSize, const GLvoid *data) 35357117f1b4Smrg{ 35367117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35373464ebd5Sriastradh compressedteximage(ctx, 3, target, level, internalFormat, 35383464ebd5Sriastradh width, height, depth, border, imageSize, data); 35397117f1b4Smrg} 35407117f1b4Smrg 35417117f1b4Smrg 35424a49301eSmrg/** 35434a49301eSmrg * Common helper for glCompressedTexSubImage1/2/3D(). 35444a49301eSmrg */ 35454a49301eSmrgstatic void 35464a49301eSmrgcompressed_tex_sub_image(GLuint dims, GLenum target, GLint level, 35474a49301eSmrg GLint xoffset, GLint yoffset, GLint zoffset, 35484a49301eSmrg GLsizei width, GLsizei height, GLsizei depth, 35494a49301eSmrg GLenum format, GLsizei imageSize, const GLvoid *data) 35507117f1b4Smrg{ 35517117f1b4Smrg struct gl_texture_object *texObj; 35527117f1b4Smrg struct gl_texture_image *texImage; 35537117f1b4Smrg GLenum error; 35547117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 35557117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 35567117f1b4Smrg 35574a49301eSmrg error = compressed_subtexture_error_check(ctx, dims, target, level, 35587117f1b4Smrg xoffset, 0, 0, /* pos */ 35594a49301eSmrg width, height, depth, /* size */ 35607117f1b4Smrg format, imageSize); 35617117f1b4Smrg if (error) { 35624a49301eSmrg _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims); 35637117f1b4Smrg return; 35647117f1b4Smrg } 35657117f1b4Smrg 35664a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 35674a49301eSmrg 35687117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35697117f1b4Smrg { 35707117f1b4Smrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 35717117f1b4Smrg assert(texImage); 35727117f1b4Smrg 35734a49301eSmrg if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, 35744a49301eSmrg format, texImage)) { 35754a49301eSmrg /* error was recorded */ 35764a49301eSmrg } 35774a49301eSmrg else if (width > 0 && height > 0 && depth > 0) { 35784a49301eSmrg switch (dims) { 35794a49301eSmrg case 1: 35804a49301eSmrg if (ctx->Driver.CompressedTexSubImage1D) { 35814a49301eSmrg ctx->Driver.CompressedTexSubImage1D(ctx, target, level, 35824a49301eSmrg xoffset, width, 35834a49301eSmrg format, imageSize, data, 35844a49301eSmrg texObj, texImage); 35854a49301eSmrg } 35864a49301eSmrg break; 35874a49301eSmrg case 2: 35884a49301eSmrg if (ctx->Driver.CompressedTexSubImage2D) { 35894a49301eSmrg ctx->Driver.CompressedTexSubImage2D(ctx, target, level, 35904a49301eSmrg xoffset, yoffset, 35914a49301eSmrg width, height, 35924a49301eSmrg format, imageSize, data, 35934a49301eSmrg texObj, texImage); 35944a49301eSmrg } 35954a49301eSmrg break; 35964a49301eSmrg case 3: 35974a49301eSmrg if (ctx->Driver.CompressedTexSubImage3D) { 35984a49301eSmrg ctx->Driver.CompressedTexSubImage3D(ctx, target, level, 35994a49301eSmrg xoffset, yoffset, zoffset, 36004a49301eSmrg width, height, depth, 36014a49301eSmrg format, imageSize, data, 36024a49301eSmrg texObj, texImage); 36034a49301eSmrg } 36044a49301eSmrg break; 36054a49301eSmrg default: 36064a49301eSmrg ; 36074a49301eSmrg } 36087117f1b4Smrg 36094a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 36107117f1b4Smrg 36114a49301eSmrg ctx->NewState |= _NEW_TEXTURE; 36127117f1b4Smrg } 36137117f1b4Smrg } 36147117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36157117f1b4Smrg} 36167117f1b4Smrg 36177117f1b4Smrg 36184a49301eSmrgvoid GLAPIENTRY 36194a49301eSmrg_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 36204a49301eSmrg GLsizei width, GLenum format, 36214a49301eSmrg GLsizei imageSize, const GLvoid *data) 36224a49301eSmrg{ 36234a49301eSmrg compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1, 36244a49301eSmrg format, imageSize, data); 36254a49301eSmrg} 36264a49301eSmrg 36274a49301eSmrg 36287117f1b4Smrgvoid GLAPIENTRY 36297117f1b4Smrg_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 36307117f1b4Smrg GLint yoffset, GLsizei width, GLsizei height, 36317117f1b4Smrg GLenum format, GLsizei imageSize, 36327117f1b4Smrg const GLvoid *data) 36337117f1b4Smrg{ 36344a49301eSmrg compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0, 36354a49301eSmrg width, height, 1, format, imageSize, data); 36367117f1b4Smrg} 36377117f1b4Smrg 36387117f1b4Smrg 36397117f1b4Smrgvoid GLAPIENTRY 36407117f1b4Smrg_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 36417117f1b4Smrg GLint yoffset, GLint zoffset, GLsizei width, 36427117f1b4Smrg GLsizei height, GLsizei depth, GLenum format, 36437117f1b4Smrg GLsizei imageSize, const GLvoid *data) 36447117f1b4Smrg{ 36454a49301eSmrg compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset, 36464a49301eSmrg width, height, depth, format, imageSize, data); 36477117f1b4Smrg} 36487117f1b4Smrg 36497117f1b4Smrg 36503464ebd5Sriastradh/** 36513464ebd5Sriastradh * Helper for glTexBuffer(). Check if internalFormat is legal. If so, 36523464ebd5Sriastradh * return the basic data type and number of components for the format. 36533464ebd5Sriastradh * \param return GL_TRUE if internalFormat is legal, GL_FALSE otherwise 36543464ebd5Sriastradh */ 36553464ebd5Sriastradhstatic GLboolean 36563464ebd5Sriastradhget_sized_format_info(const struct gl_context *ctx, GLenum internalFormat, 36573464ebd5Sriastradh GLenum *datatype, GLuint *components) 36583464ebd5Sriastradh{ 36593464ebd5Sriastradh switch (internalFormat) { 36603464ebd5Sriastradh case GL_ALPHA8: 36613464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 36623464ebd5Sriastradh *components = 1; 36633464ebd5Sriastradh break; 36643464ebd5Sriastradh case GL_ALPHA16: 36653464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 36663464ebd5Sriastradh *components = 1; 36673464ebd5Sriastradh break; 36683464ebd5Sriastradh case GL_ALPHA16F_ARB: 36693464ebd5Sriastradh *datatype = GL_HALF_FLOAT; 36703464ebd5Sriastradh *components = 1; 36713464ebd5Sriastradh break; 36723464ebd5Sriastradh case GL_ALPHA32F_ARB: 36733464ebd5Sriastradh *datatype = GL_FLOAT; 36743464ebd5Sriastradh *components = 1; 36753464ebd5Sriastradh break; 36763464ebd5Sriastradh case GL_ALPHA8I_EXT: 36773464ebd5Sriastradh *datatype = GL_BYTE; 36783464ebd5Sriastradh *components = 1; 36793464ebd5Sriastradh break; 36803464ebd5Sriastradh case GL_ALPHA16I_EXT: 36813464ebd5Sriastradh *datatype = GL_SHORT; 36823464ebd5Sriastradh *components = 1; 36833464ebd5Sriastradh break; 36843464ebd5Sriastradh case GL_ALPHA32I_EXT: 36853464ebd5Sriastradh *datatype = GL_INT; 36863464ebd5Sriastradh *components = 1; 36873464ebd5Sriastradh break; 36883464ebd5Sriastradh case GL_ALPHA8UI_EXT: 36893464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 36903464ebd5Sriastradh *components = 1; 36913464ebd5Sriastradh break; 36923464ebd5Sriastradh case GL_ALPHA16UI_EXT: 36933464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 36943464ebd5Sriastradh *components = 1; 36953464ebd5Sriastradh break; 36963464ebd5Sriastradh case GL_ALPHA32UI_EXT: 36973464ebd5Sriastradh *datatype = GL_UNSIGNED_INT; 36983464ebd5Sriastradh *components = 1; 36993464ebd5Sriastradh break; 37003464ebd5Sriastradh case GL_LUMINANCE8: 37013464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 37023464ebd5Sriastradh *components = 1; 37033464ebd5Sriastradh break; 37043464ebd5Sriastradh case GL_LUMINANCE16: 37053464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 37063464ebd5Sriastradh *components = 1; 37073464ebd5Sriastradh break; 37083464ebd5Sriastradh case GL_LUMINANCE16F_ARB: 37093464ebd5Sriastradh *datatype = GL_HALF_FLOAT; 37103464ebd5Sriastradh *components = 1; 37113464ebd5Sriastradh break; 37123464ebd5Sriastradh case GL_LUMINANCE32F_ARB: 37133464ebd5Sriastradh *datatype = GL_FLOAT; 37143464ebd5Sriastradh *components = 1; 37153464ebd5Sriastradh break; 37163464ebd5Sriastradh case GL_LUMINANCE8I_EXT: 37173464ebd5Sriastradh *datatype = GL_BYTE; 37183464ebd5Sriastradh *components = 1; 37193464ebd5Sriastradh break; 37203464ebd5Sriastradh case GL_LUMINANCE16I_EXT: 37213464ebd5Sriastradh *datatype = GL_SHORT; 37223464ebd5Sriastradh *components = 1; 37233464ebd5Sriastradh break; 37243464ebd5Sriastradh case GL_LUMINANCE32I_EXT: 37253464ebd5Sriastradh *datatype = GL_INT; 37263464ebd5Sriastradh *components = 1; 37273464ebd5Sriastradh break; 37283464ebd5Sriastradh case GL_LUMINANCE8UI_EXT: 37293464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 37303464ebd5Sriastradh *components = 1; 37313464ebd5Sriastradh break; 37323464ebd5Sriastradh case GL_LUMINANCE16UI_EXT: 37333464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 37343464ebd5Sriastradh *components = 1; 37353464ebd5Sriastradh break; 37363464ebd5Sriastradh case GL_LUMINANCE32UI_EXT: 37373464ebd5Sriastradh *datatype = GL_UNSIGNED_INT; 37383464ebd5Sriastradh *components = 1; 37393464ebd5Sriastradh break; 37403464ebd5Sriastradh case GL_LUMINANCE8_ALPHA8: 37413464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 37423464ebd5Sriastradh *components = 2; 37433464ebd5Sriastradh break; 37443464ebd5Sriastradh case GL_LUMINANCE16_ALPHA16: 37453464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 37463464ebd5Sriastradh *components = 2; 37473464ebd5Sriastradh break; 37483464ebd5Sriastradh case GL_LUMINANCE_ALPHA16F_ARB: 37493464ebd5Sriastradh *datatype = GL_HALF_FLOAT; 37503464ebd5Sriastradh *components = 2; 37513464ebd5Sriastradh break; 37523464ebd5Sriastradh case GL_LUMINANCE_ALPHA32F_ARB: 37533464ebd5Sriastradh *datatype = GL_FLOAT; 37543464ebd5Sriastradh *components = 2; 37553464ebd5Sriastradh break; 37563464ebd5Sriastradh case GL_LUMINANCE_ALPHA8I_EXT: 37573464ebd5Sriastradh *datatype = GL_BYTE; 37583464ebd5Sriastradh *components = 2; 37593464ebd5Sriastradh break; 37603464ebd5Sriastradh case GL_LUMINANCE_ALPHA16I_EXT: 37613464ebd5Sriastradh *datatype = GL_SHORT; 37623464ebd5Sriastradh *components = 2; 37633464ebd5Sriastradh break; 37643464ebd5Sriastradh case GL_LUMINANCE_ALPHA32I_EXT: 37653464ebd5Sriastradh *datatype = GL_INT; 37663464ebd5Sriastradh *components = 2; 37673464ebd5Sriastradh break; 37683464ebd5Sriastradh case GL_LUMINANCE_ALPHA8UI_EXT: 37693464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 37703464ebd5Sriastradh *components = 2; 37713464ebd5Sriastradh break; 37723464ebd5Sriastradh case GL_LUMINANCE_ALPHA16UI_EXT: 37733464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 37743464ebd5Sriastradh *components = 2; 37753464ebd5Sriastradh break; 37763464ebd5Sriastradh case GL_LUMINANCE_ALPHA32UI_EXT: 37773464ebd5Sriastradh *datatype = GL_UNSIGNED_INT; 37783464ebd5Sriastradh *components = 2; 37793464ebd5Sriastradh break; 37803464ebd5Sriastradh case GL_INTENSITY8: 37813464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 37823464ebd5Sriastradh *components = 1; 37833464ebd5Sriastradh break; 37843464ebd5Sriastradh case GL_INTENSITY16: 37853464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 37863464ebd5Sriastradh *components = 1; 37873464ebd5Sriastradh break; 37883464ebd5Sriastradh case GL_INTENSITY16F_ARB: 37893464ebd5Sriastradh *datatype = GL_HALF_FLOAT; 37903464ebd5Sriastradh *components = 1; 37913464ebd5Sriastradh break; 37923464ebd5Sriastradh case GL_INTENSITY32F_ARB: 37933464ebd5Sriastradh *datatype = GL_FLOAT; 37943464ebd5Sriastradh *components = 1; 37953464ebd5Sriastradh break; 37963464ebd5Sriastradh case GL_INTENSITY8I_EXT: 37973464ebd5Sriastradh *datatype = GL_BYTE; 37983464ebd5Sriastradh *components = 1; 37993464ebd5Sriastradh break; 38003464ebd5Sriastradh case GL_INTENSITY16I_EXT: 38013464ebd5Sriastradh *datatype = GL_SHORT; 38023464ebd5Sriastradh *components = 1; 38033464ebd5Sriastradh break; 38043464ebd5Sriastradh case GL_INTENSITY32I_EXT: 38053464ebd5Sriastradh *datatype = GL_INT; 38063464ebd5Sriastradh *components = 1; 38073464ebd5Sriastradh break; 38083464ebd5Sriastradh case GL_INTENSITY8UI_EXT: 38093464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 38103464ebd5Sriastradh *components = 1; 38113464ebd5Sriastradh break; 38123464ebd5Sriastradh case GL_INTENSITY16UI_EXT: 38133464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 38143464ebd5Sriastradh *components = 1; 38153464ebd5Sriastradh break; 38163464ebd5Sriastradh case GL_INTENSITY32UI_EXT: 38173464ebd5Sriastradh *datatype = GL_UNSIGNED_INT; 38183464ebd5Sriastradh *components = 1; 38193464ebd5Sriastradh break; 38203464ebd5Sriastradh case GL_RGBA8: 38213464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 38223464ebd5Sriastradh *components = 4; 38233464ebd5Sriastradh break; 38243464ebd5Sriastradh case GL_RGBA16: 38253464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 38263464ebd5Sriastradh *components = 4; 38273464ebd5Sriastradh break; 38283464ebd5Sriastradh case GL_RGBA16F_ARB: 38293464ebd5Sriastradh *datatype = GL_HALF_FLOAT; 38303464ebd5Sriastradh *components = 4; 38313464ebd5Sriastradh break; 38323464ebd5Sriastradh case GL_RGBA32F_ARB: 38333464ebd5Sriastradh *datatype = GL_FLOAT; 38343464ebd5Sriastradh *components = 4; 38353464ebd5Sriastradh break; 38363464ebd5Sriastradh case GL_RGBA8I_EXT: 38373464ebd5Sriastradh *datatype = GL_BYTE; 38383464ebd5Sriastradh *components = 4; 38393464ebd5Sriastradh break; 38403464ebd5Sriastradh case GL_RGBA16I_EXT: 38413464ebd5Sriastradh *datatype = GL_SHORT; 38423464ebd5Sriastradh *components = 4; 38433464ebd5Sriastradh break; 38443464ebd5Sriastradh case GL_RGBA32I_EXT: 38453464ebd5Sriastradh *datatype = GL_INT; 38463464ebd5Sriastradh *components = 4; 38473464ebd5Sriastradh break; 38483464ebd5Sriastradh case GL_RGBA8UI_EXT: 38493464ebd5Sriastradh *datatype = GL_UNSIGNED_BYTE; 38503464ebd5Sriastradh *components = 4; 38513464ebd5Sriastradh break; 38523464ebd5Sriastradh case GL_RGBA16UI_EXT: 38533464ebd5Sriastradh *datatype = GL_UNSIGNED_SHORT; 38543464ebd5Sriastradh *components = 4; 38553464ebd5Sriastradh break; 38563464ebd5Sriastradh case GL_RGBA32UI_EXT: 38573464ebd5Sriastradh *datatype = GL_UNSIGNED_INT; 38583464ebd5Sriastradh *components = 4; 38593464ebd5Sriastradh break; 38603464ebd5Sriastradh default: 38613464ebd5Sriastradh return GL_FALSE; 38623464ebd5Sriastradh } 38633464ebd5Sriastradh 38643464ebd5Sriastradh if (*datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float) 38653464ebd5Sriastradh return GL_FALSE; 38663464ebd5Sriastradh 38673464ebd5Sriastradh if (*datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel) 38683464ebd5Sriastradh return GL_FALSE; 38693464ebd5Sriastradh 38703464ebd5Sriastradh return GL_TRUE; 38713464ebd5Sriastradh} 38723464ebd5Sriastradh 38733464ebd5Sriastradh 38743464ebd5Sriastradh/** GL_ARB_texture_buffer_object */ 38753464ebd5Sriastradhvoid GLAPIENTRY 38763464ebd5Sriastradh_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) 38773464ebd5Sriastradh{ 38783464ebd5Sriastradh struct gl_texture_object *texObj; 38793464ebd5Sriastradh struct gl_buffer_object *bufObj; 38803464ebd5Sriastradh GLenum dataType; 38813464ebd5Sriastradh GLuint comps; 38823464ebd5Sriastradh 38833464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 38843464ebd5Sriastradh ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 38853464ebd5Sriastradh 38863464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_buffer_object) { 38873464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer"); 38883464ebd5Sriastradh return; 38893464ebd5Sriastradh } 38903464ebd5Sriastradh 38913464ebd5Sriastradh if (target != GL_TEXTURE_BUFFER_ARB) { 38923464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(target)"); 38933464ebd5Sriastradh return; 38943464ebd5Sriastradh } 38953464ebd5Sriastradh 38963464ebd5Sriastradh if (!get_sized_format_info(ctx, internalFormat, &dataType, &comps)) { 38973464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)", 38983464ebd5Sriastradh internalFormat); 38993464ebd5Sriastradh return; 39003464ebd5Sriastradh } 39013464ebd5Sriastradh 39023464ebd5Sriastradh bufObj = _mesa_lookup_bufferobj(ctx, buffer); 39033464ebd5Sriastradh if (buffer && !bufObj) { 39043464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer(buffer %u)", buffer); 39053464ebd5Sriastradh return; 39063464ebd5Sriastradh } 39073464ebd5Sriastradh 39083464ebd5Sriastradh texObj = _mesa_get_current_tex_object(ctx, target); 39093464ebd5Sriastradh 39103464ebd5Sriastradh _mesa_lock_texture(ctx, texObj); 39113464ebd5Sriastradh { 39123464ebd5Sriastradh _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj); 39133464ebd5Sriastradh texObj->BufferObjectFormat = internalFormat; 39143464ebd5Sriastradh } 39153464ebd5Sriastradh _mesa_unlock_texture(ctx, texObj); 39163464ebd5Sriastradh} 3917