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