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