teximage.c revision c1f859d4
17117f1b4Smrg/*
2c1f859d4Smrg * mesa 3-D graphics library
3c1f859d4Smrg * Version:  7.1
47117f1b4Smrg *
57117f1b4Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
67117f1b4Smrg *
77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
97117f1b4Smrg * to deal in the Software without restriction, including without limitation
107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
127117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
137117f1b4Smrg *
147117f1b4Smrg * The above copyright notice and this permission notice shall be included
157117f1b4Smrg * in all copies or substantial portions of the Software.
167117f1b4Smrg *
177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
207117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
217117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
227117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg */
247117f1b4Smrg
257117f1b4Smrg
267117f1b4Smrg/**
277117f1b4Smrg * \file teximage.c
287117f1b4Smrg * Texture image-related functions.
297117f1b4Smrg */
307117f1b4Smrg
317117f1b4Smrg
327117f1b4Smrg#include "glheader.h"
337117f1b4Smrg#include "bufferobj.h"
347117f1b4Smrg#include "context.h"
35c1f859d4Smrg#if FEATURE_convolve
367117f1b4Smrg#include "convolve.h"
37c1f859d4Smrg#endif
387117f1b4Smrg#include "fbobject.h"
397117f1b4Smrg#include "framebuffer.h"
407117f1b4Smrg#include "image.h"
417117f1b4Smrg#include "imports.h"
427117f1b4Smrg#include "macros.h"
437117f1b4Smrg#include "state.h"
447117f1b4Smrg#include "texcompress.h"
457117f1b4Smrg#include "texformat.h"
467117f1b4Smrg#include "teximage.h"
477117f1b4Smrg#include "texstate.h"
487117f1b4Smrg#include "texstore.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 */
57c1f859d4Smrg#define NEW_COPY_TEX_STATE (_IMAGE_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
867117f1b4Smrg#if 0
877117f1b4Smrgstatic void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
887117f1b4Smrg{
897117f1b4Smrg#if CHAN_TYPE != GL_UNSIGNED_BYTE
907117f1b4Smrg   _mesa_problem(NULL, "PrintTexture not supported");
917117f1b4Smrg#else
927117f1b4Smrg   GLuint i, j, c;
937117f1b4Smrg   const GLubyte *data = (const GLubyte *) img->Data;
947117f1b4Smrg
957117f1b4Smrg   if (!data) {
967117f1b4Smrg      _mesa_printf("No texture data\n");
977117f1b4Smrg      return;
987117f1b4Smrg   }
997117f1b4Smrg
1007117f1b4Smrg   switch (img->Format) {
1017117f1b4Smrg      case GL_ALPHA:
1027117f1b4Smrg      case GL_LUMINANCE:
1037117f1b4Smrg      case GL_INTENSITY:
1047117f1b4Smrg      case GL_COLOR_INDEX:
1057117f1b4Smrg         c = 1;
1067117f1b4Smrg         break;
1077117f1b4Smrg      case GL_LUMINANCE_ALPHA:
1087117f1b4Smrg         c = 2;
1097117f1b4Smrg         break;
1107117f1b4Smrg      case GL_RGB:
1117117f1b4Smrg         c = 3;
1127117f1b4Smrg         break;
1137117f1b4Smrg      case GL_RGBA:
1147117f1b4Smrg         c = 4;
1157117f1b4Smrg         break;
1167117f1b4Smrg      default:
1177117f1b4Smrg         _mesa_problem(NULL, "error in PrintTexture\n");
1187117f1b4Smrg         return;
1197117f1b4Smrg   }
1207117f1b4Smrg
1217117f1b4Smrg   for (i = 0; i < img->Height; i++) {
1227117f1b4Smrg      for (j = 0; j < img->Width; j++) {
1237117f1b4Smrg         if (c==1)
1247117f1b4Smrg            _mesa_printf("%02x  ", data[0]);
1257117f1b4Smrg         else if (c==2)
1267117f1b4Smrg            _mesa_printf("%02x%02x  ", data[0], data[1]);
1277117f1b4Smrg         else if (c==3)
1287117f1b4Smrg            _mesa_printf("%02x%02x%02x  ", data[0], data[1], data[2]);
1297117f1b4Smrg         else if (c==4)
1307117f1b4Smrg            _mesa_printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
1317117f1b4Smrg         data += (img->RowStride - img->Width) * c;
1327117f1b4Smrg      }
1337117f1b4Smrg      /* XXX use img->ImageStride here */
1347117f1b4Smrg      _mesa_printf("\n");
1357117f1b4Smrg   }
1367117f1b4Smrg#endif
1377117f1b4Smrg}
1387117f1b4Smrg#endif
1397117f1b4Smrg
1407117f1b4Smrg
1417117f1b4Smrg/*
1427117f1b4Smrg * Compute floor(log_base_2(n)).
1437117f1b4Smrg * If n < 0 return -1.
1447117f1b4Smrg */
1457117f1b4Smrgstatic int
1467117f1b4Smrglogbase2( int n )
1477117f1b4Smrg{
1487117f1b4Smrg   GLint i = 1;
1497117f1b4Smrg   GLint log2 = 0;
1507117f1b4Smrg
1517117f1b4Smrg   if (n < 0)
1527117f1b4Smrg      return -1;
1537117f1b4Smrg
1547117f1b4Smrg   if (n == 0)
1557117f1b4Smrg      return 0;
1567117f1b4Smrg
1577117f1b4Smrg   while ( n > i ) {
1587117f1b4Smrg      i *= 2;
1597117f1b4Smrg      log2++;
1607117f1b4Smrg   }
1617117f1b4Smrg   if (i != n) {
1627117f1b4Smrg      return log2 - 1;
1637117f1b4Smrg   }
1647117f1b4Smrg   else {
1657117f1b4Smrg      return log2;
1667117f1b4Smrg   }
1677117f1b4Smrg}
1687117f1b4Smrg
1697117f1b4Smrg
1707117f1b4Smrg
1717117f1b4Smrg/**
1727117f1b4Smrg * Return the simple base format for a given internal texture format.
1737117f1b4Smrg * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
1747117f1b4Smrg *
1757117f1b4Smrg * \param ctx GL context.
1767117f1b4Smrg * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
1777117f1b4Smrg *
1787117f1b4Smrg * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
1797117f1b4Smrg * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
1807117f1b4Smrg *
1817117f1b4Smrg * This is the format which is used during texture application (i.e. the
1827117f1b4Smrg * texture format and env mode determine the arithmetic used.
1837117f1b4Smrg */
1847117f1b4SmrgGLint
1857117f1b4Smrg_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
1867117f1b4Smrg{
1877117f1b4Smrg   switch (internalFormat) {
1887117f1b4Smrg      case GL_ALPHA:
1897117f1b4Smrg      case GL_ALPHA4:
1907117f1b4Smrg      case GL_ALPHA8:
1917117f1b4Smrg      case GL_ALPHA12:
1927117f1b4Smrg      case GL_ALPHA16:
1937117f1b4Smrg         return GL_ALPHA;
1947117f1b4Smrg      case 1:
1957117f1b4Smrg      case GL_LUMINANCE:
1967117f1b4Smrg      case GL_LUMINANCE4:
1977117f1b4Smrg      case GL_LUMINANCE8:
1987117f1b4Smrg      case GL_LUMINANCE12:
1997117f1b4Smrg      case GL_LUMINANCE16:
2007117f1b4Smrg         return GL_LUMINANCE;
2017117f1b4Smrg      case 2:
2027117f1b4Smrg      case GL_LUMINANCE_ALPHA:
2037117f1b4Smrg      case GL_LUMINANCE4_ALPHA4:
2047117f1b4Smrg      case GL_LUMINANCE6_ALPHA2:
2057117f1b4Smrg      case GL_LUMINANCE8_ALPHA8:
2067117f1b4Smrg      case GL_LUMINANCE12_ALPHA4:
2077117f1b4Smrg      case GL_LUMINANCE12_ALPHA12:
2087117f1b4Smrg      case GL_LUMINANCE16_ALPHA16:
2097117f1b4Smrg         return GL_LUMINANCE_ALPHA;
2107117f1b4Smrg      case GL_INTENSITY:
2117117f1b4Smrg      case GL_INTENSITY4:
2127117f1b4Smrg      case GL_INTENSITY8:
2137117f1b4Smrg      case GL_INTENSITY12:
2147117f1b4Smrg      case GL_INTENSITY16:
2157117f1b4Smrg         return GL_INTENSITY;
2167117f1b4Smrg      case 3:
2177117f1b4Smrg      case GL_RGB:
2187117f1b4Smrg      case GL_R3_G3_B2:
2197117f1b4Smrg      case GL_RGB4:
2207117f1b4Smrg      case GL_RGB5:
2217117f1b4Smrg      case GL_RGB8:
2227117f1b4Smrg      case GL_RGB10:
2237117f1b4Smrg      case GL_RGB12:
2247117f1b4Smrg      case GL_RGB16:
2257117f1b4Smrg         return GL_RGB;
2267117f1b4Smrg      case 4:
2277117f1b4Smrg      case GL_RGBA:
2287117f1b4Smrg      case GL_RGBA2:
2297117f1b4Smrg      case GL_RGBA4:
2307117f1b4Smrg      case GL_RGB5_A1:
2317117f1b4Smrg      case GL_RGBA8:
2327117f1b4Smrg      case GL_RGB10_A2:
2337117f1b4Smrg      case GL_RGBA12:
2347117f1b4Smrg      case GL_RGBA16:
2357117f1b4Smrg         return GL_RGBA;
2367117f1b4Smrg      default:
2377117f1b4Smrg         ; /* fallthrough */
2387117f1b4Smrg   }
2397117f1b4Smrg
2407117f1b4Smrg   if (ctx->Extensions.EXT_paletted_texture) {
2417117f1b4Smrg      switch (internalFormat) {
2427117f1b4Smrg         case GL_COLOR_INDEX:
2437117f1b4Smrg         case GL_COLOR_INDEX1_EXT:
2447117f1b4Smrg         case GL_COLOR_INDEX2_EXT:
2457117f1b4Smrg         case GL_COLOR_INDEX4_EXT:
2467117f1b4Smrg         case GL_COLOR_INDEX8_EXT:
2477117f1b4Smrg         case GL_COLOR_INDEX12_EXT:
2487117f1b4Smrg         case GL_COLOR_INDEX16_EXT:
2497117f1b4Smrg            return GL_COLOR_INDEX;
2507117f1b4Smrg         default:
2517117f1b4Smrg            ; /* fallthrough */
2527117f1b4Smrg      }
2537117f1b4Smrg   }
2547117f1b4Smrg
255c1f859d4Smrg   if (ctx->Extensions.ARB_depth_texture) {
2567117f1b4Smrg      switch (internalFormat) {
2577117f1b4Smrg         case GL_DEPTH_COMPONENT:
258c1f859d4Smrg         case GL_DEPTH_COMPONENT16:
259c1f859d4Smrg         case GL_DEPTH_COMPONENT24:
260c1f859d4Smrg         case GL_DEPTH_COMPONENT32:
2617117f1b4Smrg            return GL_DEPTH_COMPONENT;
2627117f1b4Smrg         default:
2637117f1b4Smrg            ; /* fallthrough */
2647117f1b4Smrg      }
2657117f1b4Smrg   }
2667117f1b4Smrg
2677117f1b4Smrg   if (ctx->Extensions.ARB_texture_compression) {
2687117f1b4Smrg      switch (internalFormat) {
2697117f1b4Smrg         case GL_COMPRESSED_ALPHA:
2707117f1b4Smrg            return GL_ALPHA;
2717117f1b4Smrg         case GL_COMPRESSED_LUMINANCE:
2727117f1b4Smrg            return GL_LUMINANCE;
2737117f1b4Smrg         case GL_COMPRESSED_LUMINANCE_ALPHA:
2747117f1b4Smrg            return GL_LUMINANCE_ALPHA;
2757117f1b4Smrg         case GL_COMPRESSED_INTENSITY:
2767117f1b4Smrg            return GL_INTENSITY;
2777117f1b4Smrg         case GL_COMPRESSED_RGB:
2787117f1b4Smrg            return GL_RGB;
2797117f1b4Smrg         case GL_COMPRESSED_RGBA:
2807117f1b4Smrg            return GL_RGBA;
2817117f1b4Smrg         default:
2827117f1b4Smrg            ; /* fallthrough */
2837117f1b4Smrg      }
2847117f1b4Smrg   }
2857117f1b4Smrg
2867117f1b4Smrg   if (ctx->Extensions.TDFX_texture_compression_FXT1) {
2877117f1b4Smrg      switch (internalFormat) {
2887117f1b4Smrg         case GL_COMPRESSED_RGB_FXT1_3DFX:
2897117f1b4Smrg            return GL_RGB;
2907117f1b4Smrg         case GL_COMPRESSED_RGBA_FXT1_3DFX:
2917117f1b4Smrg            return GL_RGBA;
2927117f1b4Smrg         default:
2937117f1b4Smrg            ; /* fallthrough */
2947117f1b4Smrg      }
2957117f1b4Smrg   }
2967117f1b4Smrg
2977117f1b4Smrg   if (ctx->Extensions.EXT_texture_compression_s3tc) {
2987117f1b4Smrg      switch (internalFormat) {
2997117f1b4Smrg         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
3007117f1b4Smrg            return GL_RGB;
3017117f1b4Smrg         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
3027117f1b4Smrg         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
3037117f1b4Smrg         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
3047117f1b4Smrg            return GL_RGBA;
3057117f1b4Smrg         default:
3067117f1b4Smrg            ; /* fallthrough */
3077117f1b4Smrg      }
3087117f1b4Smrg   }
3097117f1b4Smrg
3107117f1b4Smrg   if (ctx->Extensions.S3_s3tc) {
3117117f1b4Smrg      switch (internalFormat) {
3127117f1b4Smrg         case GL_RGB_S3TC:
3137117f1b4Smrg         case GL_RGB4_S3TC:
3147117f1b4Smrg            return GL_RGB;
3157117f1b4Smrg         case GL_RGBA_S3TC:
3167117f1b4Smrg         case GL_RGBA4_S3TC:
3177117f1b4Smrg            return GL_RGBA;
3187117f1b4Smrg         default:
3197117f1b4Smrg            ; /* fallthrough */
3207117f1b4Smrg      }
3217117f1b4Smrg   }
3227117f1b4Smrg
3237117f1b4Smrg   if (ctx->Extensions.MESA_ycbcr_texture) {
3247117f1b4Smrg      if (internalFormat == GL_YCBCR_MESA)
3257117f1b4Smrg         return GL_YCBCR_MESA;
3267117f1b4Smrg   }
3277117f1b4Smrg
3287117f1b4Smrg   if (ctx->Extensions.ARB_texture_float) {
3297117f1b4Smrg      switch (internalFormat) {
3307117f1b4Smrg         case GL_ALPHA16F_ARB:
3317117f1b4Smrg         case GL_ALPHA32F_ARB:
3327117f1b4Smrg            return GL_ALPHA;
3337117f1b4Smrg         case GL_RGBA16F_ARB:
3347117f1b4Smrg         case GL_RGBA32F_ARB:
3357117f1b4Smrg            return GL_RGBA;
3367117f1b4Smrg         case GL_RGB16F_ARB:
3377117f1b4Smrg         case GL_RGB32F_ARB:
3387117f1b4Smrg            return GL_RGB;
3397117f1b4Smrg         case GL_INTENSITY16F_ARB:
3407117f1b4Smrg         case GL_INTENSITY32F_ARB:
3417117f1b4Smrg            return GL_INTENSITY;
3427117f1b4Smrg         case GL_LUMINANCE16F_ARB:
3437117f1b4Smrg         case GL_LUMINANCE32F_ARB:
3447117f1b4Smrg            return GL_LUMINANCE;
3457117f1b4Smrg         case GL_LUMINANCE_ALPHA16F_ARB:
3467117f1b4Smrg         case GL_LUMINANCE_ALPHA32F_ARB:
3477117f1b4Smrg            return GL_LUMINANCE_ALPHA;
3487117f1b4Smrg         default:
3497117f1b4Smrg            ; /* fallthrough */
3507117f1b4Smrg      }
3517117f1b4Smrg   }
3527117f1b4Smrg
3537117f1b4Smrg   if (ctx->Extensions.EXT_packed_depth_stencil) {
3547117f1b4Smrg      switch (internalFormat) {
3557117f1b4Smrg         case GL_DEPTH_STENCIL_EXT:
3567117f1b4Smrg         case GL_DEPTH24_STENCIL8_EXT:
3577117f1b4Smrg            return GL_DEPTH_STENCIL_EXT;
3587117f1b4Smrg         default:
3597117f1b4Smrg            ; /* fallthrough */
3607117f1b4Smrg      }
3617117f1b4Smrg   }
3627117f1b4Smrg
3637117f1b4Smrg#if FEATURE_EXT_texture_sRGB
3647117f1b4Smrg   if (ctx->Extensions.EXT_texture_sRGB) {
3657117f1b4Smrg      switch (internalFormat) {
3667117f1b4Smrg      case GL_SRGB_EXT:
3677117f1b4Smrg      case GL_SRGB8_EXT:
3687117f1b4Smrg      case GL_COMPRESSED_SRGB_EXT:
3697117f1b4Smrg      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
3707117f1b4Smrg         return GL_RGB;
3717117f1b4Smrg      case GL_SRGB_ALPHA_EXT:
3727117f1b4Smrg      case GL_SRGB8_ALPHA8_EXT:
3737117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_EXT:
3747117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
3757117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
3767117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
3777117f1b4Smrg         return GL_RGBA;
3787117f1b4Smrg      case GL_SLUMINANCE_ALPHA_EXT:
3797117f1b4Smrg      case GL_SLUMINANCE8_ALPHA8_EXT:
3807117f1b4Smrg      case GL_COMPRESSED_SLUMINANCE_EXT:
3817117f1b4Smrg      case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
3827117f1b4Smrg         return GL_LUMINANCE_ALPHA;
3837117f1b4Smrg      case GL_SLUMINANCE_EXT:
3847117f1b4Smrg      case GL_SLUMINANCE8_EXT:
3857117f1b4Smrg         return GL_LUMINANCE;
3867117f1b4Smrg      default:
3877117f1b4Smrg            ; /* fallthrough */
3887117f1b4Smrg      }
3897117f1b4Smrg   }
3907117f1b4Smrg
3917117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */
3927117f1b4Smrg
3937117f1b4Smrg   return -1; /* error */
3947117f1b4Smrg}
3957117f1b4Smrg
3967117f1b4Smrg
3977117f1b4Smrg/**
3987117f1b4Smrg * Test if the given image format is a color/RGBA format (i.e., not color
3997117f1b4Smrg * index, depth, stencil, etc).
4007117f1b4Smrg * \param format  the image format value (may by an internal texture format)
4017117f1b4Smrg * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
402c1f859d4Smrg * XXX maybe move this func to image.c
4037117f1b4Smrg */
404c1f859d4SmrgGLboolean
405c1f859d4Smrg_mesa_is_color_format(GLenum format)
4067117f1b4Smrg{
4077117f1b4Smrg   switch (format) {
4087117f1b4Smrg      case GL_RED:
4097117f1b4Smrg      case GL_GREEN:
4107117f1b4Smrg      case GL_BLUE:
4117117f1b4Smrg      case GL_ALPHA:
4127117f1b4Smrg      case GL_ALPHA4:
4137117f1b4Smrg      case GL_ALPHA8:
4147117f1b4Smrg      case GL_ALPHA12:
4157117f1b4Smrg      case GL_ALPHA16:
4167117f1b4Smrg      case 1:
4177117f1b4Smrg      case GL_LUMINANCE:
4187117f1b4Smrg      case GL_LUMINANCE4:
4197117f1b4Smrg      case GL_LUMINANCE8:
4207117f1b4Smrg      case GL_LUMINANCE12:
4217117f1b4Smrg      case GL_LUMINANCE16:
4227117f1b4Smrg      case 2:
4237117f1b4Smrg      case GL_LUMINANCE_ALPHA:
4247117f1b4Smrg      case GL_LUMINANCE4_ALPHA4:
4257117f1b4Smrg      case GL_LUMINANCE6_ALPHA2:
4267117f1b4Smrg      case GL_LUMINANCE8_ALPHA8:
4277117f1b4Smrg      case GL_LUMINANCE12_ALPHA4:
4287117f1b4Smrg      case GL_LUMINANCE12_ALPHA12:
4297117f1b4Smrg      case GL_LUMINANCE16_ALPHA16:
4307117f1b4Smrg      case GL_INTENSITY:
4317117f1b4Smrg      case GL_INTENSITY4:
4327117f1b4Smrg      case GL_INTENSITY8:
4337117f1b4Smrg      case GL_INTENSITY12:
4347117f1b4Smrg      case GL_INTENSITY16:
4357117f1b4Smrg      case 3:
4367117f1b4Smrg      case GL_RGB:
4377117f1b4Smrg      case GL_BGR:
4387117f1b4Smrg      case GL_R3_G3_B2:
4397117f1b4Smrg      case GL_RGB4:
4407117f1b4Smrg      case GL_RGB5:
4417117f1b4Smrg      case GL_RGB8:
4427117f1b4Smrg      case GL_RGB10:
4437117f1b4Smrg      case GL_RGB12:
4447117f1b4Smrg      case GL_RGB16:
4457117f1b4Smrg      case 4:
4467117f1b4Smrg      case GL_ABGR_EXT:
4477117f1b4Smrg      case GL_RGBA:
4487117f1b4Smrg      case GL_BGRA:
4497117f1b4Smrg      case GL_RGBA2:
4507117f1b4Smrg      case GL_RGBA4:
4517117f1b4Smrg      case GL_RGB5_A1:
4527117f1b4Smrg      case GL_RGBA8:
4537117f1b4Smrg      case GL_RGB10_A2:
4547117f1b4Smrg      case GL_RGBA12:
4557117f1b4Smrg      case GL_RGBA16:
4567117f1b4Smrg      /* float texture formats */
4577117f1b4Smrg      case GL_ALPHA16F_ARB:
4587117f1b4Smrg      case GL_ALPHA32F_ARB:
4597117f1b4Smrg      case GL_LUMINANCE16F_ARB:
4607117f1b4Smrg      case GL_LUMINANCE32F_ARB:
4617117f1b4Smrg      case GL_LUMINANCE_ALPHA16F_ARB:
4627117f1b4Smrg      case GL_LUMINANCE_ALPHA32F_ARB:
4637117f1b4Smrg      case GL_INTENSITY16F_ARB:
4647117f1b4Smrg      case GL_INTENSITY32F_ARB:
4657117f1b4Smrg      case GL_RGB16F_ARB:
4667117f1b4Smrg      case GL_RGB32F_ARB:
4677117f1b4Smrg      case GL_RGBA16F_ARB:
4687117f1b4Smrg      case GL_RGBA32F_ARB:
4697117f1b4Smrg      /* compressed formats */
4707117f1b4Smrg      case GL_COMPRESSED_ALPHA:
4717117f1b4Smrg      case GL_COMPRESSED_LUMINANCE:
4727117f1b4Smrg      case GL_COMPRESSED_LUMINANCE_ALPHA:
4737117f1b4Smrg      case GL_COMPRESSED_INTENSITY:
4747117f1b4Smrg      case GL_COMPRESSED_RGB:
4757117f1b4Smrg      case GL_COMPRESSED_RGBA:
4767117f1b4Smrg      case GL_RGB_S3TC:
4777117f1b4Smrg      case GL_RGB4_S3TC:
4787117f1b4Smrg      case GL_RGBA_S3TC:
4797117f1b4Smrg      case GL_RGBA4_S3TC:
4807117f1b4Smrg      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
4817117f1b4Smrg      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
4827117f1b4Smrg      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
4837117f1b4Smrg      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
4847117f1b4Smrg      case GL_COMPRESSED_RGB_FXT1_3DFX:
4857117f1b4Smrg      case GL_COMPRESSED_RGBA_FXT1_3DFX:
4867117f1b4Smrg#if FEATURE_EXT_texture_sRGB
4877117f1b4Smrg      case GL_SRGB_EXT:
4887117f1b4Smrg      case GL_SRGB8_EXT:
4897117f1b4Smrg      case GL_SRGB_ALPHA_EXT:
4907117f1b4Smrg      case GL_SRGB8_ALPHA8_EXT:
4917117f1b4Smrg      case GL_SLUMINANCE_ALPHA_EXT:
4927117f1b4Smrg      case GL_SLUMINANCE8_ALPHA8_EXT:
4937117f1b4Smrg      case GL_SLUMINANCE_EXT:
4947117f1b4Smrg      case GL_SLUMINANCE8_EXT:
4957117f1b4Smrg      case GL_COMPRESSED_SRGB_EXT:
4967117f1b4Smrg      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
4977117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_EXT:
4987117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
4997117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
5007117f1b4Smrg      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
5017117f1b4Smrg      case GL_COMPRESSED_SLUMINANCE_EXT:
5027117f1b4Smrg      case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
5037117f1b4Smrg#endif /* FEATURE_EXT_texture_sRGB */
5047117f1b4Smrg         return GL_TRUE;
5057117f1b4Smrg      case GL_YCBCR_MESA:  /* not considered to be RGB */
506c1f859d4Smrg         /* fall-through */
5077117f1b4Smrg      default:
5087117f1b4Smrg         return GL_FALSE;
5097117f1b4Smrg   }
5107117f1b4Smrg}
5117117f1b4Smrg
5127117f1b4Smrg
5137117f1b4Smrg/**
5147117f1b4Smrg * Test if the given image format is a color index format.
5157117f1b4Smrg */
5167117f1b4Smrgstatic GLboolean
5177117f1b4Smrgis_index_format(GLenum format)
5187117f1b4Smrg{
5197117f1b4Smrg   switch (format) {
5207117f1b4Smrg      case GL_COLOR_INDEX:
5217117f1b4Smrg      case GL_COLOR_INDEX1_EXT:
5227117f1b4Smrg      case GL_COLOR_INDEX2_EXT:
5237117f1b4Smrg      case GL_COLOR_INDEX4_EXT:
5247117f1b4Smrg      case GL_COLOR_INDEX8_EXT:
5257117f1b4Smrg      case GL_COLOR_INDEX12_EXT:
5267117f1b4Smrg      case GL_COLOR_INDEX16_EXT:
5277117f1b4Smrg         return GL_TRUE;
5287117f1b4Smrg      default:
5297117f1b4Smrg         return GL_FALSE;
5307117f1b4Smrg   }
5317117f1b4Smrg}
5327117f1b4Smrg
5337117f1b4Smrg
5347117f1b4Smrg/**
5357117f1b4Smrg * Test if the given image format is a depth component format.
5367117f1b4Smrg */
5377117f1b4Smrgstatic GLboolean
5387117f1b4Smrgis_depth_format(GLenum format)
5397117f1b4Smrg{
5407117f1b4Smrg   switch (format) {
541c1f859d4Smrg      case GL_DEPTH_COMPONENT16:
542c1f859d4Smrg      case GL_DEPTH_COMPONENT24:
543c1f859d4Smrg      case GL_DEPTH_COMPONENT32:
5447117f1b4Smrg      case GL_DEPTH_COMPONENT:
5457117f1b4Smrg         return GL_TRUE;
5467117f1b4Smrg      default:
5477117f1b4Smrg         return GL_FALSE;
5487117f1b4Smrg   }
5497117f1b4Smrg}
5507117f1b4Smrg
5517117f1b4Smrg
5527117f1b4Smrg/**
5537117f1b4Smrg * Test if the given image format is a YCbCr format.
5547117f1b4Smrg */
5557117f1b4Smrgstatic GLboolean
5567117f1b4Smrgis_ycbcr_format(GLenum format)
5577117f1b4Smrg{
5587117f1b4Smrg   switch (format) {
5597117f1b4Smrg      case GL_YCBCR_MESA:
5607117f1b4Smrg         return GL_TRUE;
5617117f1b4Smrg      default:
5627117f1b4Smrg         return GL_FALSE;
5637117f1b4Smrg   }
5647117f1b4Smrg}
5657117f1b4Smrg
5667117f1b4Smrg
5677117f1b4Smrg/**
5687117f1b4Smrg * Test if the given image format is a Depth/Stencil format.
5697117f1b4Smrg */
5707117f1b4Smrgstatic GLboolean
5717117f1b4Smrgis_depthstencil_format(GLenum format)
5727117f1b4Smrg{
5737117f1b4Smrg   switch (format) {
5747117f1b4Smrg      case GL_DEPTH24_STENCIL8_EXT:
5757117f1b4Smrg      case GL_DEPTH_STENCIL_EXT:
5767117f1b4Smrg         return GL_TRUE;
5777117f1b4Smrg      default:
5787117f1b4Smrg         return GL_FALSE;
5797117f1b4Smrg   }
5807117f1b4Smrg}
5817117f1b4Smrg
5827117f1b4Smrg
5837117f1b4Smrg
5847117f1b4Smrg/**
5857117f1b4Smrg * Test if it is a supported compressed format.
5867117f1b4Smrg *
5877117f1b4Smrg * \param internalFormat the internal format token provided by the user.
5887117f1b4Smrg *
5897117f1b4Smrg * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
5907117f1b4Smrg * GL_FALSE otherwise.
5917117f1b4Smrg *
5927117f1b4Smrg * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
5937117f1b4Smrg * are supported.
5947117f1b4Smrg */
5957117f1b4Smrgstatic GLboolean
5967117f1b4Smrgis_compressed_format(GLcontext *ctx, GLenum internalFormat)
5977117f1b4Smrg{
5987117f1b4Smrg   GLint supported[100]; /* 100 should be plenty */
5997117f1b4Smrg   GLuint i, n;
6007117f1b4Smrg
6017117f1b4Smrg   n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE);
6027117f1b4Smrg   ASSERT(n < 100);
6037117f1b4Smrg   for (i = 0; i < n; i++) {
6047117f1b4Smrg      if ((GLint) internalFormat == supported[i]) {
6057117f1b4Smrg         return GL_TRUE;
6067117f1b4Smrg      }
6077117f1b4Smrg   }
6087117f1b4Smrg   return GL_FALSE;
6097117f1b4Smrg}
6107117f1b4Smrg
6117117f1b4Smrg
612c1f859d4Smrg/**
613c1f859d4Smrg * For cube map faces, return a face index in [0,5].
614c1f859d4Smrg * For other targets return 0;
615c1f859d4Smrg */
616c1f859d4SmrgGLuint
617c1f859d4Smrg_mesa_tex_target_to_face(GLenum target)
6187117f1b4Smrg{
6197117f1b4Smrg   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
6207117f1b4Smrg       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
6217117f1b4Smrg      return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
6227117f1b4Smrg   else
6237117f1b4Smrg      return 0;
6247117f1b4Smrg}
6257117f1b4Smrg
6267117f1b4Smrg
6277117f1b4Smrg
6287117f1b4Smrg/**
6297117f1b4Smrg * Store a gl_texture_image pointer in a gl_texture_object structure
6307117f1b4Smrg * according to the target and level parameters.
6317117f1b4Smrg *
6327117f1b4Smrg * \param tObj texture object.
6337117f1b4Smrg * \param target texture target.
6347117f1b4Smrg * \param level image level.
6357117f1b4Smrg * \param texImage texture image.
6367117f1b4Smrg *
6377117f1b4Smrg * This was basically prompted by the introduction of cube maps.
6387117f1b4Smrg */
6397117f1b4Smrgvoid
6407117f1b4Smrg_mesa_set_tex_image(struct gl_texture_object *tObj,
6417117f1b4Smrg                    GLenum target, GLint level,
6427117f1b4Smrg                    struct gl_texture_image *texImage)
6437117f1b4Smrg{
6447117f1b4Smrg   ASSERT(tObj);
6457117f1b4Smrg   ASSERT(texImage);
646c1f859d4Smrg   /* XXX simplify this with _mesa_tex_target_to_face() */
6477117f1b4Smrg   switch (target) {
6487117f1b4Smrg      case GL_TEXTURE_1D:
6497117f1b4Smrg      case GL_TEXTURE_2D:
6507117f1b4Smrg      case GL_TEXTURE_3D:
651c1f859d4Smrg      case GL_TEXTURE_1D_ARRAY_EXT:
652c1f859d4Smrg      case GL_TEXTURE_2D_ARRAY_EXT:
6537117f1b4Smrg         tObj->Image[0][level] = texImage;
6547117f1b4Smrg         break;
6557117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
6567117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
6577117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
6587117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
6597117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
6607117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
6617117f1b4Smrg         {
6627117f1b4Smrg            GLuint face = ((GLuint) target -
6637117f1b4Smrg                           (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
6647117f1b4Smrg            tObj->Image[face][level] = texImage;
6657117f1b4Smrg         }
6667117f1b4Smrg         break;
6677117f1b4Smrg      case GL_TEXTURE_RECTANGLE_NV:
6687117f1b4Smrg         ASSERT(level == 0);
6697117f1b4Smrg         tObj->Image[0][level] = texImage;
6707117f1b4Smrg         break;
6717117f1b4Smrg      default:
6727117f1b4Smrg         _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
6737117f1b4Smrg         return;
6747117f1b4Smrg   }
6757117f1b4Smrg   /* Set the 'back' pointer */
6767117f1b4Smrg   texImage->TexObject = tObj;
6777117f1b4Smrg}
6787117f1b4Smrg
6797117f1b4Smrg
6807117f1b4Smrg/**
6817117f1b4Smrg * Allocate a texture image structure.
6827117f1b4Smrg *
6837117f1b4Smrg * Called via ctx->Driver.NewTextureImage() unless overriden by a device
6847117f1b4Smrg * driver.
6857117f1b4Smrg *
6867117f1b4Smrg * \return a pointer to gl_texture_image struct with all fields initialized to
6877117f1b4Smrg * zero.
6887117f1b4Smrg */
6897117f1b4Smrgstruct gl_texture_image *
6907117f1b4Smrg_mesa_new_texture_image( GLcontext *ctx )
6917117f1b4Smrg{
6927117f1b4Smrg   (void) ctx;
6937117f1b4Smrg   return CALLOC_STRUCT(gl_texture_image);
6947117f1b4Smrg}
6957117f1b4Smrg
6967117f1b4Smrg
6977117f1b4Smrg/**
6987117f1b4Smrg * Free texture image data.
6997117f1b4Smrg * This function is a fallback called via ctx->Driver.FreeTexImageData().
7007117f1b4Smrg *
7017117f1b4Smrg * \param teximage texture image.
7027117f1b4Smrg *
7037117f1b4Smrg * Free the texture image data if it's not marked as client data.
7047117f1b4Smrg */
7057117f1b4Smrgvoid
7067117f1b4Smrg_mesa_free_texture_image_data(GLcontext *ctx,
7077117f1b4Smrg                              struct gl_texture_image *texImage)
7087117f1b4Smrg{
7097117f1b4Smrg   (void) ctx;
7107117f1b4Smrg
7117117f1b4Smrg   if (texImage->Data && !texImage->IsClientData) {
7127117f1b4Smrg      /* free the old texture data */
7137117f1b4Smrg      _mesa_free_texmemory(texImage->Data);
7147117f1b4Smrg   }
7157117f1b4Smrg
7167117f1b4Smrg   texImage->Data = NULL;
7177117f1b4Smrg}
7187117f1b4Smrg
7197117f1b4Smrg
7207117f1b4Smrg/**
7217117f1b4Smrg * Free texture image.
7227117f1b4Smrg *
7237117f1b4Smrg * \param teximage texture image.
7247117f1b4Smrg *
7257117f1b4Smrg * Free the texture image structure and the associated image data.
7267117f1b4Smrg */
7277117f1b4Smrgvoid
7287117f1b4Smrg_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
7297117f1b4Smrg{
7307117f1b4Smrg   /* Free texImage->Data and/or any other driver-specific texture
7317117f1b4Smrg    * image storage.
7327117f1b4Smrg    */
7337117f1b4Smrg   ASSERT(ctx->Driver.FreeTexImageData);
7347117f1b4Smrg   ctx->Driver.FreeTexImageData( ctx, texImage );
7357117f1b4Smrg
7367117f1b4Smrg   ASSERT(texImage->Data == NULL);
7377117f1b4Smrg   if (texImage->ImageOffsets)
7387117f1b4Smrg      _mesa_free(texImage->ImageOffsets);
7397117f1b4Smrg   _mesa_free(texImage);
7407117f1b4Smrg}
7417117f1b4Smrg
7427117f1b4Smrg
7437117f1b4Smrg/**
7447117f1b4Smrg * Test if a target is a proxy target.
7457117f1b4Smrg *
7467117f1b4Smrg * \param target texture target.
7477117f1b4Smrg *
7487117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
7497117f1b4Smrg */
7507117f1b4SmrgGLboolean
7517117f1b4Smrg_mesa_is_proxy_texture(GLenum target)
7527117f1b4Smrg{
7537117f1b4Smrg   return (target == GL_PROXY_TEXTURE_1D ||
7547117f1b4Smrg           target == GL_PROXY_TEXTURE_2D ||
7557117f1b4Smrg           target == GL_PROXY_TEXTURE_3D ||
7567117f1b4Smrg           target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
757c1f859d4Smrg           target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
758c1f859d4Smrg           target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
759c1f859d4Smrg           target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
7607117f1b4Smrg}
7617117f1b4Smrg
7627117f1b4Smrg
7637117f1b4Smrg/**
7647117f1b4Smrg * Get the texture object that corresponds to the target of the given texture unit.
7657117f1b4Smrg *
7667117f1b4Smrg * \param ctx GL context.
7677117f1b4Smrg * \param texUnit texture unit.
7687117f1b4Smrg * \param target texture target.
7697117f1b4Smrg *
7707117f1b4Smrg * \return pointer to the texture object on success, or NULL on failure.
7717117f1b4Smrg *
7727117f1b4Smrg * \sa gl_texture_unit.
7737117f1b4Smrg */
7747117f1b4Smrgstruct gl_texture_object *
7757117f1b4Smrg_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
7767117f1b4Smrg                        GLenum target)
7777117f1b4Smrg{
7787117f1b4Smrg   switch (target) {
7797117f1b4Smrg      case GL_TEXTURE_1D:
780c1f859d4Smrg         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
7817117f1b4Smrg      case GL_PROXY_TEXTURE_1D:
782c1f859d4Smrg         return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
7837117f1b4Smrg      case GL_TEXTURE_2D:
784c1f859d4Smrg         return texUnit->CurrentTex[TEXTURE_2D_INDEX];
7857117f1b4Smrg      case GL_PROXY_TEXTURE_2D:
786c1f859d4Smrg         return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
7877117f1b4Smrg      case GL_TEXTURE_3D:
788c1f859d4Smrg         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
7897117f1b4Smrg      case GL_PROXY_TEXTURE_3D:
790c1f859d4Smrg         return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
7917117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
7927117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
7937117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
7947117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
7957117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
7967117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
7977117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_ARB:
7987117f1b4Smrg         return ctx->Extensions.ARB_texture_cube_map
799c1f859d4Smrg                ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
8007117f1b4Smrg      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
8017117f1b4Smrg         return ctx->Extensions.ARB_texture_cube_map
802c1f859d4Smrg                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
8037117f1b4Smrg      case GL_TEXTURE_RECTANGLE_NV:
8047117f1b4Smrg         return ctx->Extensions.NV_texture_rectangle
805c1f859d4Smrg                ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
8067117f1b4Smrg      case GL_PROXY_TEXTURE_RECTANGLE_NV:
8077117f1b4Smrg         return ctx->Extensions.NV_texture_rectangle
808c1f859d4Smrg                ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
809c1f859d4Smrg      case GL_TEXTURE_1D_ARRAY_EXT:
810c1f859d4Smrg         return ctx->Extensions.MESA_texture_array
811c1f859d4Smrg                ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
812c1f859d4Smrg      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
813c1f859d4Smrg         return ctx->Extensions.MESA_texture_array
814c1f859d4Smrg                ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
815c1f859d4Smrg      case GL_TEXTURE_2D_ARRAY_EXT:
816c1f859d4Smrg         return ctx->Extensions.MESA_texture_array
817c1f859d4Smrg                ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
818c1f859d4Smrg      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
819c1f859d4Smrg         return ctx->Extensions.MESA_texture_array
820c1f859d4Smrg                ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
8217117f1b4Smrg      default:
8227117f1b4Smrg         _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
8237117f1b4Smrg         return NULL;
8247117f1b4Smrg   }
8257117f1b4Smrg}
8267117f1b4Smrg
8277117f1b4Smrg
8287117f1b4Smrg/**
8297117f1b4Smrg * Get the texture image struct which corresponds to target and level
8307117f1b4Smrg * of the given texture unit.
8317117f1b4Smrg *
8327117f1b4Smrg * \param ctx GL context.
8337117f1b4Smrg * \param texUnit texture unit.
8347117f1b4Smrg * \param target texture target.
8357117f1b4Smrg * \param level image level.
8367117f1b4Smrg *
8377117f1b4Smrg * \return pointer to the texture image structure on success, or NULL on failure.
8387117f1b4Smrg *
8397117f1b4Smrg * \sa gl_texture_unit.
8407117f1b4Smrg */
8417117f1b4Smrgstruct gl_texture_image *
8427117f1b4Smrg_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
8437117f1b4Smrg		       GLenum target, GLint level)
8447117f1b4Smrg{
8457117f1b4Smrg   ASSERT(texObj);
8467117f1b4Smrg
8477117f1b4Smrg   if (level < 0 || level >= MAX_TEXTURE_LEVELS)
8487117f1b4Smrg      return NULL;
8497117f1b4Smrg
850c1f859d4Smrg   /* XXX simplify this with _mesa_tex_target_to_face() */
8517117f1b4Smrg   switch (target) {
8527117f1b4Smrg      case GL_TEXTURE_1D:
8537117f1b4Smrg      case GL_PROXY_TEXTURE_1D:
8547117f1b4Smrg      case GL_TEXTURE_2D:
8557117f1b4Smrg      case GL_PROXY_TEXTURE_2D:
8567117f1b4Smrg      case GL_TEXTURE_3D:
8577117f1b4Smrg      case GL_PROXY_TEXTURE_3D:
8587117f1b4Smrg         return texObj->Image[0][level];
8597117f1b4Smrg
8607117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
8617117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
8627117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
8637117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
8647117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
8657117f1b4Smrg      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
8667117f1b4Smrg         if (ctx->Extensions.ARB_texture_cube_map) {
8677117f1b4Smrg	    GLuint face = ((GLuint) target -
8687117f1b4Smrg			   (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
8697117f1b4Smrg            return texObj->Image[face][level];
8707117f1b4Smrg	 }
8717117f1b4Smrg         else
8727117f1b4Smrg            return NULL;
8737117f1b4Smrg
8747117f1b4Smrg      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
8757117f1b4Smrg         if (ctx->Extensions.ARB_texture_cube_map)
8767117f1b4Smrg            return texObj->Image[0][level];
8777117f1b4Smrg         else
8787117f1b4Smrg            return NULL;
8797117f1b4Smrg
8807117f1b4Smrg      case GL_TEXTURE_RECTANGLE_NV:
8817117f1b4Smrg      case GL_PROXY_TEXTURE_RECTANGLE_NV:
8827117f1b4Smrg         if (ctx->Extensions.NV_texture_rectangle && level == 0)
8837117f1b4Smrg            return texObj->Image[0][level];
8847117f1b4Smrg         else
8857117f1b4Smrg            return NULL;
8867117f1b4Smrg
887c1f859d4Smrg      case GL_TEXTURE_1D_ARRAY_EXT:
888c1f859d4Smrg      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
889c1f859d4Smrg      case GL_TEXTURE_2D_ARRAY_EXT:
890c1f859d4Smrg      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
891c1f859d4Smrg         return (ctx->Extensions.MESA_texture_array)
892c1f859d4Smrg            ? texObj->Image[0][level] : NULL;
893c1f859d4Smrg
8947117f1b4Smrg      default:
8957117f1b4Smrg         return NULL;
8967117f1b4Smrg   }
8977117f1b4Smrg}
8987117f1b4Smrg
8997117f1b4Smrg
9007117f1b4Smrg/**
9017117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
9027117f1b4Smrg * it and install it.  Only return NULL if passed a bad parameter or run
9037117f1b4Smrg * out of memory.
9047117f1b4Smrg */
9057117f1b4Smrgstruct gl_texture_image *
9067117f1b4Smrg_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
9077117f1b4Smrg                    GLenum target, GLint level)
9087117f1b4Smrg{
9097117f1b4Smrg   struct gl_texture_image *texImage;
9107117f1b4Smrg
9117117f1b4Smrg   if (!texObj)
9127117f1b4Smrg      return NULL;
9137117f1b4Smrg
9147117f1b4Smrg   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
9157117f1b4Smrg   if (!texImage) {
9167117f1b4Smrg      texImage = ctx->Driver.NewTextureImage(ctx);
9177117f1b4Smrg      if (!texImage) {
9187117f1b4Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
9197117f1b4Smrg         return NULL;
9207117f1b4Smrg      }
9217117f1b4Smrg
9227117f1b4Smrg      _mesa_set_tex_image(texObj, target, level, texImage);
9237117f1b4Smrg   }
9247117f1b4Smrg
9257117f1b4Smrg   return texImage;
9267117f1b4Smrg}
9277117f1b4Smrg
9287117f1b4Smrg
9297117f1b4Smrg/**
9307117f1b4Smrg * Return pointer to the specified proxy texture image.
9317117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit.
9327117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid
9337117f1b4Smrg *         level, or out of memory.
9347117f1b4Smrg */
9357117f1b4Smrgstruct gl_texture_image *
9367117f1b4Smrg_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
9377117f1b4Smrg{
9387117f1b4Smrg   struct gl_texture_image *texImage;
9397117f1b4Smrg
9407117f1b4Smrg   if (level < 0 )
9417117f1b4Smrg      return NULL;
9427117f1b4Smrg
9437117f1b4Smrg   switch (target) {
9447117f1b4Smrg   case GL_PROXY_TEXTURE_1D:
9457117f1b4Smrg      if (level >= ctx->Const.MaxTextureLevels)
9467117f1b4Smrg         return NULL;
947c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level];
9487117f1b4Smrg      if (!texImage) {
9497117f1b4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
9507117f1b4Smrg         if (!texImage) {
9517117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
9527117f1b4Smrg            return NULL;
9537117f1b4Smrg         }
954c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level] = texImage;
9557117f1b4Smrg         /* Set the 'back' pointer */
956c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
9577117f1b4Smrg      }
9587117f1b4Smrg      return texImage;
9597117f1b4Smrg   case GL_PROXY_TEXTURE_2D:
9607117f1b4Smrg      if (level >= ctx->Const.MaxTextureLevels)
9617117f1b4Smrg         return NULL;
962c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level];
9637117f1b4Smrg      if (!texImage) {
9647117f1b4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
9657117f1b4Smrg         if (!texImage) {
9667117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
9677117f1b4Smrg            return NULL;
9687117f1b4Smrg         }
969c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level] = texImage;
9707117f1b4Smrg         /* Set the 'back' pointer */
971c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
9727117f1b4Smrg      }
9737117f1b4Smrg      return texImage;
9747117f1b4Smrg   case GL_PROXY_TEXTURE_3D:
9757117f1b4Smrg      if (level >= ctx->Const.Max3DTextureLevels)
9767117f1b4Smrg         return NULL;
977c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level];
9787117f1b4Smrg      if (!texImage) {
9797117f1b4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
9807117f1b4Smrg         if (!texImage) {
9817117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
9827117f1b4Smrg            return NULL;
9837117f1b4Smrg         }
984c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level] = texImage;
9857117f1b4Smrg         /* Set the 'back' pointer */
986c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
9877117f1b4Smrg      }
9887117f1b4Smrg      return texImage;
9897117f1b4Smrg   case GL_PROXY_TEXTURE_CUBE_MAP:
9907117f1b4Smrg      if (level >= ctx->Const.MaxCubeTextureLevels)
9917117f1b4Smrg         return NULL;
992c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level];
9937117f1b4Smrg      if (!texImage) {
9947117f1b4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
9957117f1b4Smrg         if (!texImage) {
9967117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
9977117f1b4Smrg            return NULL;
9987117f1b4Smrg         }
999c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level] = texImage;
10007117f1b4Smrg         /* Set the 'back' pointer */
1001c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX];
10027117f1b4Smrg      }
10037117f1b4Smrg      return texImage;
10047117f1b4Smrg   case GL_PROXY_TEXTURE_RECTANGLE_NV:
10057117f1b4Smrg      if (level > 0)
10067117f1b4Smrg         return NULL;
1007c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level];
1008c1f859d4Smrg      if (!texImage) {
1009c1f859d4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
1010c1f859d4Smrg         if (!texImage) {
1011c1f859d4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
1012c1f859d4Smrg            return NULL;
1013c1f859d4Smrg         }
1014c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level] = texImage;
1015c1f859d4Smrg         /* Set the 'back' pointer */
1016c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX];
1017c1f859d4Smrg      }
1018c1f859d4Smrg      return texImage;
1019c1f859d4Smrg   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1020c1f859d4Smrg      if (level >= ctx->Const.MaxTextureLevels)
1021c1f859d4Smrg         return NULL;
1022c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level];
10237117f1b4Smrg      if (!texImage) {
10247117f1b4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
10257117f1b4Smrg         if (!texImage) {
10267117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
10277117f1b4Smrg            return NULL;
10287117f1b4Smrg         }
1029c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level] = texImage;
10307117f1b4Smrg         /* Set the 'back' pointer */
1031c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX];
1032c1f859d4Smrg      }
1033c1f859d4Smrg      return texImage;
1034c1f859d4Smrg   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1035c1f859d4Smrg      if (level >= ctx->Const.MaxTextureLevels)
1036c1f859d4Smrg         return NULL;
1037c1f859d4Smrg      texImage = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level];
1038c1f859d4Smrg      if (!texImage) {
1039c1f859d4Smrg         texImage = ctx->Driver.NewTextureImage(ctx);
1040c1f859d4Smrg         if (!texImage) {
1041c1f859d4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
1042c1f859d4Smrg            return NULL;
1043c1f859d4Smrg         }
1044c1f859d4Smrg         ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level] = texImage;
1045c1f859d4Smrg         /* Set the 'back' pointer */
1046c1f859d4Smrg         texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX];
10477117f1b4Smrg      }
10487117f1b4Smrg      return texImage;
10497117f1b4Smrg   default:
10507117f1b4Smrg      return NULL;
10517117f1b4Smrg   }
10527117f1b4Smrg}
10537117f1b4Smrg
10547117f1b4Smrg
10557117f1b4Smrg/**
10567117f1b4Smrg * Get the maximum number of allowed mipmap levels.
10577117f1b4Smrg *
10587117f1b4Smrg * \param ctx GL context.
10597117f1b4Smrg * \param target texture target.
10607117f1b4Smrg *
10617117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given
10627117f1b4Smrg * texture target, or zero if passed a bad target.
10637117f1b4Smrg *
10647117f1b4Smrg * \sa gl_constants.
10657117f1b4Smrg */
10667117f1b4SmrgGLint
10677117f1b4Smrg_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
10687117f1b4Smrg{
10697117f1b4Smrg   switch (target) {
10707117f1b4Smrg   case GL_TEXTURE_1D:
10717117f1b4Smrg   case GL_PROXY_TEXTURE_1D:
10727117f1b4Smrg   case GL_TEXTURE_2D:
10737117f1b4Smrg   case GL_PROXY_TEXTURE_2D:
1074c1f859d4Smrg   case GL_TEXTURE_1D_ARRAY_EXT:
1075c1f859d4Smrg   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1076c1f859d4Smrg   case GL_TEXTURE_2D_ARRAY_EXT:
1077c1f859d4Smrg   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
10787117f1b4Smrg      return ctx->Const.MaxTextureLevels;
10797117f1b4Smrg   case GL_TEXTURE_3D:
10807117f1b4Smrg   case GL_PROXY_TEXTURE_3D:
10817117f1b4Smrg      return ctx->Const.Max3DTextureLevels;
10827117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
10837117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
10847117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
10857117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
10867117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
10877117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
10887117f1b4Smrg   case GL_TEXTURE_CUBE_MAP_ARB:
10897117f1b4Smrg   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
10907117f1b4Smrg      return ctx->Const.MaxCubeTextureLevels;
10917117f1b4Smrg   case GL_TEXTURE_RECTANGLE_NV:
10927117f1b4Smrg   case GL_PROXY_TEXTURE_RECTANGLE_NV:
10937117f1b4Smrg      return 1;
10947117f1b4Smrg   default:
10957117f1b4Smrg      return 0; /* bad target */
10967117f1b4Smrg   }
10977117f1b4Smrg}
10987117f1b4Smrg
10997117f1b4Smrg
11007117f1b4Smrg
11017117f1b4Smrg#if 000 /* not used anymore */
11027117f1b4Smrg/*
11037117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer.  In this case we
11047117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL
11057117f1b4Smrg * spec.
11067117f1b4Smrg */
11077117f1b4Smrgstatic GLubyte *
11087117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format)
11097117f1b4Smrg{
11107117f1b4Smrg   const GLint components = _mesa_components_in_format(format);
11117117f1b4Smrg   const GLint numPixels = width * height * depth;
11127117f1b4Smrg   GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
11137117f1b4Smrg
11147117f1b4Smrg#ifdef DEBUG
11157117f1b4Smrg   /*
11167117f1b4Smrg    * Let's see if anyone finds this.  If glTexImage2D() is called with
11177117f1b4Smrg    * a NULL image pointer then load the texture image with something
11187117f1b4Smrg    * interesting instead of leaving it indeterminate.
11197117f1b4Smrg    */
11207117f1b4Smrg   if (data) {
11217117f1b4Smrg      static const char message[8][32] = {
11227117f1b4Smrg         "   X   X  XXXXX   XXX     X    ",
11237117f1b4Smrg         "   XX XX  X      X   X   X X   ",
11247117f1b4Smrg         "   X X X  X      X      X   X  ",
11257117f1b4Smrg         "   X   X  XXXX    XXX   XXXXX  ",
11267117f1b4Smrg         "   X   X  X          X  X   X  ",
11277117f1b4Smrg         "   X   X  X      X   X  X   X  ",
11287117f1b4Smrg         "   X   X  XXXXX   XXX   X   X  ",
11297117f1b4Smrg         "                               "
11307117f1b4Smrg      };
11317117f1b4Smrg
11327117f1b4Smrg      GLubyte *imgPtr = data;
11337117f1b4Smrg      GLint h, i, j, k;
11347117f1b4Smrg      for (h = 0; h < depth; h++) {
11357117f1b4Smrg         for (i = 0; i < height; i++) {
11367117f1b4Smrg            GLint srcRow = 7 - (i % 8);
11377117f1b4Smrg            for (j = 0; j < width; j++) {
11387117f1b4Smrg               GLint srcCol = j % 32;
11397117f1b4Smrg               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
11407117f1b4Smrg               for (k = 0; k < components; k++) {
11417117f1b4Smrg                  *imgPtr++ = texel;
11427117f1b4Smrg               }
11437117f1b4Smrg            }
11447117f1b4Smrg         }
11457117f1b4Smrg      }
11467117f1b4Smrg   }
11477117f1b4Smrg#endif
11487117f1b4Smrg
11497117f1b4Smrg   return data;
11507117f1b4Smrg}
11517117f1b4Smrg#endif
11527117f1b4Smrg
11537117f1b4Smrg
11547117f1b4Smrg
11557117f1b4Smrg/**
11567117f1b4Smrg * Reset the fields of a gl_texture_image struct to zero.
11577117f1b4Smrg *
11587117f1b4Smrg * \param img texture image structure.
11597117f1b4Smrg *
11607117f1b4Smrg * This is called when a proxy texture test fails, we set all the
11617117f1b4Smrg * image members (except DriverData) to zero.
11627117f1b4Smrg * It's also used in glTexImage[123]D as a safeguard to be sure all
11637117f1b4Smrg * required fields get initialized properly by the Driver.TexImage[123]D
11647117f1b4Smrg * functions.
11657117f1b4Smrg */
11667117f1b4Smrgstatic void
11677117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img)
11687117f1b4Smrg{
11697117f1b4Smrg   ASSERT(img);
11707117f1b4Smrg   img->_BaseFormat = 0;
11717117f1b4Smrg   img->InternalFormat = 0;
11727117f1b4Smrg   img->Border = 0;
11737117f1b4Smrg   img->Width = 0;
11747117f1b4Smrg   img->Height = 0;
11757117f1b4Smrg   img->Depth = 0;
11767117f1b4Smrg   img->RowStride = 0;
11777117f1b4Smrg   if (img->ImageOffsets) {
11787117f1b4Smrg      _mesa_free(img->ImageOffsets);
11797117f1b4Smrg      img->ImageOffsets = NULL;
11807117f1b4Smrg   }
11817117f1b4Smrg   img->Width2 = 0;
11827117f1b4Smrg   img->Height2 = 0;
11837117f1b4Smrg   img->Depth2 = 0;
11847117f1b4Smrg   img->WidthLog2 = 0;
11857117f1b4Smrg   img->HeightLog2 = 0;
11867117f1b4Smrg   img->DepthLog2 = 0;
11877117f1b4Smrg   img->Data = NULL;
11887117f1b4Smrg   img->TexFormat = &_mesa_null_texformat;
11897117f1b4Smrg   img->FetchTexelc = NULL;
11907117f1b4Smrg   img->FetchTexelf = NULL;
11917117f1b4Smrg   img->IsCompressed = 0;
11927117f1b4Smrg   img->CompressedSize = 0;
11937117f1b4Smrg}
11947117f1b4Smrg
11957117f1b4Smrg
11967117f1b4Smrg/**
11977117f1b4Smrg * Initialize basic fields of the gl_texture_image struct.
11987117f1b4Smrg *
11997117f1b4Smrg * \param ctx GL context.
12007117f1b4Smrg * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
12017117f1b4Smrg * \param img texture image structure to be initialized.
12027117f1b4Smrg * \param width image width.
12037117f1b4Smrg * \param height image height.
12047117f1b4Smrg * \param depth image depth.
12057117f1b4Smrg * \param border image border.
12067117f1b4Smrg * \param internalFormat internal format.
12077117f1b4Smrg *
12087117f1b4Smrg * Fills in the fields of \p img with the given information.
12097117f1b4Smrg * Note: width, height and depth include the border.
12107117f1b4Smrg */
12117117f1b4Smrgvoid
12127117f1b4Smrg_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
12137117f1b4Smrg                           struct gl_texture_image *img,
12147117f1b4Smrg                           GLsizei width, GLsizei height, GLsizei depth,
12157117f1b4Smrg                           GLint border, GLenum internalFormat)
12167117f1b4Smrg{
12177117f1b4Smrg   GLint i;
12187117f1b4Smrg
12197117f1b4Smrg   ASSERT(img);
12207117f1b4Smrg   ASSERT(width >= 0);
12217117f1b4Smrg   ASSERT(height >= 0);
12227117f1b4Smrg   ASSERT(depth >= 0);
12237117f1b4Smrg
12247117f1b4Smrg   img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
12257117f1b4Smrg   ASSERT(img->_BaseFormat > 0);
12267117f1b4Smrg   img->InternalFormat = internalFormat;
12277117f1b4Smrg   img->Border = border;
12287117f1b4Smrg   img->Width = width;
12297117f1b4Smrg   img->Height = height;
12307117f1b4Smrg   img->Depth = depth;
12317117f1b4Smrg   img->Width2 = width - 2 * border;   /* == 1 << img->WidthLog2; */
12327117f1b4Smrg   img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
12337117f1b4Smrg   img->Depth2 = depth - 2 * border;   /* == 1 << img->DepthLog2; */
12347117f1b4Smrg   img->WidthLog2 = logbase2(img->Width2);
12357117f1b4Smrg   if (height == 1)  /* 1-D texture */
12367117f1b4Smrg      img->HeightLog2 = 0;
12377117f1b4Smrg   else
12387117f1b4Smrg      img->HeightLog2 = logbase2(img->Height2);
12397117f1b4Smrg   if (depth == 1)   /* 2-D texture */
12407117f1b4Smrg      img->DepthLog2 = 0;
12417117f1b4Smrg   else
12427117f1b4Smrg      img->DepthLog2 = logbase2(img->Depth2);
12437117f1b4Smrg   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
12447117f1b4Smrg   img->IsCompressed = GL_FALSE;
12457117f1b4Smrg   img->CompressedSize = 0;
12467117f1b4Smrg
1247c1f859d4Smrg   if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
1248c1f859d4Smrg       (height == 1 || _mesa_is_pow_two(img->Height2)) &&
1249c1f859d4Smrg       (depth == 1 || _mesa_is_pow_two(img->Depth2)))
12507117f1b4Smrg      img->_IsPowerOfTwo = GL_TRUE;
12517117f1b4Smrg   else
12527117f1b4Smrg      img->_IsPowerOfTwo = GL_FALSE;
12537117f1b4Smrg
12547117f1b4Smrg   /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
12557117f1b4Smrg   img->RowStride = width;
12567117f1b4Smrg   /* Allocate the ImageOffsets array and initialize to typical values.
12577117f1b4Smrg    * We allocate the array for 1D/2D textures too in order to avoid special-
12587117f1b4Smrg    * case code in the texstore routines.
12597117f1b4Smrg    */
12607117f1b4Smrg   img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
12617117f1b4Smrg   for (i = 0; i < depth; i++) {
12627117f1b4Smrg      img->ImageOffsets[i] = i * width * height;
12637117f1b4Smrg   }
12647117f1b4Smrg
12657117f1b4Smrg   /* Compute Width/Height/DepthScale for mipmap lod computation */
12667117f1b4Smrg   if (target == GL_TEXTURE_RECTANGLE_NV) {
12677117f1b4Smrg      /* scale = 1.0 since texture coords directly map to texels */
12687117f1b4Smrg      img->WidthScale = 1.0;
12697117f1b4Smrg      img->HeightScale = 1.0;
12707117f1b4Smrg      img->DepthScale = 1.0;
12717117f1b4Smrg   }
12727117f1b4Smrg   else {
12737117f1b4Smrg      img->WidthScale = (GLfloat) img->Width;
12747117f1b4Smrg      img->HeightScale = (GLfloat) img->Height;
12757117f1b4Smrg      img->DepthScale = (GLfloat) img->Depth;
12767117f1b4Smrg   }
12777117f1b4Smrg}
12787117f1b4Smrg
12797117f1b4Smrg
12807117f1b4Smrg/**
12817117f1b4Smrg * This is the fallback for Driver.TestProxyTexImage().  Test the texture
12827117f1b4Smrg * level, width, height and depth against the ctx->Const limits for textures.
12837117f1b4Smrg *
12847117f1b4Smrg * A hardware driver might override this function if, for example, the
12857117f1b4Smrg * max 3D texture size is 512x512x64 (i.e. not a cube).
12867117f1b4Smrg *
12877117f1b4Smrg * Note that width, height, depth == 0 is not an error.  However, a
12887117f1b4Smrg * texture with zero width/height/depth will be considered "incomplete"
12897117f1b4Smrg * and texturing will effectively be disabled.
12907117f1b4Smrg *
12917117f1b4Smrg * \param target  one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
12927117f1b4Smrg *                GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
12937117f1b4Smrg *                GL_PROXY_TEXTURE_CUBE_MAP_ARB.
12947117f1b4Smrg * \param level  as passed to glTexImage
12957117f1b4Smrg * \param internalFormat  as passed to glTexImage
12967117f1b4Smrg * \param format  as passed to glTexImage
12977117f1b4Smrg * \param type  as passed to glTexImage
12987117f1b4Smrg * \param width  as passed to glTexImage
12997117f1b4Smrg * \param height  as passed to glTexImage
13007117f1b4Smrg * \param depth  as passed to glTexImage
13017117f1b4Smrg * \param border  as passed to glTexImage
13027117f1b4Smrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
13037117f1b4Smrg */
13047117f1b4SmrgGLboolean
13057117f1b4Smrg_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
13067117f1b4Smrg                          GLint internalFormat, GLenum format, GLenum type,
13077117f1b4Smrg                          GLint width, GLint height, GLint depth, GLint border)
13087117f1b4Smrg{
13097117f1b4Smrg   GLint maxSize;
13107117f1b4Smrg
13117117f1b4Smrg   (void) internalFormat;
13127117f1b4Smrg   (void) format;
13137117f1b4Smrg   (void) type;
13147117f1b4Smrg
13157117f1b4Smrg   switch (target) {
13167117f1b4Smrg   case GL_PROXY_TEXTURE_1D:
13177117f1b4Smrg      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
13187117f1b4Smrg      if (width < 2 * border || width > 2 + maxSize ||
13197117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1320c1f859d4Smrg           width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
13217117f1b4Smrg          level >= ctx->Const.MaxTextureLevels) {
13227117f1b4Smrg         /* bad width or level */
13237117f1b4Smrg         return GL_FALSE;
13247117f1b4Smrg      }
13257117f1b4Smrg      return GL_TRUE;
13267117f1b4Smrg   case GL_PROXY_TEXTURE_2D:
13277117f1b4Smrg      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
13287117f1b4Smrg      if (width < 2 * border || width > 2 + maxSize ||
13297117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1330c1f859d4Smrg           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
13317117f1b4Smrg          height < 2 * border || height > 2 + maxSize ||
13327117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1333c1f859d4Smrg           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
13347117f1b4Smrg          level >= ctx->Const.MaxTextureLevels) {
13357117f1b4Smrg         /* bad width or height or level */
13367117f1b4Smrg         return GL_FALSE;
13377117f1b4Smrg      }
13387117f1b4Smrg      return GL_TRUE;
13397117f1b4Smrg   case GL_PROXY_TEXTURE_3D:
13407117f1b4Smrg      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
13417117f1b4Smrg      if (width < 2 * border || width > 2 + maxSize ||
13427117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1343c1f859d4Smrg           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
13447117f1b4Smrg          height < 2 * border || height > 2 + maxSize ||
13457117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1346c1f859d4Smrg           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
13477117f1b4Smrg          depth < 2 * border || depth > 2 + maxSize ||
13487117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1349c1f859d4Smrg           depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
13507117f1b4Smrg          level >= ctx->Const.Max3DTextureLevels) {
13517117f1b4Smrg         /* bad width or height or depth or level */
13527117f1b4Smrg         return GL_FALSE;
13537117f1b4Smrg      }
13547117f1b4Smrg      return GL_TRUE;
13557117f1b4Smrg   case GL_PROXY_TEXTURE_RECTANGLE_NV:
13567117f1b4Smrg      if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
13577117f1b4Smrg          height < 0 || height > ctx->Const.MaxTextureRectSize ||
13587117f1b4Smrg          level != 0) {
13597117f1b4Smrg         /* bad width or height or level */
13607117f1b4Smrg         return GL_FALSE;
13617117f1b4Smrg      }
13627117f1b4Smrg      return GL_TRUE;
13637117f1b4Smrg   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
13647117f1b4Smrg      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
13657117f1b4Smrg      if (width < 2 * border || width > 2 + maxSize ||
13667117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1367c1f859d4Smrg           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
13687117f1b4Smrg          height < 2 * border || height > 2 + maxSize ||
13697117f1b4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1370c1f859d4Smrg           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
13717117f1b4Smrg          level >= ctx->Const.MaxCubeTextureLevels) {
13727117f1b4Smrg         /* bad width or height */
13737117f1b4Smrg         return GL_FALSE;
13747117f1b4Smrg      }
13757117f1b4Smrg      return GL_TRUE;
1376c1f859d4Smrg   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1377c1f859d4Smrg      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1378c1f859d4Smrg      if (width < 2 * border || width > 2 + maxSize ||
1379c1f859d4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1380c1f859d4Smrg           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1381c1f859d4Smrg          level >= ctx->Const.MaxTextureLevels) {
1382c1f859d4Smrg         /* bad width or level */
1383c1f859d4Smrg         return GL_FALSE;
1384c1f859d4Smrg      }
1385c1f859d4Smrg
1386c1f859d4Smrg      if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
1387c1f859d4Smrg         return GL_FALSE;
1388c1f859d4Smrg      }
1389c1f859d4Smrg      return GL_TRUE;
1390c1f859d4Smrg   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1391c1f859d4Smrg      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1392c1f859d4Smrg      if (width < 2 * border || width > 2 + maxSize ||
1393c1f859d4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1394c1f859d4Smrg           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1395c1f859d4Smrg          height < 2 * border || height > 2 + maxSize ||
1396c1f859d4Smrg          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1397c1f859d4Smrg           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1398c1f859d4Smrg          level >= ctx->Const.MaxTextureLevels) {
1399c1f859d4Smrg         /* bad width or height or level */
1400c1f859d4Smrg         return GL_FALSE;
1401c1f859d4Smrg      }
1402c1f859d4Smrg      if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
1403c1f859d4Smrg         return GL_FALSE;
1404c1f859d4Smrg      }
1405c1f859d4Smrg      return GL_TRUE;
14067117f1b4Smrg   default:
14077117f1b4Smrg      _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
14087117f1b4Smrg      return GL_FALSE;
14097117f1b4Smrg   }
14107117f1b4Smrg}
14117117f1b4Smrg
14127117f1b4Smrg
14137117f1b4Smrg/**
14147117f1b4Smrg * Helper function to determine whether a target supports compressed textures
14157117f1b4Smrg */
14167117f1b4Smrgstatic GLboolean
14177117f1b4Smrgtarget_can_be_compressed(GLcontext *ctx, GLenum target)
14187117f1b4Smrg{
14197117f1b4Smrg   return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
14207117f1b4Smrg           || ((ctx->Extensions.ARB_texture_cube_map &&
14217117f1b4Smrg                (target == GL_PROXY_TEXTURE_CUBE_MAP ||
14227117f1b4Smrg                 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1423c1f859d4Smrg                  target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
1424c1f859d4Smrg           || ((ctx->Extensions.MESA_texture_array &&
1425c1f859d4Smrg                ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
1426c1f859d4Smrg                 (target == GL_TEXTURE_2D_ARRAY_EXT)))));
14277117f1b4Smrg}
14287117f1b4Smrg
14297117f1b4Smrg
14307117f1b4Smrg/**
14317117f1b4Smrg * Test the glTexImage[123]D() parameters for errors.
14327117f1b4Smrg *
14337117f1b4Smrg * \param ctx GL context.
14347117f1b4Smrg * \param target texture target given by the user.
14357117f1b4Smrg * \param level image level given by the user.
14367117f1b4Smrg * \param internalFormat internal format given by the user.
14377117f1b4Smrg * \param format pixel data format given by the user.
14387117f1b4Smrg * \param type pixel data type given by the user.
14397117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3).
14407117f1b4Smrg * \param width image width given by the user.
14417117f1b4Smrg * \param height image height given by the user.
14427117f1b4Smrg * \param depth image depth given by the user.
14437117f1b4Smrg * \param border image border given by the user.
14447117f1b4Smrg *
14457117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
14467117f1b4Smrg *
14477117f1b4Smrg * Verifies each of the parameters against the constants specified in
14487117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the
14497117f1b4Smrg * OpenGL specification.
14507117f1b4Smrg */
14517117f1b4Smrgstatic GLboolean
14527117f1b4Smrgtexture_error_check( GLcontext *ctx, GLenum target,
14537117f1b4Smrg                     GLint level, GLint internalFormat,
14547117f1b4Smrg                     GLenum format, GLenum type,
14557117f1b4Smrg                     GLuint dimensions,
14567117f1b4Smrg                     GLint width, GLint height,
14577117f1b4Smrg                     GLint depth, GLint border )
14587117f1b4Smrg{
14597117f1b4Smrg   const GLboolean isProxy = _mesa_is_proxy_texture(target);
14607117f1b4Smrg   GLboolean sizeOK = GL_TRUE;
14617117f1b4Smrg   GLboolean colorFormat, indexFormat;
14627117f1b4Smrg   GLenum proxy_target;
14637117f1b4Smrg
14647117f1b4Smrg   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
14657117f1b4Smrg   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
14667117f1b4Smrg      if (!isProxy) {
14677117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
14687117f1b4Smrg                     "glTexImage%dD(level=%d)", dimensions, level);
14697117f1b4Smrg      }
14707117f1b4Smrg      return GL_TRUE;
14717117f1b4Smrg   }
14727117f1b4Smrg
14737117f1b4Smrg   /* Check border */
14747117f1b4Smrg   if (border < 0 || border > 1 ||
14757117f1b4Smrg       ((target == GL_TEXTURE_RECTANGLE_NV ||
14767117f1b4Smrg         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
14777117f1b4Smrg      if (!isProxy) {
14787117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
14797117f1b4Smrg                     "glTexImage%dD(border=%d)", dimensions, border);
14807117f1b4Smrg      }
14817117f1b4Smrg      return GL_TRUE;
14827117f1b4Smrg   }
14837117f1b4Smrg
14847117f1b4Smrg   if (width < 0 || height < 0 || depth < 0) {
14857117f1b4Smrg      if (!isProxy) {
14867117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
14877117f1b4Smrg                     "glTexImage%dD(width, height or depth < 0)", dimensions);
14887117f1b4Smrg      }
14897117f1b4Smrg      return GL_TRUE;
14907117f1b4Smrg   }
14917117f1b4Smrg
14927117f1b4Smrg   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
14937117f1b4Smrg    * level, width, height and depth.
14947117f1b4Smrg    */
14957117f1b4Smrg   if (dimensions == 1) {
14967117f1b4Smrg      if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
14977117f1b4Smrg         proxy_target = GL_PROXY_TEXTURE_1D;
14987117f1b4Smrg         height = 1;
14997117f1b4Smrg         depth = 1;
15007117f1b4Smrg      }
15017117f1b4Smrg      else {
15027117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
15037117f1b4Smrg         return GL_TRUE;
15047117f1b4Smrg      }
15057117f1b4Smrg   }
15067117f1b4Smrg   else if (dimensions == 2) {
15077117f1b4Smrg      depth = 1;
15087117f1b4Smrg      if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
15097117f1b4Smrg         proxy_target = GL_PROXY_TEXTURE_2D;
15107117f1b4Smrg      }
15117117f1b4Smrg      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
15127117f1b4Smrg               (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
15137117f1b4Smrg                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
15147117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map) {
15157117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
15167117f1b4Smrg            return GL_TRUE;
15177117f1b4Smrg         }
15187117f1b4Smrg         proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
15197117f1b4Smrg         sizeOK = (width == height);
15207117f1b4Smrg      }
15217117f1b4Smrg      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
15227117f1b4Smrg               target == GL_TEXTURE_RECTANGLE_NV) {
15237117f1b4Smrg         if (!ctx->Extensions.NV_texture_rectangle) {
15247117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
15257117f1b4Smrg            return GL_TRUE;
15267117f1b4Smrg         }
15277117f1b4Smrg         proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
15287117f1b4Smrg      }
1529c1f859d4Smrg      else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
1530c1f859d4Smrg               target == GL_TEXTURE_1D_ARRAY_EXT) {
1531c1f859d4Smrg         proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
1532c1f859d4Smrg      }
15337117f1b4Smrg      else {
15347117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
15357117f1b4Smrg         return GL_TRUE;
15367117f1b4Smrg      }
15377117f1b4Smrg   }
15387117f1b4Smrg   else if (dimensions == 3) {
15397117f1b4Smrg      if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
15407117f1b4Smrg         proxy_target = GL_PROXY_TEXTURE_3D;
15417117f1b4Smrg      }
1542c1f859d4Smrg      else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
1543c1f859d4Smrg               target == GL_TEXTURE_2D_ARRAY_EXT) {
1544c1f859d4Smrg         proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
1545c1f859d4Smrg      }
15467117f1b4Smrg      else {
15477117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
15487117f1b4Smrg         return GL_TRUE;
15497117f1b4Smrg      }
15507117f1b4Smrg   }
15517117f1b4Smrg   else {
15527117f1b4Smrg      _mesa_problem( ctx, "bad dims in texture_error_check" );
15537117f1b4Smrg      return GL_TRUE;
15547117f1b4Smrg   }
15557117f1b4Smrg
15567117f1b4Smrg   sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
15577117f1b4Smrg                                                    internalFormat, format,
15587117f1b4Smrg                                                    type, width, height,
15597117f1b4Smrg                                                    depth, border);
15607117f1b4Smrg   if (!sizeOK) {
15617117f1b4Smrg      if (!isProxy) {
15627117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
15637117f1b4Smrg                     "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
15647117f1b4Smrg                     dimensions, level, width, height, depth);
15657117f1b4Smrg      }
15667117f1b4Smrg      return GL_TRUE;
15677117f1b4Smrg   }
15687117f1b4Smrg
15697117f1b4Smrg   /* Check internalFormat */
15707117f1b4Smrg   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
15717117f1b4Smrg      if (!isProxy) {
15727117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
15737117f1b4Smrg                     "glTexImage%dD(internalFormat=0x%x)",
15747117f1b4Smrg                     dimensions, internalFormat);
15757117f1b4Smrg      }
15767117f1b4Smrg      return GL_TRUE;
15777117f1b4Smrg   }
15787117f1b4Smrg
15797117f1b4Smrg   /* Check incoming image format and type */
15807117f1b4Smrg   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
15817117f1b4Smrg      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
15827117f1b4Smrg       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
15837117f1b4Smrg       */
15847117f1b4Smrg      if (!isProxy) {
15857117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
15867117f1b4Smrg                     "glTexImage%dD(format or type)", dimensions);
15877117f1b4Smrg      }
15887117f1b4Smrg      return GL_TRUE;
15897117f1b4Smrg   }
15907117f1b4Smrg
15917117f1b4Smrg   /* make sure internal format and format basically agree */
1592c1f859d4Smrg   colorFormat = _mesa_is_color_format(format);
15937117f1b4Smrg   indexFormat = is_index_format(format);
1594c1f859d4Smrg   if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
15957117f1b4Smrg       (is_index_format(internalFormat) && !indexFormat) ||
15967117f1b4Smrg       (is_depth_format(internalFormat) != is_depth_format(format)) ||
15977117f1b4Smrg       (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
15987117f1b4Smrg       (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
15997117f1b4Smrg      if (!isProxy)
16007117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
16017117f1b4Smrg                     "glTexImage(internalFormat/format)");
16027117f1b4Smrg      return GL_TRUE;
16037117f1b4Smrg   }
16047117f1b4Smrg
16057117f1b4Smrg   /* additional checks for ycbcr textures */
16067117f1b4Smrg   if (internalFormat == GL_YCBCR_MESA) {
16077117f1b4Smrg      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
16087117f1b4Smrg      if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
16097117f1b4Smrg          type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
16107117f1b4Smrg         char message[100];
16117117f1b4Smrg         _mesa_sprintf(message,
16127117f1b4Smrg                 "glTexImage%d(format/type YCBCR mismatch", dimensions);
16137117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, message);
16147117f1b4Smrg         return GL_TRUE; /* error */
16157117f1b4Smrg      }
16167117f1b4Smrg      if (target != GL_TEXTURE_2D &&
16177117f1b4Smrg          target != GL_PROXY_TEXTURE_2D &&
16187117f1b4Smrg          target != GL_TEXTURE_RECTANGLE_NV &&
16197117f1b4Smrg          target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
16207117f1b4Smrg         if (!isProxy)
16217117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
16227117f1b4Smrg         return GL_TRUE;
16237117f1b4Smrg      }
16247117f1b4Smrg      if (border != 0) {
16257117f1b4Smrg         if (!isProxy) {
16267117f1b4Smrg            char message[100];
16277117f1b4Smrg            _mesa_sprintf(message,
16287117f1b4Smrg                    "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
16297117f1b4Smrg                    dimensions, border);
16307117f1b4Smrg            _mesa_error(ctx, GL_INVALID_VALUE, message);
16317117f1b4Smrg         }
16327117f1b4Smrg         return GL_TRUE;
16337117f1b4Smrg      }
16347117f1b4Smrg   }
16357117f1b4Smrg
16367117f1b4Smrg   /* additional checks for depth textures */
16377117f1b4Smrg   if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
16387117f1b4Smrg      /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
16397117f1b4Smrg      if (target != GL_TEXTURE_1D &&
16407117f1b4Smrg          target != GL_PROXY_TEXTURE_1D &&
16417117f1b4Smrg          target != GL_TEXTURE_2D &&
16427117f1b4Smrg          target != GL_PROXY_TEXTURE_2D &&
16437117f1b4Smrg          target != GL_TEXTURE_RECTANGLE_ARB &&
16447117f1b4Smrg          target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
16457117f1b4Smrg         if (!isProxy)
16467117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM,
16477117f1b4Smrg                        "glTexImage(target/internalFormat)");
16487117f1b4Smrg         return GL_TRUE;
16497117f1b4Smrg      }
16507117f1b4Smrg   }
16517117f1b4Smrg
16527117f1b4Smrg   /* additional checks for compressed textures */
16537117f1b4Smrg   if (is_compressed_format(ctx, internalFormat)) {
16547117f1b4Smrg      if (!target_can_be_compressed(ctx, target) && !isProxy) {
16557117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM,
16567117f1b4Smrg                     "glTexImage%d(target)", dimensions);
16577117f1b4Smrg         return GL_TRUE;
16587117f1b4Smrg      }
16597117f1b4Smrg      if (border != 0) {
16607117f1b4Smrg         if (!isProxy) {
16617117f1b4Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
16627117f1b4Smrg                        "glTexImage%D(border!=0)", dimensions);
16637117f1b4Smrg         }
16647117f1b4Smrg         return GL_TRUE;
16657117f1b4Smrg      }
16667117f1b4Smrg   }
16677117f1b4Smrg
16687117f1b4Smrg   /* if we get here, the parameters are OK */
16697117f1b4Smrg   return GL_FALSE;
16707117f1b4Smrg}
16717117f1b4Smrg
16727117f1b4Smrg
16737117f1b4Smrg/**
16747117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors.
16757117f1b4Smrg *
16767117f1b4Smrg * \param ctx GL context.
16777117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3).
16787117f1b4Smrg * \param target texture target given by the user.
16797117f1b4Smrg * \param level image level given by the user.
16807117f1b4Smrg * \param xoffset sub-image x offset given by the user.
16817117f1b4Smrg * \param yoffset sub-image y offset given by the user.
16827117f1b4Smrg * \param zoffset sub-image z offset given by the user.
16837117f1b4Smrg * \param format pixel data format given by the user.
16847117f1b4Smrg * \param type pixel data type given by the user.
16857117f1b4Smrg * \param width image width given by the user.
16867117f1b4Smrg * \param height image height given by the user.
16877117f1b4Smrg * \param depth image depth given by the user.
16887117f1b4Smrg *
16897117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
16907117f1b4Smrg *
16917117f1b4Smrg * Verifies each of the parameters against the constants specified in
16927117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the
16937117f1b4Smrg * OpenGL specification.
16947117f1b4Smrg */
16957117f1b4Smrgstatic GLboolean
16967117f1b4Smrgsubtexture_error_check( GLcontext *ctx, GLuint dimensions,
16977117f1b4Smrg                        GLenum target, GLint level,
16987117f1b4Smrg                        GLint xoffset, GLint yoffset, GLint zoffset,
16997117f1b4Smrg                        GLint width, GLint height, GLint depth,
17007117f1b4Smrg                        GLenum format, GLenum type )
17017117f1b4Smrg{
17027117f1b4Smrg   /* Check target */
17037117f1b4Smrg   if (dimensions == 1) {
17047117f1b4Smrg      if (target != GL_TEXTURE_1D) {
17057117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
17067117f1b4Smrg         return GL_TRUE;
17077117f1b4Smrg      }
17087117f1b4Smrg   }
17097117f1b4Smrg   else if (dimensions == 2) {
17107117f1b4Smrg      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
17117117f1b4Smrg          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
17127117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map) {
17137117f1b4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
17147117f1b4Smrg            return GL_TRUE;
17157117f1b4Smrg         }
17167117f1b4Smrg      }
17177117f1b4Smrg      else if (target == GL_TEXTURE_RECTANGLE_NV) {
17187117f1b4Smrg         if (!ctx->Extensions.NV_texture_rectangle) {
17197117f1b4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
17207117f1b4Smrg            return GL_TRUE;
17217117f1b4Smrg         }
17227117f1b4Smrg      }
1723c1f859d4Smrg      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1724c1f859d4Smrg        if (!ctx->Extensions.MESA_texture_array) {
1725c1f859d4Smrg           _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1726c1f859d4Smrg           return GL_TRUE;
1727c1f859d4Smrg        }
1728c1f859d4Smrg      }
17297117f1b4Smrg      else if (target != GL_TEXTURE_2D) {
17307117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
17317117f1b4Smrg         return GL_TRUE;
17327117f1b4Smrg      }
17337117f1b4Smrg   }
17347117f1b4Smrg   else if (dimensions == 3) {
1735c1f859d4Smrg      if (target == GL_TEXTURE_2D_ARRAY_EXT) {
1736c1f859d4Smrg         if (!ctx->Extensions.MESA_texture_array) {
1737c1f859d4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1738c1f859d4Smrg            return GL_TRUE;
1739c1f859d4Smrg         }
1740c1f859d4Smrg      }
1741c1f859d4Smrg      else if (target != GL_TEXTURE_3D) {
17427117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
17437117f1b4Smrg         return GL_TRUE;
17447117f1b4Smrg      }
17457117f1b4Smrg   }
17467117f1b4Smrg   else {
17477117f1b4Smrg      _mesa_problem( ctx, "invalid dims in texture_error_check" );
17487117f1b4Smrg      return GL_TRUE;
17497117f1b4Smrg   }
17507117f1b4Smrg
17517117f1b4Smrg   /* Basic level check */
17527117f1b4Smrg   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
17537117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
17547117f1b4Smrg      return GL_TRUE;
17557117f1b4Smrg   }
17567117f1b4Smrg
17577117f1b4Smrg   if (width < 0) {
17587117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
17597117f1b4Smrg                  "glTexSubImage%dD(width=%d)", dimensions, width);
17607117f1b4Smrg      return GL_TRUE;
17617117f1b4Smrg   }
17627117f1b4Smrg   if (height < 0 && dimensions > 1) {
17637117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
17647117f1b4Smrg                  "glTexSubImage%dD(height=%d)", dimensions, height);
17657117f1b4Smrg      return GL_TRUE;
17667117f1b4Smrg   }
17677117f1b4Smrg   if (depth < 0 && dimensions > 2) {
17687117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
17697117f1b4Smrg                  "glTexSubImage%dD(depth=%d)", dimensions, depth);
17707117f1b4Smrg      return GL_TRUE;
17717117f1b4Smrg   }
17727117f1b4Smrg
17737117f1b4Smrg   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
17747117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
17757117f1b4Smrg                  "glTexSubImage%dD(format or type)", dimensions);
17767117f1b4Smrg      return GL_TRUE;
17777117f1b4Smrg   }
17787117f1b4Smrg
17797117f1b4Smrg   return GL_FALSE;
17807117f1b4Smrg}
17817117f1b4Smrg
17827117f1b4Smrgstatic GLboolean
17837117f1b4Smrgsubtexture_error_check2( GLcontext *ctx, GLuint dimensions,
17847117f1b4Smrg			 GLenum target, GLint level,
17857117f1b4Smrg			 GLint xoffset, GLint yoffset, GLint zoffset,
17867117f1b4Smrg			 GLint width, GLint height, GLint depth,
17877117f1b4Smrg			 GLenum format, GLenum type,
17887117f1b4Smrg			 const struct gl_texture_image *destTex )
17897117f1b4Smrg{
17907117f1b4Smrg   if (!destTex) {
17917117f1b4Smrg      /* undefined image level */
17927117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
17937117f1b4Smrg      return GL_TRUE;
17947117f1b4Smrg   }
17957117f1b4Smrg
17967117f1b4Smrg   if (xoffset < -((GLint)destTex->Border)) {
17977117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
17987117f1b4Smrg                  dimensions);
17997117f1b4Smrg      return GL_TRUE;
18007117f1b4Smrg   }
18017117f1b4Smrg   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
18027117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
18037117f1b4Smrg                  dimensions);
18047117f1b4Smrg      return GL_TRUE;
18057117f1b4Smrg   }
18067117f1b4Smrg   if (dimensions > 1) {
18077117f1b4Smrg      if (yoffset < -((GLint)destTex->Border)) {
18087117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
18097117f1b4Smrg                     dimensions);
18107117f1b4Smrg         return GL_TRUE;
18117117f1b4Smrg      }
18127117f1b4Smrg      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
18137117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
18147117f1b4Smrg                     dimensions);
18157117f1b4Smrg         return GL_TRUE;
18167117f1b4Smrg      }
18177117f1b4Smrg   }
18187117f1b4Smrg   if (dimensions > 2) {
18197117f1b4Smrg      if (zoffset < -((GLint)destTex->Border)) {
18207117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
18217117f1b4Smrg         return GL_TRUE;
18227117f1b4Smrg      }
18237117f1b4Smrg      if (zoffset + depth  > (GLint) (destTex->Depth + destTex->Border)) {
18247117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
18257117f1b4Smrg         return GL_TRUE;
18267117f1b4Smrg      }
18277117f1b4Smrg   }
18287117f1b4Smrg
18297117f1b4Smrg#if FEATURE_EXT_texture_sRGB
18307117f1b4Smrg   if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
18317117f1b4Smrg       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
18327117f1b4Smrg       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
18337117f1b4Smrg       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
18347117f1b4Smrg      if ((width & 0x3) || (height & 0x3) ||
18357117f1b4Smrg          (xoffset & 0x3) || (yoffset & 0x3))
18367117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
18377117f1b4Smrg                     "glTexSubImage%dD(size or offset not multiple of 4)",
18387117f1b4Smrg                     dimensions);
18397117f1b4Smrg      return GL_TRUE;
18407117f1b4Smrg   }
18417117f1b4Smrg#endif
18427117f1b4Smrg
18437117f1b4Smrg   if (destTex->IsCompressed) {
18447117f1b4Smrg      if (!target_can_be_compressed(ctx, target)) {
18457117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM,
18467117f1b4Smrg                     "glTexSubImage%D(target)", dimensions);
18477117f1b4Smrg         return GL_TRUE;
18487117f1b4Smrg      }
18497117f1b4Smrg      /* offset must be multiple of 4 */
18507117f1b4Smrg      if ((xoffset & 3) || (yoffset & 3)) {
18517117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
18527117f1b4Smrg                     "glTexSubImage%D(xoffset or yoffset)", dimensions);
18537117f1b4Smrg         return GL_TRUE;
18547117f1b4Smrg      }
18557117f1b4Smrg      /* size must be multiple of 4 or equal to whole texture size */
18567117f1b4Smrg      if ((width & 3) && (GLuint) width != destTex->Width) {
18577117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
18587117f1b4Smrg                     "glTexSubImage%D(width)", dimensions);
18597117f1b4Smrg         return GL_TRUE;
18607117f1b4Smrg      }
18617117f1b4Smrg      if ((height & 3) && (GLuint) height != destTex->Height) {
18627117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
18637117f1b4Smrg                     "glTexSubImage%D(width)", dimensions);
18647117f1b4Smrg         return GL_TRUE;
18657117f1b4Smrg      }
18667117f1b4Smrg   }
18677117f1b4Smrg
18687117f1b4Smrg   return GL_FALSE;
18697117f1b4Smrg}
18707117f1b4Smrg
18717117f1b4Smrg
18727117f1b4Smrg/**
18737117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors.
18747117f1b4Smrg *
18757117f1b4Smrg * \param ctx GL context.
18767117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3).
18777117f1b4Smrg * \param target texture target given by the user.
18787117f1b4Smrg * \param level image level given by the user.
18797117f1b4Smrg * \param internalFormat internal format given by the user.
18807117f1b4Smrg * \param width image width given by the user.
18817117f1b4Smrg * \param height image height given by the user.
18827117f1b4Smrg * \param depth image depth given by the user.
18837117f1b4Smrg * \param border texture border.
18847117f1b4Smrg *
18857117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
18867117f1b4Smrg *
18877117f1b4Smrg * Verifies each of the parameters against the constants specified in
18887117f1b4Smrg * __GLcontextRec::Const and the supported extensions, and according to the
18897117f1b4Smrg * OpenGL specification.
18907117f1b4Smrg */
18917117f1b4Smrgstatic GLboolean
18927117f1b4Smrgcopytexture_error_check( GLcontext *ctx, GLuint dimensions,
18937117f1b4Smrg                         GLenum target, GLint level, GLint internalFormat,
18947117f1b4Smrg                         GLint width, GLint height, GLint border )
18957117f1b4Smrg{
18967117f1b4Smrg   GLenum type;
18977117f1b4Smrg   GLboolean sizeOK;
18987117f1b4Smrg   GLint format;
18997117f1b4Smrg
19007117f1b4Smrg   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
19017117f1b4Smrg   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
19027117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
19037117f1b4Smrg                  "glCopyTexImage%dD(level=%d)", dimensions, level);
19047117f1b4Smrg      return GL_TRUE;
19057117f1b4Smrg   }
19067117f1b4Smrg
19077117f1b4Smrg   /* Check that the source buffer is complete */
19087117f1b4Smrg   if (ctx->ReadBuffer->Name) {
19097117f1b4Smrg      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
19107117f1b4Smrg      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
19117117f1b4Smrg         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
19127117f1b4Smrg                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
19137117f1b4Smrg         return GL_TRUE;
19147117f1b4Smrg      }
19157117f1b4Smrg   }
19167117f1b4Smrg
19177117f1b4Smrg   /* Check border */
19187117f1b4Smrg   if (border < 0 || border > 1 ||
19197117f1b4Smrg       ((target == GL_TEXTURE_RECTANGLE_NV ||
19207117f1b4Smrg         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
19217117f1b4Smrg      return GL_TRUE;
19227117f1b4Smrg   }
19237117f1b4Smrg
19247117f1b4Smrg   format = _mesa_base_tex_format(ctx, internalFormat);
19257117f1b4Smrg   if (format < 0) {
19267117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
19277117f1b4Smrg                  "glCopyTexImage%dD(internalFormat)", dimensions);
19287117f1b4Smrg      return GL_TRUE;
19297117f1b4Smrg   }
19307117f1b4Smrg
19317117f1b4Smrg   /* NOTE: the format and type aren't really significant for
19327117f1b4Smrg    * TestProxyTexImage().  Only the internalformat really matters.
19337117f1b4Smrg   if (!_mesa_source_buffer_exists(ctx, format)) {
19347117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
19357117f1b4Smrg                  "glCopyTexImage%dD(missing readbuffer)", dimensions);
19367117f1b4Smrg      return GL_TRUE;
19377117f1b4Smrg   }
19387117f1b4Smrg
19397117f1b4Smrg    */
19407117f1b4Smrg   type = GL_FLOAT;
19417117f1b4Smrg
19427117f1b4Smrg   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
19437117f1b4Smrg    * level, width, height and depth.
19447117f1b4Smrg    */
19457117f1b4Smrg   if (dimensions == 1) {
19467117f1b4Smrg      if (target == GL_TEXTURE_1D) {
19477117f1b4Smrg         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
19487117f1b4Smrg                                                level, internalFormat,
19497117f1b4Smrg                                                format, type,
19507117f1b4Smrg                                                width, 1, 1, border);
19517117f1b4Smrg      }
19527117f1b4Smrg      else {
19537117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
19547117f1b4Smrg         return GL_TRUE;
19557117f1b4Smrg      }
19567117f1b4Smrg   }
19577117f1b4Smrg   else if (dimensions == 2) {
19587117f1b4Smrg      if (target == GL_TEXTURE_2D) {
19597117f1b4Smrg         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
19607117f1b4Smrg                                                level, internalFormat,
19617117f1b4Smrg                                                format, type,
19627117f1b4Smrg                                                width, height, 1, border);
19637117f1b4Smrg      }
19647117f1b4Smrg      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
19657117f1b4Smrg               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
19667117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map) {
19677117f1b4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
19687117f1b4Smrg            return GL_TRUE;
19697117f1b4Smrg         }
19707117f1b4Smrg         sizeOK = (width == height) &&
19717117f1b4Smrg            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
19727117f1b4Smrg                                          level, internalFormat, format, type,
19737117f1b4Smrg                                          width, height, 1, border);
19747117f1b4Smrg      }
19757117f1b4Smrg      else if (target == GL_TEXTURE_RECTANGLE_NV) {
19767117f1b4Smrg         if (!ctx->Extensions.NV_texture_rectangle) {
19777117f1b4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
19787117f1b4Smrg            return GL_TRUE;
19797117f1b4Smrg         }
19807117f1b4Smrg         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
19817117f1b4Smrg                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
19827117f1b4Smrg                                                level, internalFormat,
19837117f1b4Smrg                                                format, type,
19847117f1b4Smrg                                                width, height, 1, border);
19857117f1b4Smrg      }
1986c1f859d4Smrg      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1987c1f859d4Smrg         if (!ctx->Extensions.MESA_texture_array) {
1988c1f859d4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
1989c1f859d4Smrg            return GL_TRUE;
1990c1f859d4Smrg         }
1991c1f859d4Smrg         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1992c1f859d4Smrg                                                GL_PROXY_TEXTURE_1D_ARRAY_EXT,
1993c1f859d4Smrg                                                level, internalFormat,
1994c1f859d4Smrg                                                format, type,
1995c1f859d4Smrg                                                width, height, 1, border);
1996c1f859d4Smrg      }
19977117f1b4Smrg      else {
19987117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
19997117f1b4Smrg         return GL_TRUE;
20007117f1b4Smrg      }
20017117f1b4Smrg   }
20027117f1b4Smrg   else {
20037117f1b4Smrg      _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
20047117f1b4Smrg      return GL_TRUE;
20057117f1b4Smrg   }
20067117f1b4Smrg
20077117f1b4Smrg   if (!sizeOK) {
20087117f1b4Smrg      if (dimensions == 1) {
20097117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
20107117f1b4Smrg                     "glCopyTexImage1D(width=%d)", width);
20117117f1b4Smrg      }
20127117f1b4Smrg      else {
20137117f1b4Smrg         ASSERT(dimensions == 2);
20147117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
20157117f1b4Smrg                     "glCopyTexImage2D(width=%d, height=%d)", width, height);
20167117f1b4Smrg      }
20177117f1b4Smrg      return GL_TRUE;
20187117f1b4Smrg   }
20197117f1b4Smrg
20207117f1b4Smrg   if (is_compressed_format(ctx, internalFormat)) {
2021c1f859d4Smrg      if (!target_can_be_compressed(ctx, target)) {
20227117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM,
20237117f1b4Smrg                     "glCopyTexImage%d(target)", dimensions);
20247117f1b4Smrg         return GL_TRUE;
20257117f1b4Smrg      }
20267117f1b4Smrg      if (border != 0) {
20277117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
20287117f1b4Smrg                     "glCopyTexImage%D(border!=0)", dimensions);
20297117f1b4Smrg         return GL_TRUE;
20307117f1b4Smrg      }
20317117f1b4Smrg   }
20327117f1b4Smrg   else if (is_depth_format(internalFormat)) {
20337117f1b4Smrg      /* make sure we have depth/stencil buffers */
20347117f1b4Smrg      if (!ctx->ReadBuffer->_DepthBuffer) {
20357117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
20367117f1b4Smrg                     "glCopyTexImage%D(no depth)", dimensions);
20377117f1b4Smrg         return GL_TRUE;
20387117f1b4Smrg      }
20397117f1b4Smrg   }
20407117f1b4Smrg   else if (is_depthstencil_format(internalFormat)) {
20417117f1b4Smrg      /* make sure we have depth/stencil buffers */
20427117f1b4Smrg      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
20437117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
20447117f1b4Smrg                     "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
20457117f1b4Smrg         return GL_TRUE;
20467117f1b4Smrg      }
20477117f1b4Smrg   }
20487117f1b4Smrg
20497117f1b4Smrg   /* if we get here, the parameters are OK */
20507117f1b4Smrg   return GL_FALSE;
20517117f1b4Smrg}
20527117f1b4Smrg
20537117f1b4Smrg
20547117f1b4Smrg/**
20557117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors.
2056c1f859d4Smrg * Note that this is the first part of error checking.
2057c1f859d4Smrg * See also copytexsubimage_error_check2() below for the second part.
20587117f1b4Smrg *
20597117f1b4Smrg * \param ctx GL context.
20607117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3).
20617117f1b4Smrg * \param target texture target given by the user.
20627117f1b4Smrg * \param level image level given by the user.
20637117f1b4Smrg *
20647117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
20657117f1b4Smrg */
20667117f1b4Smrgstatic GLboolean
2067c1f859d4Smrgcopytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
2068c1f859d4Smrg                              GLenum target, GLint level)
20697117f1b4Smrg{
20707117f1b4Smrg   /* Check that the source buffer is complete */
20717117f1b4Smrg   if (ctx->ReadBuffer->Name) {
20727117f1b4Smrg      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
20737117f1b4Smrg      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
20747117f1b4Smrg         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
20757117f1b4Smrg                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
20767117f1b4Smrg         return GL_TRUE;
20777117f1b4Smrg      }
20787117f1b4Smrg   }
20797117f1b4Smrg
2080c1f859d4Smrg   /* Check target */
20817117f1b4Smrg   if (dimensions == 1) {
20827117f1b4Smrg      if (target != GL_TEXTURE_1D) {
20837117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
20847117f1b4Smrg         return GL_TRUE;
20857117f1b4Smrg      }
20867117f1b4Smrg   }
20877117f1b4Smrg   else if (dimensions == 2) {
20887117f1b4Smrg      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
20897117f1b4Smrg          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
20907117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map) {
20917117f1b4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
20927117f1b4Smrg            return GL_TRUE;
20937117f1b4Smrg         }
20947117f1b4Smrg      }
20957117f1b4Smrg      else if (target == GL_TEXTURE_RECTANGLE_NV) {
20967117f1b4Smrg         if (!ctx->Extensions.NV_texture_rectangle) {
20977117f1b4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
20987117f1b4Smrg            return GL_TRUE;
20997117f1b4Smrg         }
21007117f1b4Smrg      }
2101c1f859d4Smrg      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
2102c1f859d4Smrg         if (!ctx->Extensions.MESA_texture_array) {
2103c1f859d4Smrg            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2104c1f859d4Smrg            return GL_TRUE;
2105c1f859d4Smrg         }
2106c1f859d4Smrg      }
21077117f1b4Smrg      else if (target != GL_TEXTURE_2D) {
21087117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
21097117f1b4Smrg         return GL_TRUE;
21107117f1b4Smrg      }
21117117f1b4Smrg   }
21127117f1b4Smrg   else if (dimensions == 3) {
2113c1f859d4Smrg      if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
2114c1f859d4Smrg	   (!ctx->Extensions.MESA_texture_array))
2115c1f859d4Smrg	  && (target != GL_TEXTURE_3D)) {
2116c1f859d4Smrg	 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
2117c1f859d4Smrg	 return GL_TRUE;
21187117f1b4Smrg      }
21197117f1b4Smrg   }
21207117f1b4Smrg
21217117f1b4Smrg   /* Check level */
21227117f1b4Smrg   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
21237117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
21247117f1b4Smrg                  "glCopyTexSubImage%dD(level=%d)", dimensions, level);
21257117f1b4Smrg      return GL_TRUE;
21267117f1b4Smrg   }
21277117f1b4Smrg
21287117f1b4Smrg   return GL_FALSE;
21297117f1b4Smrg}
21307117f1b4Smrg
2131c1f859d4Smrg
2132c1f859d4Smrg/**
2133c1f859d4Smrg * Second part of error checking for glCopyTexSubImage[12]D().
2134c1f859d4Smrg * \param xoffset sub-image x offset given by the user.
2135c1f859d4Smrg * \param yoffset sub-image y offset given by the user.
2136c1f859d4Smrg * \param zoffset sub-image z offset given by the user.
2137c1f859d4Smrg * \param width image width given by the user.
2138c1f859d4Smrg * \param height image height given by the user.
2139c1f859d4Smrg */
21407117f1b4Smrgstatic GLboolean
21417117f1b4Smrgcopytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
21427117f1b4Smrg			      GLenum target, GLint level,
21437117f1b4Smrg			      GLint xoffset, GLint yoffset, GLint zoffset,
21447117f1b4Smrg			      GLsizei width, GLsizei height,
21457117f1b4Smrg			      const struct gl_texture_image *teximage )
21467117f1b4Smrg{
2147c1f859d4Smrg   /* check that dest tex image exists */
21487117f1b4Smrg   if (!teximage) {
21497117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
21507117f1b4Smrg                  "glCopyTexSubImage%dD(undefined texture level: %d)",
21517117f1b4Smrg                  dimensions, level);
21527117f1b4Smrg      return GL_TRUE;
21537117f1b4Smrg   }
21547117f1b4Smrg
2155c1f859d4Smrg   /* Check size */
2156c1f859d4Smrg   if (width < 0) {
2157c1f859d4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2158c1f859d4Smrg                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
2159c1f859d4Smrg      return GL_TRUE;
2160c1f859d4Smrg   }
2161c1f859d4Smrg   if (dimensions > 1 && height < 0) {
2162c1f859d4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2163c1f859d4Smrg                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
2164c1f859d4Smrg      return GL_TRUE;
2165c1f859d4Smrg   }
2166c1f859d4Smrg
2167c1f859d4Smrg   /* check x/y offsets */
21687117f1b4Smrg   if (xoffset < -((GLint)teximage->Border)) {
21697117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
21707117f1b4Smrg                  "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
21717117f1b4Smrg      return GL_TRUE;
21727117f1b4Smrg   }
21737117f1b4Smrg   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
21747117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
21757117f1b4Smrg                  "glCopyTexSubImage%dD(xoffset+width)", dimensions);
21767117f1b4Smrg      return GL_TRUE;
21777117f1b4Smrg   }
21787117f1b4Smrg   if (dimensions > 1) {
21797117f1b4Smrg      if (yoffset < -((GLint)teximage->Border)) {
21807117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
21817117f1b4Smrg                     "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
21827117f1b4Smrg         return GL_TRUE;
21837117f1b4Smrg      }
21847117f1b4Smrg      /* NOTE: we're adding the border here, not subtracting! */
21857117f1b4Smrg      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
21867117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
21877117f1b4Smrg                     "glCopyTexSubImage%dD(yoffset+height)", dimensions);
21887117f1b4Smrg         return GL_TRUE;
21897117f1b4Smrg      }
21907117f1b4Smrg   }
21917117f1b4Smrg
2192c1f859d4Smrg   /* check z offset */
21937117f1b4Smrg   if (dimensions > 2) {
21947117f1b4Smrg      if (zoffset < -((GLint)teximage->Border)) {
21957117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
21967117f1b4Smrg                     "glCopyTexSubImage%dD(zoffset)", dimensions);
21977117f1b4Smrg         return GL_TRUE;
21987117f1b4Smrg      }
21997117f1b4Smrg      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
22007117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
22017117f1b4Smrg                     "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
22027117f1b4Smrg         return GL_TRUE;
22037117f1b4Smrg      }
22047117f1b4Smrg   }
22057117f1b4Smrg
22067117f1b4Smrg   if (teximage->IsCompressed) {
2207c1f859d4Smrg      if (!target_can_be_compressed(ctx, target)) {
22087117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM,
22097117f1b4Smrg                     "glCopyTexSubImage%d(target)", dimensions);
22107117f1b4Smrg         return GL_TRUE;
22117117f1b4Smrg      }
22127117f1b4Smrg      /* offset must be multiple of 4 */
22137117f1b4Smrg      if ((xoffset & 3) || (yoffset & 3)) {
22147117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
22157117f1b4Smrg                     "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
22167117f1b4Smrg         return GL_TRUE;
22177117f1b4Smrg      }
22187117f1b4Smrg      /* size must be multiple of 4 */
22197117f1b4Smrg      if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
22207117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
22217117f1b4Smrg                     "glCopyTexSubImage%D(width)", dimensions);
22227117f1b4Smrg         return GL_TRUE;
22237117f1b4Smrg      }
22247117f1b4Smrg      if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
22257117f1b4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
22267117f1b4Smrg                     "glCopyTexSubImage%D(height)", dimensions);
22277117f1b4Smrg         return GL_TRUE;
22287117f1b4Smrg      }
22297117f1b4Smrg   }
22307117f1b4Smrg
22317117f1b4Smrg   if (teximage->InternalFormat == GL_YCBCR_MESA) {
22327117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
22337117f1b4Smrg      return GL_TRUE;
22347117f1b4Smrg   }
22357117f1b4Smrg
22367117f1b4Smrg   if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
22377117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2238c1f859d4Smrg                  "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
2239c1f859d4Smrg                  dimensions, teximage->_BaseFormat);
22407117f1b4Smrg      return GL_TRUE;
22417117f1b4Smrg   }
22427117f1b4Smrg
22437117f1b4Smrg   if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
22447117f1b4Smrg      if (!ctx->ReadBuffer->_DepthBuffer) {
22457117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
22467117f1b4Smrg                     "glCopyTexSubImage%D(no depth buffer)",
22477117f1b4Smrg                     dimensions);
22487117f1b4Smrg         return GL_TRUE;
22497117f1b4Smrg      }
22507117f1b4Smrg   }
22517117f1b4Smrg   else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
22527117f1b4Smrg      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
22537117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
22547117f1b4Smrg                     "glCopyTexSubImage%D(no depth/stencil buffer)",
22557117f1b4Smrg                     dimensions);
22567117f1b4Smrg         return GL_TRUE;
22577117f1b4Smrg      }
22587117f1b4Smrg   }
22597117f1b4Smrg
22607117f1b4Smrg   /* if we get here, the parameters are OK */
22617117f1b4Smrg   return GL_FALSE;
22627117f1b4Smrg}
22637117f1b4Smrg
22647117f1b4Smrg
22657117f1b4Smrg/**
22667117f1b4Smrg * Get texture image.  Called by glGetTexImage.
22677117f1b4Smrg *
22687117f1b4Smrg * \param target texture target.
22697117f1b4Smrg * \param level image level.
22707117f1b4Smrg * \param format pixel data format for returned image.
22717117f1b4Smrg * \param type pixel data type for returned image.
22727117f1b4Smrg * \param pixels returned pixel data.
22737117f1b4Smrg */
22747117f1b4Smrgvoid GLAPIENTRY
22757117f1b4Smrg_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
22767117f1b4Smrg                   GLenum type, GLvoid *pixels )
22777117f1b4Smrg{
22787117f1b4Smrg   const struct gl_texture_unit *texUnit;
22797117f1b4Smrg   struct gl_texture_object *texObj;
22807117f1b4Smrg   struct gl_texture_image *texImage;
22817117f1b4Smrg   GLint maxLevels = 0;
22827117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
22837117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
22847117f1b4Smrg
22857117f1b4Smrg   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
22867117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
22877117f1b4Smrg   if (!texObj || _mesa_is_proxy_texture(target)) {
22887117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
22897117f1b4Smrg      return;
22907117f1b4Smrg   }
22917117f1b4Smrg
22927117f1b4Smrg   maxLevels = _mesa_max_texture_levels(ctx, target);
22937117f1b4Smrg   ASSERT(maxLevels > 0);  /* 0 indicates bad target, caught above */
22947117f1b4Smrg
22957117f1b4Smrg   if (level < 0 || level >= maxLevels) {
22967117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
22977117f1b4Smrg      return;
22987117f1b4Smrg   }
22997117f1b4Smrg
23007117f1b4Smrg   if (_mesa_sizeof_packed_type(type) <= 0) {
23017117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
23027117f1b4Smrg      return;
23037117f1b4Smrg   }
23047117f1b4Smrg
23057117f1b4Smrg   if (_mesa_components_in_format(format) <= 0 ||
23067117f1b4Smrg       format == GL_STENCIL_INDEX) {
23077117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
23087117f1b4Smrg      return;
23097117f1b4Smrg   }
23107117f1b4Smrg
23117117f1b4Smrg   if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
23127117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
23137117f1b4Smrg      return;
23147117f1b4Smrg   }
23157117f1b4Smrg
2316c1f859d4Smrg   if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
23177117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
23187117f1b4Smrg      return;
23197117f1b4Smrg   }
23207117f1b4Smrg
23217117f1b4Smrg   if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
23227117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
23237117f1b4Smrg      return;
23247117f1b4Smrg   }
23257117f1b4Smrg
23267117f1b4Smrg   if (!ctx->Extensions.EXT_packed_depth_stencil
23277117f1b4Smrg       && is_depthstencil_format(format)) {
23287117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
23297117f1b4Smrg      return;
23307117f1b4Smrg   }
23317117f1b4Smrg
23327117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
23337117f1b4Smrg   {
23347117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
23357117f1b4Smrg      if (!texImage) {
23367117f1b4Smrg	 /* invalid mipmap level, not an error */
23377117f1b4Smrg	 goto out;
23387117f1b4Smrg      }
23397117f1b4Smrg
23407117f1b4Smrg
23417117f1b4Smrg      /* Make sure the requested image format is compatible with the
23427117f1b4Smrg       * texture's format.  Note that a color index texture can be converted
23437117f1b4Smrg       * to RGBA so that combo is allowed.
23447117f1b4Smrg       */
2345c1f859d4Smrg      if (_mesa_is_color_format(format)
2346c1f859d4Smrg	  && !_mesa_is_color_format(texImage->TexFormat->BaseFormat)
23477117f1b4Smrg	  && !is_index_format(texImage->TexFormat->BaseFormat)) {
23487117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
23497117f1b4Smrg	 goto out;
23507117f1b4Smrg      }
23517117f1b4Smrg      else if (is_index_format(format)
23527117f1b4Smrg	       && !is_index_format(texImage->TexFormat->BaseFormat)) {
23537117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
23547117f1b4Smrg	 goto out;
23557117f1b4Smrg      }
23567117f1b4Smrg      else if (is_depth_format(format)
23577117f1b4Smrg	       && !is_depth_format(texImage->TexFormat->BaseFormat)
23587117f1b4Smrg	       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
23597117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
23607117f1b4Smrg	 goto out;
23617117f1b4Smrg      }
23627117f1b4Smrg      else if (is_ycbcr_format(format)
23637117f1b4Smrg	       && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
23647117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
23657117f1b4Smrg	 goto out;
23667117f1b4Smrg      }
23677117f1b4Smrg      else if (is_depthstencil_format(format)
23687117f1b4Smrg	       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
23697117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
23707117f1b4Smrg	 goto out;
23717117f1b4Smrg      }
23727117f1b4Smrg
23737117f1b4Smrg      if (ctx->Pack.BufferObj->Name) {
23747117f1b4Smrg	 /* packing texture image into a PBO */
23757117f1b4Smrg	 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
23767117f1b4Smrg	 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
23777117f1b4Smrg					texImage->Height, texImage->Depth,
23787117f1b4Smrg					format, type, pixels)) {
23797117f1b4Smrg	    _mesa_error(ctx, GL_INVALID_OPERATION,
23807117f1b4Smrg			"glGetTexImage(invalid PBO access)");
23817117f1b4Smrg	    goto out;
23827117f1b4Smrg	 }
23837117f1b4Smrg      }
23847117f1b4Smrg
23857117f1b4Smrg      /* typically, this will call _mesa_get_teximage() */
23867117f1b4Smrg      ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
23877117f1b4Smrg			      texObj, texImage);
23887117f1b4Smrg
23897117f1b4Smrg   }
23907117f1b4Smrg out:
23917117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
23927117f1b4Smrg}
23937117f1b4Smrg
23947117f1b4Smrg
23957117f1b4Smrg
23967117f1b4Smrg/**
23977117f1b4Smrg * Check if the given texture image is bound to any framebuffer objects
23987117f1b4Smrg * and update/invalidate them.
23997117f1b4Smrg * XXX We're only checking the currently bound framebuffer object for now.
24007117f1b4Smrg * In the future, perhaps struct gl_texture_image should have a pointer (or
24017117f1b4Smrg * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
24027117f1b4Smrg */
24037117f1b4Smrgstatic void
24047117f1b4Smrgupdate_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
24057117f1b4Smrg                   GLuint face, GLuint level)
24067117f1b4Smrg{
24077117f1b4Smrg   if (ctx->DrawBuffer->Name) {
24087117f1b4Smrg      GLuint i;
24097117f1b4Smrg      for (i = 0; i < BUFFER_COUNT; i++) {
24107117f1b4Smrg         struct gl_renderbuffer_attachment *att =
24117117f1b4Smrg            ctx->DrawBuffer->Attachment + i;
24127117f1b4Smrg         if (att->Type == GL_TEXTURE &&
24137117f1b4Smrg             att->Texture == texObj &&
24147117f1b4Smrg             att->TextureLevel == level &&
24157117f1b4Smrg             att->CubeMapFace == face) {
24167117f1b4Smrg            ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
24177117f1b4Smrg            /* Tell driver about the new renderbuffer texture */
24187117f1b4Smrg            ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
24197117f1b4Smrg         }
24207117f1b4Smrg      }
24217117f1b4Smrg   }
24227117f1b4Smrg}
24237117f1b4Smrg
24247117f1b4Smrg
24257117f1b4Smrg
24267117f1b4Smrg/*
24277117f1b4Smrg * Called from the API.  Note that width includes the border.
24287117f1b4Smrg */
24297117f1b4Smrgvoid GLAPIENTRY
24307117f1b4Smrg_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
24317117f1b4Smrg                  GLsizei width, GLint border, GLenum format,
24327117f1b4Smrg                  GLenum type, const GLvoid *pixels )
24337117f1b4Smrg{
24347117f1b4Smrg   GLsizei postConvWidth = width;
24357117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
24367117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
24377117f1b4Smrg
2438c1f859d4Smrg#if FEATURE_convolve
2439c1f859d4Smrg   if (_mesa_is_color_format(internalFormat)) {
24407117f1b4Smrg      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
24417117f1b4Smrg   }
2442c1f859d4Smrg#endif
24437117f1b4Smrg
24447117f1b4Smrg   if (target == GL_TEXTURE_1D) {
24457117f1b4Smrg      /* non-proxy target */
24467117f1b4Smrg      struct gl_texture_unit *texUnit;
24477117f1b4Smrg      struct gl_texture_object *texObj;
24487117f1b4Smrg      struct gl_texture_image *texImage;
2449c1f859d4Smrg      const GLuint face = _mesa_tex_target_to_face(target);
24507117f1b4Smrg
24517117f1b4Smrg      if (texture_error_check(ctx, target, level, internalFormat,
24527117f1b4Smrg                              format, type, 1, postConvWidth, 1, 1, border)) {
24537117f1b4Smrg         return;   /* error was recorded */
24547117f1b4Smrg      }
24557117f1b4Smrg
24567117f1b4Smrg      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
24577117f1b4Smrg	 _mesa_update_state(ctx);
24587117f1b4Smrg
24597117f1b4Smrg      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
24607117f1b4Smrg      texObj = _mesa_select_tex_object(ctx, texUnit, target);
24617117f1b4Smrg      _mesa_lock_texture(ctx, texObj);
24627117f1b4Smrg      {
24637117f1b4Smrg	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
24647117f1b4Smrg	 if (!texImage) {
24657117f1b4Smrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
24667117f1b4Smrg	    goto out;
24677117f1b4Smrg	 }
24687117f1b4Smrg
24697117f1b4Smrg	 if (texImage->Data) {
24707117f1b4Smrg	    ctx->Driver.FreeTexImageData( ctx, texImage );
24717117f1b4Smrg	 }
24727117f1b4Smrg
24737117f1b4Smrg	 ASSERT(texImage->Data == NULL);
24747117f1b4Smrg
24757117f1b4Smrg	 clear_teximage_fields(texImage); /* not really needed, but helpful */
24767117f1b4Smrg	 _mesa_init_teximage_fields(ctx, target, texImage,
24777117f1b4Smrg				    postConvWidth, 1, 1,
24787117f1b4Smrg				    border, internalFormat);
24797117f1b4Smrg
24807117f1b4Smrg	 ASSERT(ctx->Driver.TexImage1D);
24817117f1b4Smrg
24827117f1b4Smrg	 /* Give the texture to the driver!  <pixels> may be null! */
24837117f1b4Smrg	 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
24847117f1b4Smrg				   width, border, format, type, pixels,
24857117f1b4Smrg				   &ctx->Unpack, texObj, texImage);
24867117f1b4Smrg
24877117f1b4Smrg	 ASSERT(texImage->TexFormat);
24887117f1b4Smrg
24897117f1b4Smrg	 update_fbo_texture(ctx, texObj, face, level);
24907117f1b4Smrg
24917117f1b4Smrg	 /* state update */
2492c1f859d4Smrg	 texObj->_Complete = GL_FALSE;
24937117f1b4Smrg	 ctx->NewState |= _NEW_TEXTURE;
24947117f1b4Smrg      }
24957117f1b4Smrg   out:
24967117f1b4Smrg      _mesa_unlock_texture(ctx, texObj);
24977117f1b4Smrg   }
24987117f1b4Smrg   else if (target == GL_PROXY_TEXTURE_1D) {
24997117f1b4Smrg      /* Proxy texture: check for errors and update proxy state */
25007117f1b4Smrg      struct gl_texture_image *texImage;
25017117f1b4Smrg      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
25027117f1b4Smrg      if (texture_error_check(ctx, target, level, internalFormat,
25037117f1b4Smrg                              format, type, 1, postConvWidth, 1, 1, border)) {
25047117f1b4Smrg         /* when error, clear all proxy texture image parameters */
25057117f1b4Smrg         if (texImage)
25067117f1b4Smrg            clear_teximage_fields(texImage);
25077117f1b4Smrg      }
25087117f1b4Smrg      else {
25097117f1b4Smrg         /* no error, set the tex image parameters */
25107117f1b4Smrg         ASSERT(texImage);
25117117f1b4Smrg         _mesa_init_teximage_fields(ctx, target, texImage,
25127117f1b4Smrg                                    postConvWidth, 1, 1,
25137117f1b4Smrg                                    border, internalFormat);
25147117f1b4Smrg         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
25157117f1b4Smrg                                          internalFormat, format, type);
25167117f1b4Smrg      }
25177117f1b4Smrg   }
25187117f1b4Smrg   else {
25197117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
25207117f1b4Smrg      return;
25217117f1b4Smrg   }
25227117f1b4Smrg}
25237117f1b4Smrg
25247117f1b4Smrg
25257117f1b4Smrgvoid GLAPIENTRY
25267117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
25277117f1b4Smrg                  GLsizei width, GLsizei height, GLint border,
25287117f1b4Smrg                  GLenum format, GLenum type,
25297117f1b4Smrg                  const GLvoid *pixels )
25307117f1b4Smrg{
25317117f1b4Smrg   GLsizei postConvWidth = width, postConvHeight = height;
25327117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
25337117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
25347117f1b4Smrg
2535c1f859d4Smrg#if FEATURE_convolve
2536c1f859d4Smrg   if (_mesa_is_color_format(internalFormat)) {
25377117f1b4Smrg      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
25387117f1b4Smrg					 &postConvHeight);
25397117f1b4Smrg   }
2540c1f859d4Smrg#endif
25417117f1b4Smrg
25427117f1b4Smrg   if (target == GL_TEXTURE_2D ||
25437117f1b4Smrg       (ctx->Extensions.ARB_texture_cube_map &&
25447117f1b4Smrg        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
25457117f1b4Smrg        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
25467117f1b4Smrg       (ctx->Extensions.NV_texture_rectangle &&
2547c1f859d4Smrg        target == GL_TEXTURE_RECTANGLE_NV) ||
2548c1f859d4Smrg       (ctx->Extensions.MESA_texture_array &&
2549c1f859d4Smrg        target == GL_TEXTURE_1D_ARRAY_EXT)) {
25507117f1b4Smrg      /* non-proxy target */
25517117f1b4Smrg      struct gl_texture_unit *texUnit;
25527117f1b4Smrg      struct gl_texture_object *texObj;
25537117f1b4Smrg      struct gl_texture_image *texImage;
2554c1f859d4Smrg      const GLuint face = _mesa_tex_target_to_face(target);
25557117f1b4Smrg
25567117f1b4Smrg      if (texture_error_check(ctx, target, level, internalFormat,
25577117f1b4Smrg                              format, type, 2, postConvWidth, postConvHeight,
25587117f1b4Smrg                              1, border)) {
25597117f1b4Smrg         return;   /* error was recorded */
25607117f1b4Smrg      }
25617117f1b4Smrg
25627117f1b4Smrg      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
25637117f1b4Smrg	 _mesa_update_state(ctx);
25647117f1b4Smrg
25657117f1b4Smrg      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
25667117f1b4Smrg      texObj = _mesa_select_tex_object(ctx, texUnit, target);
25677117f1b4Smrg      _mesa_lock_texture(ctx, texObj);
25687117f1b4Smrg      {
25697117f1b4Smrg	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
25707117f1b4Smrg	 if (!texImage) {
25717117f1b4Smrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
25727117f1b4Smrg	    goto out;
25737117f1b4Smrg	 }
25747117f1b4Smrg
25757117f1b4Smrg	 if (texImage->Data) {
25767117f1b4Smrg	    ctx->Driver.FreeTexImageData( ctx, texImage );
25777117f1b4Smrg	 }
25787117f1b4Smrg
25797117f1b4Smrg	 ASSERT(texImage->Data == NULL);
25807117f1b4Smrg	 clear_teximage_fields(texImage); /* not really needed, but helpful */
25817117f1b4Smrg	 _mesa_init_teximage_fields(ctx, target, texImage,
25827117f1b4Smrg				    postConvWidth, postConvHeight, 1,
25837117f1b4Smrg				    border, internalFormat);
25847117f1b4Smrg
25857117f1b4Smrg	 ASSERT(ctx->Driver.TexImage2D);
25867117f1b4Smrg
25877117f1b4Smrg	 /* Give the texture to the driver!  <pixels> may be null! */
25887117f1b4Smrg	 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
25897117f1b4Smrg				   width, height, border, format, type, pixels,
25907117f1b4Smrg				   &ctx->Unpack, texObj, texImage);
25917117f1b4Smrg
25927117f1b4Smrg	 ASSERT(texImage->TexFormat);
25937117f1b4Smrg
25947117f1b4Smrg	 update_fbo_texture(ctx, texObj, face, level);
25957117f1b4Smrg
25967117f1b4Smrg	 /* state update */
2597c1f859d4Smrg	 texObj->_Complete = GL_FALSE;
25987117f1b4Smrg	 ctx->NewState |= _NEW_TEXTURE;
25997117f1b4Smrg      }
26007117f1b4Smrg   out:
26017117f1b4Smrg      _mesa_unlock_texture(ctx, texObj);
26027117f1b4Smrg   }
26037117f1b4Smrg   else if (target == GL_PROXY_TEXTURE_2D ||
26047117f1b4Smrg            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
26057117f1b4Smrg             ctx->Extensions.ARB_texture_cube_map) ||
26067117f1b4Smrg            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2607c1f859d4Smrg             ctx->Extensions.NV_texture_rectangle) ||
2608c1f859d4Smrg            (ctx->Extensions.MESA_texture_array &&
2609c1f859d4Smrg             target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
26107117f1b4Smrg      /* Proxy texture: check for errors and update proxy state */
26117117f1b4Smrg      struct gl_texture_image *texImage;
26127117f1b4Smrg      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
26137117f1b4Smrg      if (texture_error_check(ctx, target, level, internalFormat,
26147117f1b4Smrg                              format, type, 2, postConvWidth, postConvHeight,
26157117f1b4Smrg                              1, border)) {
26167117f1b4Smrg         /* when error, clear all proxy texture image parameters */
26177117f1b4Smrg         if (texImage)
2618c1f859d4Smrg            clear_teximage_fields(texImage);
26197117f1b4Smrg      }
26207117f1b4Smrg      else {
26217117f1b4Smrg         /* no error, set the tex image parameters */
26227117f1b4Smrg         _mesa_init_teximage_fields(ctx, target, texImage,
26237117f1b4Smrg                                    postConvWidth, postConvHeight, 1,
26247117f1b4Smrg                                    border, internalFormat);
26257117f1b4Smrg         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
26267117f1b4Smrg                                          internalFormat, format, type);
26277117f1b4Smrg      }
26287117f1b4Smrg   }
26297117f1b4Smrg   else {
26307117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
26317117f1b4Smrg      return;
26327117f1b4Smrg   }
26337117f1b4Smrg}
26347117f1b4Smrg
26357117f1b4Smrg
26367117f1b4Smrg/*
26377117f1b4Smrg * Called by the API or display list executor.
26387117f1b4Smrg * Note that width and height include the border.
26397117f1b4Smrg */
26407117f1b4Smrgvoid GLAPIENTRY
26417117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
26427117f1b4Smrg                  GLsizei width, GLsizei height, GLsizei depth,
26437117f1b4Smrg                  GLint border, GLenum format, GLenum type,
26447117f1b4Smrg                  const GLvoid *pixels )
26457117f1b4Smrg{
26467117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
26477117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
26487117f1b4Smrg
2649c1f859d4Smrg   if (target == GL_TEXTURE_3D ||
2650c1f859d4Smrg       (ctx->Extensions.MESA_texture_array &&
2651c1f859d4Smrg        target == GL_TEXTURE_2D_ARRAY_EXT)) {
26527117f1b4Smrg      /* non-proxy target */
26537117f1b4Smrg      struct gl_texture_unit *texUnit;
26547117f1b4Smrg      struct gl_texture_object *texObj;
26557117f1b4Smrg      struct gl_texture_image *texImage;
2656c1f859d4Smrg      const GLuint face = _mesa_tex_target_to_face(target);
26577117f1b4Smrg
26587117f1b4Smrg      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
26597117f1b4Smrg                              format, type, 3, width, height, depth, border)) {
26607117f1b4Smrg         return;   /* error was recorded */
26617117f1b4Smrg      }
26627117f1b4Smrg
26637117f1b4Smrg      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
26647117f1b4Smrg	 _mesa_update_state(ctx);
26657117f1b4Smrg
26667117f1b4Smrg      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
26677117f1b4Smrg      texObj = _mesa_select_tex_object(ctx, texUnit, target);
26687117f1b4Smrg      _mesa_lock_texture(ctx, texObj);
26697117f1b4Smrg      {
26707117f1b4Smrg	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
26717117f1b4Smrg	 if (!texImage) {
26727117f1b4Smrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
26737117f1b4Smrg	    goto out;
26747117f1b4Smrg	 }
26757117f1b4Smrg
26767117f1b4Smrg	 if (texImage->Data) {
26777117f1b4Smrg	    ctx->Driver.FreeTexImageData( ctx, texImage );
26787117f1b4Smrg	 }
26797117f1b4Smrg
26807117f1b4Smrg	 ASSERT(texImage->Data == NULL);
26817117f1b4Smrg	 clear_teximage_fields(texImage); /* not really needed, but helpful */
26827117f1b4Smrg	 _mesa_init_teximage_fields(ctx, target, texImage,
26837117f1b4Smrg				    width, height, depth,
26847117f1b4Smrg				    border, internalFormat);
26857117f1b4Smrg
26867117f1b4Smrg	 ASSERT(ctx->Driver.TexImage3D);
26877117f1b4Smrg
26887117f1b4Smrg	 /* Give the texture to the driver!  <pixels> may be null! */
26897117f1b4Smrg	 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
26907117f1b4Smrg				   width, height, depth, border, format, type,
26917117f1b4Smrg				   pixels, &ctx->Unpack, texObj, texImage);
26927117f1b4Smrg
26937117f1b4Smrg	 ASSERT(texImage->TexFormat);
26947117f1b4Smrg
26957117f1b4Smrg	 update_fbo_texture(ctx, texObj, face, level);
26967117f1b4Smrg
26977117f1b4Smrg	 /* state update */
2698c1f859d4Smrg	 texObj->_Complete = GL_FALSE;
26997117f1b4Smrg	 ctx->NewState |= _NEW_TEXTURE;
27007117f1b4Smrg      }
27017117f1b4Smrg   out:
27027117f1b4Smrg      _mesa_unlock_texture(ctx, texObj);
27037117f1b4Smrg   }
2704c1f859d4Smrg   else if (target == GL_PROXY_TEXTURE_3D ||
2705c1f859d4Smrg       (ctx->Extensions.MESA_texture_array &&
2706c1f859d4Smrg        target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
27077117f1b4Smrg      /* Proxy texture: check for errors and update proxy state */
27087117f1b4Smrg      struct gl_texture_image *texImage;
27097117f1b4Smrg      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
27107117f1b4Smrg      if (texture_error_check(ctx, target, level, internalFormat,
27117117f1b4Smrg                              format, type, 3, width, height, depth, border)) {
27127117f1b4Smrg         /* when error, clear all proxy texture image parameters */
27137117f1b4Smrg         if (texImage)
27147117f1b4Smrg            clear_teximage_fields(texImage);
27157117f1b4Smrg      }
27167117f1b4Smrg      else {
27177117f1b4Smrg         /* no error, set the tex image parameters */
27187117f1b4Smrg         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
27197117f1b4Smrg                                    depth, border, internalFormat);
27207117f1b4Smrg         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
27217117f1b4Smrg                                          internalFormat, format, type);
27227117f1b4Smrg      }
27237117f1b4Smrg   }
27247117f1b4Smrg   else {
27257117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
27267117f1b4Smrg      return;
27277117f1b4Smrg   }
27287117f1b4Smrg}
27297117f1b4Smrg
27307117f1b4Smrg
27317117f1b4Smrgvoid GLAPIENTRY
27327117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
27337117f1b4Smrg                     GLsizei width, GLsizei height, GLsizei depth,
27347117f1b4Smrg                     GLint border, GLenum format, GLenum type,
27357117f1b4Smrg                     const GLvoid *pixels )
27367117f1b4Smrg{
27377117f1b4Smrg   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
27387117f1b4Smrg                    depth, border, format, type, pixels);
27397117f1b4Smrg}
27407117f1b4Smrg
27417117f1b4Smrg
27427117f1b4Smrg
27437117f1b4Smrgvoid GLAPIENTRY
27447117f1b4Smrg_mesa_TexSubImage1D( GLenum target, GLint level,
27457117f1b4Smrg                     GLint xoffset, GLsizei width,
27467117f1b4Smrg                     GLenum format, GLenum type,
27477117f1b4Smrg                     const GLvoid *pixels )
27487117f1b4Smrg{
27497117f1b4Smrg   GLsizei postConvWidth = width;
27507117f1b4Smrg   struct gl_texture_unit *texUnit;
27517117f1b4Smrg   struct gl_texture_object *texObj;
27527117f1b4Smrg   struct gl_texture_image *texImage = NULL;
27537117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
27547117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
27557117f1b4Smrg
27567117f1b4Smrg   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
27577117f1b4Smrg      _mesa_update_state(ctx);
27587117f1b4Smrg
2759c1f859d4Smrg#if FEATURE_convolve
27607117f1b4Smrg   /* XXX should test internal format */
2761c1f859d4Smrg   if (_mesa_is_color_format(format)) {
27627117f1b4Smrg      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
27637117f1b4Smrg   }
2764c1f859d4Smrg#endif
27657117f1b4Smrg
27667117f1b4Smrg   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
27677117f1b4Smrg			       postConvWidth, 1, 1, format, type)) {
27687117f1b4Smrg      return;   /* error was detected */
27697117f1b4Smrg   }
27707117f1b4Smrg
27717117f1b4Smrg
27727117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
27737117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
27747117f1b4Smrg   assert(texObj);
27757117f1b4Smrg
27767117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
27777117f1b4Smrg   {
27787117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
27797117f1b4Smrg
27807117f1b4Smrg      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
27817117f1b4Smrg				  postConvWidth, 1, 1, format, type, texImage)) {
27827117f1b4Smrg	 goto out;   /* error was detected */
27837117f1b4Smrg      }
27847117f1b4Smrg
27857117f1b4Smrg      if (width == 0)
27867117f1b4Smrg	 goto out;  /* no-op, not an error */
27877117f1b4Smrg
27887117f1b4Smrg      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
27897117f1b4Smrg      xoffset += texImage->Border;
27907117f1b4Smrg
27917117f1b4Smrg      ASSERT(ctx->Driver.TexSubImage1D);
27927117f1b4Smrg      (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
27937117f1b4Smrg				   format, type, pixels, &ctx->Unpack,
27947117f1b4Smrg				   texObj, texImage);
27957117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
27967117f1b4Smrg   }
27977117f1b4Smrg out:
27987117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
27997117f1b4Smrg}
28007117f1b4Smrg
28017117f1b4Smrg
28027117f1b4Smrgvoid GLAPIENTRY
28037117f1b4Smrg_mesa_TexSubImage2D( GLenum target, GLint level,
28047117f1b4Smrg                     GLint xoffset, GLint yoffset,
28057117f1b4Smrg                     GLsizei width, GLsizei height,
28067117f1b4Smrg                     GLenum format, GLenum type,
28077117f1b4Smrg                     const GLvoid *pixels )
28087117f1b4Smrg{
28097117f1b4Smrg   GLsizei postConvWidth = width, postConvHeight = height;
28107117f1b4Smrg   struct gl_texture_unit *texUnit;
28117117f1b4Smrg   struct gl_texture_object *texObj;
28127117f1b4Smrg   struct gl_texture_image *texImage;
28137117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
28147117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
28157117f1b4Smrg
28167117f1b4Smrg   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
28177117f1b4Smrg      _mesa_update_state(ctx);
28187117f1b4Smrg
2819c1f859d4Smrg#if FEATURE_convolve
28207117f1b4Smrg   /* XXX should test internal format */
2821c1f859d4Smrg   if (_mesa_is_color_format(format)) {
28227117f1b4Smrg      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
28237117f1b4Smrg                                         &postConvHeight);
28247117f1b4Smrg   }
2825c1f859d4Smrg#endif
28267117f1b4Smrg
28277117f1b4Smrg   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
28287117f1b4Smrg			      postConvWidth, postConvHeight, 1, format, type)) {
28297117f1b4Smrg      return;   /* error was detected */
28307117f1b4Smrg   }
28317117f1b4Smrg
28327117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
28337117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
28347117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
28357117f1b4Smrg   {
28367117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
28377117f1b4Smrg
28387117f1b4Smrg      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
28397117f1b4Smrg				  postConvWidth, postConvHeight, 1, format, type,
28407117f1b4Smrg				  texImage)) {
28417117f1b4Smrg	 goto out;   /* error was detected */
28427117f1b4Smrg      }
28437117f1b4Smrg
28447117f1b4Smrg      if (width == 0 || height == 0)
28457117f1b4Smrg	 goto out;  /* no-op, not an error */
28467117f1b4Smrg
28477117f1b4Smrg      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
28487117f1b4Smrg      xoffset += texImage->Border;
28497117f1b4Smrg      yoffset += texImage->Border;
28507117f1b4Smrg
28517117f1b4Smrg      ASSERT(ctx->Driver.TexSubImage2D);
28527117f1b4Smrg      (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
28537117f1b4Smrg				   width, height, format, type, pixels,
28547117f1b4Smrg				   &ctx->Unpack, texObj, texImage);
28557117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
28567117f1b4Smrg   }
28577117f1b4Smrg out:
28587117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
28597117f1b4Smrg}
28607117f1b4Smrg
28617117f1b4Smrg
28627117f1b4Smrg
28637117f1b4Smrgvoid GLAPIENTRY
28647117f1b4Smrg_mesa_TexSubImage3D( GLenum target, GLint level,
28657117f1b4Smrg                     GLint xoffset, GLint yoffset, GLint zoffset,
28667117f1b4Smrg                     GLsizei width, GLsizei height, GLsizei depth,
28677117f1b4Smrg                     GLenum format, GLenum type,
28687117f1b4Smrg                     const GLvoid *pixels )
28697117f1b4Smrg{
28707117f1b4Smrg   struct gl_texture_unit *texUnit;
28717117f1b4Smrg   struct gl_texture_object *texObj;
28727117f1b4Smrg   struct gl_texture_image *texImage;
28737117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
28747117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
28757117f1b4Smrg
28767117f1b4Smrg   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
28777117f1b4Smrg      _mesa_update_state(ctx);
28787117f1b4Smrg
28797117f1b4Smrg   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
28807117f1b4Smrg                              width, height, depth, format, type)) {
28817117f1b4Smrg      return;   /* error was detected */
28827117f1b4Smrg   }
28837117f1b4Smrg
28847117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
28857117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
28867117f1b4Smrg
28877117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
28887117f1b4Smrg   {
28897117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
28907117f1b4Smrg
28917117f1b4Smrg      if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
28927117f1b4Smrg				  width, height, depth, format, type, texImage)) {
28937117f1b4Smrg	 goto out;   /* error was detected */
28947117f1b4Smrg      }
28957117f1b4Smrg
28967117f1b4Smrg      if (width == 0 || height == 0 || height == 0)
28977117f1b4Smrg	 goto out;  /* no-op, not an error */
28987117f1b4Smrg
28997117f1b4Smrg      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
29007117f1b4Smrg      xoffset += texImage->Border;
29017117f1b4Smrg      yoffset += texImage->Border;
29027117f1b4Smrg      zoffset += texImage->Border;
29037117f1b4Smrg
29047117f1b4Smrg      ASSERT(ctx->Driver.TexSubImage3D);
29057117f1b4Smrg      (*ctx->Driver.TexSubImage3D)(ctx, target, level,
29067117f1b4Smrg				   xoffset, yoffset, zoffset,
29077117f1b4Smrg				   width, height, depth,
29087117f1b4Smrg				   format, type, pixels,
29097117f1b4Smrg				   &ctx->Unpack, texObj, texImage );
29107117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
29117117f1b4Smrg   }
29127117f1b4Smrg out:
29137117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
29147117f1b4Smrg}
29157117f1b4Smrg
29167117f1b4Smrg
29177117f1b4Smrg
29187117f1b4Smrgvoid GLAPIENTRY
29197117f1b4Smrg_mesa_CopyTexImage1D( GLenum target, GLint level,
29207117f1b4Smrg                      GLenum internalFormat,
29217117f1b4Smrg                      GLint x, GLint y,
29227117f1b4Smrg                      GLsizei width, GLint border )
29237117f1b4Smrg{
29247117f1b4Smrg   struct gl_texture_unit *texUnit;
29257117f1b4Smrg   struct gl_texture_object *texObj;
29267117f1b4Smrg   struct gl_texture_image *texImage;
29277117f1b4Smrg   GLsizei postConvWidth = width;
2928c1f859d4Smrg   const GLuint face = _mesa_tex_target_to_face(target);
29297117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
29307117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
29317117f1b4Smrg
2932c1f859d4Smrg   if (ctx->NewState & NEW_COPY_TEX_STATE)
29337117f1b4Smrg      _mesa_update_state(ctx);
29347117f1b4Smrg
2935c1f859d4Smrg#if FEATURE_convolve
2936c1f859d4Smrg   if (_mesa_is_color_format(internalFormat)) {
29377117f1b4Smrg      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
29387117f1b4Smrg   }
2939c1f859d4Smrg#endif
29407117f1b4Smrg
29417117f1b4Smrg   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
29427117f1b4Smrg                               postConvWidth, 1, border))
29437117f1b4Smrg      return;
29447117f1b4Smrg
29457117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
29467117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
29477117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
29487117f1b4Smrg   {
29497117f1b4Smrg      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
29507117f1b4Smrg      if (!texImage) {
29517117f1b4Smrg	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
29527117f1b4Smrg	 goto out;
29537117f1b4Smrg      }
29547117f1b4Smrg
29557117f1b4Smrg      if (texImage->Data) {
29567117f1b4Smrg	 ctx->Driver.FreeTexImageData( ctx, texImage );
29577117f1b4Smrg      }
29587117f1b4Smrg
29597117f1b4Smrg      ASSERT(texImage->Data == NULL);
29607117f1b4Smrg
29617117f1b4Smrg      clear_teximage_fields(texImage); /* not really needed, but helpful */
29627117f1b4Smrg      _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
29637117f1b4Smrg				 border, internalFormat);
29647117f1b4Smrg
29657117f1b4Smrg
29667117f1b4Smrg      ASSERT(ctx->Driver.CopyTexImage1D);
29677117f1b4Smrg      (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
29687117f1b4Smrg				    x, y, width, border);
29697117f1b4Smrg
29707117f1b4Smrg      ASSERT(texImage->TexFormat);
29717117f1b4Smrg
29727117f1b4Smrg      update_fbo_texture(ctx, texObj, face, level);
29737117f1b4Smrg
29747117f1b4Smrg      /* state update */
2975c1f859d4Smrg      texObj->_Complete = GL_FALSE;
29767117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
29777117f1b4Smrg   }
29787117f1b4Smrg out:
29797117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
29807117f1b4Smrg}
29817117f1b4Smrg
29827117f1b4Smrg
29837117f1b4Smrg
29847117f1b4Smrgvoid GLAPIENTRY
29857117f1b4Smrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
29867117f1b4Smrg                      GLint x, GLint y, GLsizei width, GLsizei height,
29877117f1b4Smrg                      GLint border )
29887117f1b4Smrg{
29897117f1b4Smrg   struct gl_texture_unit *texUnit;
29907117f1b4Smrg   struct gl_texture_object *texObj;
29917117f1b4Smrg   struct gl_texture_image *texImage;
29927117f1b4Smrg   GLsizei postConvWidth = width, postConvHeight = height;
2993c1f859d4Smrg   const GLuint face = _mesa_tex_target_to_face(target);
29947117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
29957117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
29967117f1b4Smrg
2997c1f859d4Smrg   if (ctx->NewState & NEW_COPY_TEX_STATE)
29987117f1b4Smrg      _mesa_update_state(ctx);
29997117f1b4Smrg
3000c1f859d4Smrg#if FEATURE_convolve
3001c1f859d4Smrg   if (_mesa_is_color_format(internalFormat)) {
30027117f1b4Smrg      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
30037117f1b4Smrg                                         &postConvHeight);
30047117f1b4Smrg   }
3005c1f859d4Smrg#endif
30067117f1b4Smrg
30077117f1b4Smrg   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
30087117f1b4Smrg                               postConvWidth, postConvHeight, border))
30097117f1b4Smrg      return;
30107117f1b4Smrg
30117117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
30127117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
30137117f1b4Smrg
30147117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
30157117f1b4Smrg   {
30167117f1b4Smrg      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
30177117f1b4Smrg
30187117f1b4Smrg      if (!texImage) {
30197117f1b4Smrg	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
30207117f1b4Smrg	 goto out;
30217117f1b4Smrg      }
30227117f1b4Smrg
30237117f1b4Smrg      if (texImage->Data) {
30247117f1b4Smrg	 ctx->Driver.FreeTexImageData( ctx, texImage );
30257117f1b4Smrg      }
30267117f1b4Smrg
30277117f1b4Smrg      ASSERT(texImage->Data == NULL);
30287117f1b4Smrg
30297117f1b4Smrg      clear_teximage_fields(texImage); /* not really needed, but helpful */
30307117f1b4Smrg      _mesa_init_teximage_fields(ctx, target, texImage,
30317117f1b4Smrg				 postConvWidth, postConvHeight, 1,
30327117f1b4Smrg				 border, internalFormat);
30337117f1b4Smrg
30347117f1b4Smrg      ASSERT(ctx->Driver.CopyTexImage2D);
30357117f1b4Smrg      (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
30367117f1b4Smrg				    x, y, width, height, border);
30377117f1b4Smrg
30387117f1b4Smrg      ASSERT(texImage->TexFormat);
30397117f1b4Smrg
30407117f1b4Smrg      update_fbo_texture(ctx, texObj, face, level);
30417117f1b4Smrg
30427117f1b4Smrg      /* state update */
3043c1f859d4Smrg      texObj->_Complete = GL_FALSE;
30447117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
30457117f1b4Smrg   }
30467117f1b4Smrg out:
30477117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
30487117f1b4Smrg}
30497117f1b4Smrg
30507117f1b4Smrg
30517117f1b4Smrgvoid GLAPIENTRY
30527117f1b4Smrg_mesa_CopyTexSubImage1D( GLenum target, GLint level,
30537117f1b4Smrg                         GLint xoffset, GLint x, GLint y, GLsizei width )
30547117f1b4Smrg{
30557117f1b4Smrg   struct gl_texture_unit *texUnit;
30567117f1b4Smrg   struct gl_texture_object *texObj;
30577117f1b4Smrg   struct gl_texture_image *texImage;
30587117f1b4Smrg   GLsizei postConvWidth = width;
3059c1f859d4Smrg   GLint yoffset = 0;
3060c1f859d4Smrg   GLsizei height = 1;
3061c1f859d4Smrg
30627117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
30637117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
30647117f1b4Smrg
3065c1f859d4Smrg   if (ctx->NewState & NEW_COPY_TEX_STATE)
30667117f1b4Smrg      _mesa_update_state(ctx);
30677117f1b4Smrg
3068c1f859d4Smrg   if (copytexsubimage_error_check1(ctx, 1, target, level))
30697117f1b4Smrg      return;
30707117f1b4Smrg
30717117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
30727117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
30737117f1b4Smrg
30747117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
30757117f1b4Smrg   {
30767117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
30777117f1b4Smrg
3078c1f859d4Smrg#if FEATURE_convolve
3079c1f859d4Smrg      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3080c1f859d4Smrg         _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
3081c1f859d4Smrg      }
3082c1f859d4Smrg#endif
3083c1f859d4Smrg
30847117f1b4Smrg      if (copytexsubimage_error_check2(ctx, 1, target, level,
30857117f1b4Smrg				       xoffset, 0, 0, postConvWidth, 1,
30867117f1b4Smrg				       texImage))
30877117f1b4Smrg	 goto out;
30887117f1b4Smrg
30897117f1b4Smrg
30907117f1b4Smrg      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
30917117f1b4Smrg      xoffset += texImage->Border;
30927117f1b4Smrg
3093c1f859d4Smrg      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3094c1f859d4Smrg                                     &width, &height)) {
3095c1f859d4Smrg         ASSERT(ctx->Driver.CopyTexSubImage1D);
3096c1f859d4Smrg         ctx->Driver.CopyTexSubImage1D(ctx, target, level,
3097c1f859d4Smrg                                       xoffset, x, y, width);
3098c1f859d4Smrg      }
3099c1f859d4Smrg
31007117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
31017117f1b4Smrg   }
31027117f1b4Smrg out:
31037117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
31047117f1b4Smrg}
31057117f1b4Smrg
31067117f1b4Smrg
31077117f1b4Smrg
31087117f1b4Smrgvoid GLAPIENTRY
31097117f1b4Smrg_mesa_CopyTexSubImage2D( GLenum target, GLint level,
31107117f1b4Smrg                         GLint xoffset, GLint yoffset,
31117117f1b4Smrg                         GLint x, GLint y, GLsizei width, GLsizei height )
31127117f1b4Smrg{
31137117f1b4Smrg   struct gl_texture_unit *texUnit;
31147117f1b4Smrg   struct gl_texture_object *texObj;
31157117f1b4Smrg   struct gl_texture_image *texImage;
31167117f1b4Smrg   GLsizei postConvWidth = width, postConvHeight = height;
31177117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
31187117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
31197117f1b4Smrg
3120c1f859d4Smrg   if (ctx->NewState & NEW_COPY_TEX_STATE)
31217117f1b4Smrg      _mesa_update_state(ctx);
31227117f1b4Smrg
3123c1f859d4Smrg   if (copytexsubimage_error_check1(ctx, 2, target, level))
31247117f1b4Smrg      return;
31257117f1b4Smrg
31267117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
31277117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
31287117f1b4Smrg
31297117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
31307117f1b4Smrg   {
31317117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
31327117f1b4Smrg
3133c1f859d4Smrg#if FEATURE_convolve
3134c1f859d4Smrg      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3135c1f859d4Smrg         _mesa_adjust_image_for_convolution(ctx, 2,
3136c1f859d4Smrg                                            &postConvWidth, &postConvHeight);
3137c1f859d4Smrg      }
3138c1f859d4Smrg#endif
3139c1f859d4Smrg
31407117f1b4Smrg      if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
31417117f1b4Smrg				       postConvWidth, postConvHeight, texImage))
31427117f1b4Smrg	 goto out;
31437117f1b4Smrg
31447117f1b4Smrg      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
31457117f1b4Smrg      xoffset += texImage->Border;
31467117f1b4Smrg      yoffset += texImage->Border;
3147c1f859d4Smrg
3148c1f859d4Smrg      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3149c1f859d4Smrg                                     &width, &height)) {
3150c1f859d4Smrg         ASSERT(ctx->Driver.CopyTexSubImage2D);
3151c1f859d4Smrg         ctx->Driver.CopyTexSubImage2D(ctx, target, level,
31527117f1b4Smrg				       xoffset, yoffset, x, y, width, height);
3153c1f859d4Smrg      }
3154c1f859d4Smrg
31557117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
31567117f1b4Smrg   }
31577117f1b4Smrg out:
31587117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
31597117f1b4Smrg}
31607117f1b4Smrg
31617117f1b4Smrg
31627117f1b4Smrg
31637117f1b4Smrgvoid GLAPIENTRY
31647117f1b4Smrg_mesa_CopyTexSubImage3D( GLenum target, GLint level,
31657117f1b4Smrg                         GLint xoffset, GLint yoffset, GLint zoffset,
31667117f1b4Smrg                         GLint x, GLint y, GLsizei width, GLsizei height )
31677117f1b4Smrg{
31687117f1b4Smrg   struct gl_texture_unit *texUnit;
31697117f1b4Smrg   struct gl_texture_object *texObj;
31707117f1b4Smrg   struct gl_texture_image *texImage;
31717117f1b4Smrg   GLsizei postConvWidth = width, postConvHeight = height;
31727117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
31737117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
31747117f1b4Smrg
3175c1f859d4Smrg   if (ctx->NewState & NEW_COPY_TEX_STATE)
31767117f1b4Smrg      _mesa_update_state(ctx);
31777117f1b4Smrg
3178c1f859d4Smrg   if (copytexsubimage_error_check1(ctx, 3, target, level))
31797117f1b4Smrg      return;
31807117f1b4Smrg
31817117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
31827117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
31837117f1b4Smrg
31847117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
31857117f1b4Smrg   {
31867117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
31877117f1b4Smrg
3188c1f859d4Smrg#if FEATURE_convolve
3189c1f859d4Smrg      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3190c1f859d4Smrg         _mesa_adjust_image_for_convolution(ctx, 2,
3191c1f859d4Smrg                                            &postConvWidth, &postConvHeight);
3192c1f859d4Smrg      }
3193c1f859d4Smrg#endif
3194c1f859d4Smrg
31957117f1b4Smrg      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
31967117f1b4Smrg				       zoffset, postConvWidth, postConvHeight,
31977117f1b4Smrg				       texImage))
31987117f1b4Smrg	 goto out;
31997117f1b4Smrg
32007117f1b4Smrg      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
32017117f1b4Smrg      xoffset += texImage->Border;
32027117f1b4Smrg      yoffset += texImage->Border;
32037117f1b4Smrg      zoffset += texImage->Border;
32047117f1b4Smrg
3205c1f859d4Smrg      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3206c1f859d4Smrg                                     &width, &height)) {
3207c1f859d4Smrg         ASSERT(ctx->Driver.CopyTexSubImage3D);
3208c1f859d4Smrg         ctx->Driver.CopyTexSubImage3D(ctx, target, level,
32097117f1b4Smrg				       xoffset, yoffset, zoffset,
32107117f1b4Smrg				       x, y, width, height);
3211c1f859d4Smrg      }
3212c1f859d4Smrg
32137117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
32147117f1b4Smrg   }
32157117f1b4Smrg out:
32167117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
32177117f1b4Smrg}
32187117f1b4Smrg
32197117f1b4Smrg
32207117f1b4Smrg
32217117f1b4Smrg
32227117f1b4Smrg/**********************************************************************/
32237117f1b4Smrg/******                   Compressed Textures                    ******/
32247117f1b4Smrg/**********************************************************************/
32257117f1b4Smrg
32267117f1b4Smrg
32277117f1b4Smrg/**
32287117f1b4Smrg * Error checking for glCompressedTexImage[123]D().
32297117f1b4Smrg * \return error code or GL_NO_ERROR.
32307117f1b4Smrg */
32317117f1b4Smrgstatic GLenum
32327117f1b4Smrgcompressed_texture_error_check(GLcontext *ctx, GLint dimensions,
32337117f1b4Smrg                               GLenum target, GLint level,
32347117f1b4Smrg                               GLenum internalFormat, GLsizei width,
32357117f1b4Smrg                               GLsizei height, GLsizei depth, GLint border,
32367117f1b4Smrg                               GLsizei imageSize)
32377117f1b4Smrg{
32387117f1b4Smrg   GLint expectedSize, maxLevels = 0, maxTextureSize;
32397117f1b4Smrg
32407117f1b4Smrg   if (dimensions == 1) {
32417117f1b4Smrg      /* 1D compressed textures not allowed */
32427117f1b4Smrg      return GL_INVALID_ENUM;
32437117f1b4Smrg   }
32447117f1b4Smrg   else if (dimensions == 2) {
32457117f1b4Smrg      if (target == GL_PROXY_TEXTURE_2D) {
32467117f1b4Smrg         maxLevels = ctx->Const.MaxTextureLevels;
32477117f1b4Smrg      }
32487117f1b4Smrg      else if (target == GL_TEXTURE_2D) {
32497117f1b4Smrg         maxLevels = ctx->Const.MaxTextureLevels;
32507117f1b4Smrg      }
32517117f1b4Smrg      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
32527117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map)
32537117f1b4Smrg            return GL_INVALID_ENUM; /*target*/
32547117f1b4Smrg         maxLevels = ctx->Const.MaxCubeTextureLevels;
32557117f1b4Smrg      }
32567117f1b4Smrg      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
32577117f1b4Smrg               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
32587117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map)
32597117f1b4Smrg            return GL_INVALID_ENUM; /*target*/
32607117f1b4Smrg         maxLevels = ctx->Const.MaxCubeTextureLevels;
32617117f1b4Smrg      }
32627117f1b4Smrg      else {
32637117f1b4Smrg         return GL_INVALID_ENUM; /*target*/
32647117f1b4Smrg      }
32657117f1b4Smrg   }
32667117f1b4Smrg   else if (dimensions == 3) {
32677117f1b4Smrg      /* 3D compressed textures not allowed */
32687117f1b4Smrg      return GL_INVALID_ENUM;
32697117f1b4Smrg   }
32707117f1b4Smrg
32717117f1b4Smrg   maxTextureSize = 1 << (maxLevels - 1);
32727117f1b4Smrg
32737117f1b4Smrg   /* This will detect any invalid internalFormat value */
32747117f1b4Smrg   if (!is_compressed_format(ctx, internalFormat))
32757117f1b4Smrg      return GL_INVALID_ENUM;
32767117f1b4Smrg
32777117f1b4Smrg   /* This should really never fail */
32787117f1b4Smrg   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
32797117f1b4Smrg      return GL_INVALID_ENUM;
32807117f1b4Smrg
32817117f1b4Smrg   if (border != 0)
32827117f1b4Smrg      return GL_INVALID_VALUE;
32837117f1b4Smrg
32847117f1b4Smrg   /*
32857117f1b4Smrg    * XXX We should probably use the proxy texture error check function here.
32867117f1b4Smrg    */
32877117f1b4Smrg   if (width < 1 || width > maxTextureSize ||
3288c1f859d4Smrg       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
32897117f1b4Smrg      return GL_INVALID_VALUE;
32907117f1b4Smrg
32917117f1b4Smrg   if ((height < 1 || height > maxTextureSize ||
3292c1f859d4Smrg       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
32937117f1b4Smrg       && dimensions > 1)
32947117f1b4Smrg      return GL_INVALID_VALUE;
32957117f1b4Smrg
32967117f1b4Smrg   if ((depth < 1 || depth > maxTextureSize ||
3297c1f859d4Smrg       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
32987117f1b4Smrg       && dimensions > 2)
32997117f1b4Smrg      return GL_INVALID_VALUE;
33007117f1b4Smrg
33017117f1b4Smrg   /* For cube map, width must equal height */
33027117f1b4Smrg   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
33037117f1b4Smrg       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
33047117f1b4Smrg      return GL_INVALID_VALUE;
33057117f1b4Smrg
33067117f1b4Smrg   if (level < 0 || level >= maxLevels)
33077117f1b4Smrg      return GL_INVALID_VALUE;
33087117f1b4Smrg
33097117f1b4Smrg   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
33107117f1b4Smrg                                                       depth, internalFormat);
33117117f1b4Smrg   if (expectedSize != imageSize)
33127117f1b4Smrg      return GL_INVALID_VALUE;
33137117f1b4Smrg
33147117f1b4Smrg#if FEATURE_EXT_texture_sRGB
33157117f1b4Smrg   if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
33167117f1b4Smrg        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
33177117f1b4Smrg        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
33187117f1b4Smrg        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
33197117f1b4Smrg       && border != 0) {
33207117f1b4Smrg      return GL_INVALID_OPERATION;
33217117f1b4Smrg   }
33227117f1b4Smrg#endif
33237117f1b4Smrg
33247117f1b4Smrg   return GL_NO_ERROR;
33257117f1b4Smrg}
33267117f1b4Smrg
33277117f1b4Smrg
33287117f1b4Smrg/**
33297117f1b4Smrg * Error checking for glCompressedTexSubImage[123]D().
33307117f1b4Smrg * \warning  There are some bad assumptions here about the size of compressed
33317117f1b4Smrg *           texture tiles (multiple of 4) used to test the validity of the
33327117f1b4Smrg *           offset and size parameters.
33337117f1b4Smrg * \return error code or GL_NO_ERROR.
33347117f1b4Smrg */
33357117f1b4Smrgstatic GLenum
33367117f1b4Smrgcompressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
33377117f1b4Smrg                                  GLenum target, GLint level,
33387117f1b4Smrg                                  GLint xoffset, GLint yoffset, GLint zoffset,
33397117f1b4Smrg                                  GLsizei width, GLsizei height, GLsizei depth,
33407117f1b4Smrg                                  GLenum format, GLsizei imageSize)
33417117f1b4Smrg{
33427117f1b4Smrg   GLint expectedSize, maxLevels = 0, maxTextureSize;
33437117f1b4Smrg   (void) zoffset;
33447117f1b4Smrg
33457117f1b4Smrg   if (dimensions == 1) {
33467117f1b4Smrg      /* 1D compressed textures not allowed */
33477117f1b4Smrg      return GL_INVALID_ENUM;
33487117f1b4Smrg   }
33497117f1b4Smrg   else if (dimensions == 2) {
33507117f1b4Smrg      if (target == GL_PROXY_TEXTURE_2D) {
33517117f1b4Smrg         maxLevels = ctx->Const.MaxTextureLevels;
33527117f1b4Smrg      }
33537117f1b4Smrg      else if (target == GL_TEXTURE_2D) {
33547117f1b4Smrg         maxLevels = ctx->Const.MaxTextureLevels;
33557117f1b4Smrg      }
33567117f1b4Smrg      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
33577117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map)
33587117f1b4Smrg            return GL_INVALID_ENUM; /*target*/
33597117f1b4Smrg         maxLevels = ctx->Const.MaxCubeTextureLevels;
33607117f1b4Smrg      }
33617117f1b4Smrg      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
33627117f1b4Smrg               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
33637117f1b4Smrg         if (!ctx->Extensions.ARB_texture_cube_map)
33647117f1b4Smrg            return GL_INVALID_ENUM; /*target*/
33657117f1b4Smrg         maxLevels = ctx->Const.MaxCubeTextureLevels;
33667117f1b4Smrg      }
33677117f1b4Smrg      else {
33687117f1b4Smrg         return GL_INVALID_ENUM; /*target*/
33697117f1b4Smrg      }
33707117f1b4Smrg   }
33717117f1b4Smrg   else if (dimensions == 3) {
33727117f1b4Smrg      /* 3D compressed textures not allowed */
33737117f1b4Smrg      return GL_INVALID_ENUM;
33747117f1b4Smrg   }
33757117f1b4Smrg
33767117f1b4Smrg   maxTextureSize = 1 << (maxLevels - 1);
33777117f1b4Smrg
33787117f1b4Smrg   /* this will catch any invalid compressed format token */
33797117f1b4Smrg   if (!is_compressed_format(ctx, format))
33807117f1b4Smrg      return GL_INVALID_ENUM;
33817117f1b4Smrg
33827117f1b4Smrg   if (width < 1 || width > maxTextureSize)
33837117f1b4Smrg      return GL_INVALID_VALUE;
33847117f1b4Smrg
33857117f1b4Smrg   if ((height < 1 || height > maxTextureSize)
33867117f1b4Smrg       && dimensions > 1)
33877117f1b4Smrg      return GL_INVALID_VALUE;
33887117f1b4Smrg
33897117f1b4Smrg   if (level < 0 || level >= maxLevels)
33907117f1b4Smrg      return GL_INVALID_VALUE;
33917117f1b4Smrg
33927117f1b4Smrg   /* XXX these tests are specific to the compressed format.
33937117f1b4Smrg    * this code should be generalized in some way.
33947117f1b4Smrg    */
33957117f1b4Smrg   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
33967117f1b4Smrg      return GL_INVALID_VALUE;
33977117f1b4Smrg
33987117f1b4Smrg   if ((width & 3) != 0 && width != 2 && width != 1)
33997117f1b4Smrg      return GL_INVALID_VALUE;
34007117f1b4Smrg
34017117f1b4Smrg   if ((height & 3) != 0 && height != 2 && height != 1)
34027117f1b4Smrg      return GL_INVALID_VALUE;
34037117f1b4Smrg
34047117f1b4Smrg   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
34057117f1b4Smrg                                                       depth, format);
34067117f1b4Smrg   if (expectedSize != imageSize)
34077117f1b4Smrg      return GL_INVALID_VALUE;
34087117f1b4Smrg
34097117f1b4Smrg   return GL_NO_ERROR;
34107117f1b4Smrg}
34117117f1b4Smrg
34127117f1b4Smrg
34137117f1b4Smrg
34147117f1b4Smrgvoid GLAPIENTRY
34157117f1b4Smrg_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
34167117f1b4Smrg                              GLenum internalFormat, GLsizei width,
34177117f1b4Smrg                              GLint border, GLsizei imageSize,
34187117f1b4Smrg                              const GLvoid *data)
34197117f1b4Smrg{
34207117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
34217117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
34227117f1b4Smrg
34237117f1b4Smrg   if (target == GL_TEXTURE_1D) {
34247117f1b4Smrg      /* non-proxy target */
34257117f1b4Smrg      struct gl_texture_unit *texUnit;
34267117f1b4Smrg      struct gl_texture_object *texObj;
34277117f1b4Smrg      struct gl_texture_image *texImage;
34287117f1b4Smrg      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
34297117f1b4Smrg                               internalFormat, width, 1, 1, border, imageSize);
34307117f1b4Smrg      if (error) {
34317117f1b4Smrg         _mesa_error(ctx, error, "glCompressedTexImage1D");
34327117f1b4Smrg         return;
34337117f1b4Smrg      }
34347117f1b4Smrg
34357117f1b4Smrg      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
34367117f1b4Smrg      texObj = _mesa_select_tex_object(ctx, texUnit, target);
34377117f1b4Smrg
34387117f1b4Smrg      _mesa_lock_texture(ctx, texObj);
34397117f1b4Smrg      {
34407117f1b4Smrg	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
34417117f1b4Smrg	 if (!texImage) {
34427117f1b4Smrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
34437117f1b4Smrg	    goto out;
34447117f1b4Smrg	 }
34457117f1b4Smrg
34467117f1b4Smrg	 if (texImage->Data) {
34477117f1b4Smrg	    ctx->Driver.FreeTexImageData( ctx, texImage );
34487117f1b4Smrg	 }
34497117f1b4Smrg	 ASSERT(texImage->Data == NULL);
34507117f1b4Smrg
34517117f1b4Smrg	 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
34527117f1b4Smrg				    border, internalFormat);
34537117f1b4Smrg
34547117f1b4Smrg	 ASSERT(ctx->Driver.CompressedTexImage1D);
34557117f1b4Smrg	 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
34567117f1b4Smrg					     internalFormat, width, border,
34577117f1b4Smrg					     imageSize, data,
34587117f1b4Smrg					     texObj, texImage);
34597117f1b4Smrg
34607117f1b4Smrg	 /* state update */
3461c1f859d4Smrg	 texObj->_Complete = GL_FALSE;
34627117f1b4Smrg	 ctx->NewState |= _NEW_TEXTURE;
34637117f1b4Smrg      }
34647117f1b4Smrg   out:
34657117f1b4Smrg      _mesa_unlock_texture(ctx, texObj);
34667117f1b4Smrg   }
34677117f1b4Smrg   else if (target == GL_PROXY_TEXTURE_1D) {
34687117f1b4Smrg      /* Proxy texture: check for errors and update proxy state */
34697117f1b4Smrg      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
34707117f1b4Smrg                               internalFormat, width, 1, 1, border, imageSize);
34717117f1b4Smrg      if (!error) {
34727117f1b4Smrg         ASSERT(ctx->Driver.TestProxyTexImage);
34737117f1b4Smrg         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
34747117f1b4Smrg                                             internalFormat, GL_NONE, GL_NONE,
34757117f1b4Smrg                                             width, 1, 1, border);
34767117f1b4Smrg      }
34777117f1b4Smrg      if (error) {
34787117f1b4Smrg         /* if error, clear all proxy texture image parameters */
34797117f1b4Smrg         struct gl_texture_image *texImage;
34807117f1b4Smrg         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
34817117f1b4Smrg         if (texImage)
34827117f1b4Smrg            clear_teximage_fields(texImage);
34837117f1b4Smrg      }
34847117f1b4Smrg      else {
34857117f1b4Smrg         /* store the teximage parameters */
34867117f1b4Smrg         struct gl_texture_unit *texUnit;
34877117f1b4Smrg         struct gl_texture_object *texObj;
34887117f1b4Smrg         struct gl_texture_image *texImage;
34897117f1b4Smrg         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
34907117f1b4Smrg	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
34917117f1b4Smrg
34927117f1b4Smrg	 _mesa_lock_texture(ctx, texObj);
34937117f1b4Smrg	 {
34947117f1b4Smrg	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
34957117f1b4Smrg	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
34967117f1b4Smrg				       border, internalFormat);
34977117f1b4Smrg	 }
34987117f1b4Smrg	 _mesa_unlock_texture(ctx, texObj);
34997117f1b4Smrg      }
35007117f1b4Smrg   }
35017117f1b4Smrg   else {
35027117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
35037117f1b4Smrg      return;
35047117f1b4Smrg   }
35057117f1b4Smrg}
35067117f1b4Smrg
35077117f1b4Smrg
35087117f1b4Smrgvoid GLAPIENTRY
35097117f1b4Smrg_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
35107117f1b4Smrg                              GLenum internalFormat, GLsizei width,
35117117f1b4Smrg                              GLsizei height, GLint border, GLsizei imageSize,
35127117f1b4Smrg                              const GLvoid *data)
35137117f1b4Smrg{
35147117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
35157117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
35167117f1b4Smrg
35177117f1b4Smrg   if (target == GL_TEXTURE_2D ||
35187117f1b4Smrg       (ctx->Extensions.ARB_texture_cube_map &&
35197117f1b4Smrg        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
35207117f1b4Smrg        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
35217117f1b4Smrg      /* non-proxy target */
35227117f1b4Smrg      struct gl_texture_unit *texUnit;
35237117f1b4Smrg      struct gl_texture_object *texObj;
35247117f1b4Smrg      struct gl_texture_image *texImage;
35257117f1b4Smrg      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
35267117f1b4Smrg                          internalFormat, width, height, 1, border, imageSize);
35277117f1b4Smrg      if (error) {
35287117f1b4Smrg         _mesa_error(ctx, error, "glCompressedTexImage2D");
35297117f1b4Smrg         return;
35307117f1b4Smrg      }
35317117f1b4Smrg
35327117f1b4Smrg      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
35337117f1b4Smrg      texObj = _mesa_select_tex_object(ctx, texUnit, target);
35347117f1b4Smrg
35357117f1b4Smrg      _mesa_lock_texture(ctx, texObj);
35367117f1b4Smrg      {
35377117f1b4Smrg	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
35387117f1b4Smrg	 if (!texImage) {
35397117f1b4Smrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
35407117f1b4Smrg	    goto out;
35417117f1b4Smrg	 }
35427117f1b4Smrg
35437117f1b4Smrg	 if (texImage->Data) {
35447117f1b4Smrg	    ctx->Driver.FreeTexImageData( ctx, texImage );
35457117f1b4Smrg	 }
35467117f1b4Smrg	 ASSERT(texImage->Data == NULL);
35477117f1b4Smrg
35487117f1b4Smrg	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
35497117f1b4Smrg				    border, internalFormat);
35507117f1b4Smrg
35517117f1b4Smrg	 ASSERT(ctx->Driver.CompressedTexImage2D);
35527117f1b4Smrg	 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
35537117f1b4Smrg					     internalFormat, width, height,
35547117f1b4Smrg					     border, imageSize, data,
35557117f1b4Smrg					     texObj, texImage);
35567117f1b4Smrg
35577117f1b4Smrg	 /* state update */
3558c1f859d4Smrg	 texObj->_Complete = GL_FALSE;
35597117f1b4Smrg	 ctx->NewState |= _NEW_TEXTURE;
35607117f1b4Smrg      }
35617117f1b4Smrg   out:
35627117f1b4Smrg      _mesa_unlock_texture(ctx, texObj);
35637117f1b4Smrg   }
35647117f1b4Smrg   else if (target == GL_PROXY_TEXTURE_2D ||
35657117f1b4Smrg            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
35667117f1b4Smrg             ctx->Extensions.ARB_texture_cube_map)) {
35677117f1b4Smrg      /* Proxy texture: check for errors and update proxy state */
35687117f1b4Smrg      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
35697117f1b4Smrg                          internalFormat, width, height, 1, border, imageSize);
35707117f1b4Smrg      if (!error) {
35717117f1b4Smrg         ASSERT(ctx->Driver.TestProxyTexImage);
35727117f1b4Smrg         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
35737117f1b4Smrg                                              internalFormat, GL_NONE, GL_NONE,
35747117f1b4Smrg                                              width, height, 1, border);
35757117f1b4Smrg      }
35767117f1b4Smrg      if (error) {
35777117f1b4Smrg         /* if error, clear all proxy texture image parameters */
35787117f1b4Smrg         struct gl_texture_image *texImage;
35797117f1b4Smrg         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
35807117f1b4Smrg         if (texImage)
35817117f1b4Smrg            clear_teximage_fields(texImage);
35827117f1b4Smrg      }
35837117f1b4Smrg      else {
35847117f1b4Smrg         /* store the teximage parameters */
35857117f1b4Smrg         struct gl_texture_unit *texUnit;
35867117f1b4Smrg         struct gl_texture_object *texObj;
35877117f1b4Smrg         struct gl_texture_image *texImage;
35887117f1b4Smrg         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
35897117f1b4Smrg	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
35907117f1b4Smrg
35917117f1b4Smrg	 _mesa_lock_texture(ctx, texObj);
35927117f1b4Smrg	 {
35937117f1b4Smrg	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
35947117f1b4Smrg	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
35957117f1b4Smrg				       border, internalFormat);
35967117f1b4Smrg	 }
35977117f1b4Smrg	 _mesa_unlock_texture(ctx, texObj);
35987117f1b4Smrg      }
35997117f1b4Smrg   }
36007117f1b4Smrg   else {
36017117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
36027117f1b4Smrg      return;
36037117f1b4Smrg   }
36047117f1b4Smrg}
36057117f1b4Smrg
36067117f1b4Smrg
36077117f1b4Smrgvoid GLAPIENTRY
36087117f1b4Smrg_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
36097117f1b4Smrg                              GLenum internalFormat, GLsizei width,
36107117f1b4Smrg                              GLsizei height, GLsizei depth, GLint border,
36117117f1b4Smrg                              GLsizei imageSize, const GLvoid *data)
36127117f1b4Smrg{
36137117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
36147117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
36157117f1b4Smrg
36167117f1b4Smrg   if (target == GL_TEXTURE_3D) {
36177117f1b4Smrg      /* non-proxy target */
36187117f1b4Smrg      struct gl_texture_unit *texUnit;
36197117f1b4Smrg      struct gl_texture_object *texObj;
36207117f1b4Smrg      struct gl_texture_image *texImage;
36217117f1b4Smrg      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
36227117f1b4Smrg                      internalFormat, width, height, depth, border, imageSize);
36237117f1b4Smrg      if (error) {
36247117f1b4Smrg         _mesa_error(ctx, error, "glCompressedTexImage3D");
36257117f1b4Smrg         return;
36267117f1b4Smrg      }
36277117f1b4Smrg
36287117f1b4Smrg      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
36297117f1b4Smrg      texObj = _mesa_select_tex_object(ctx, texUnit, target);
36307117f1b4Smrg      _mesa_lock_texture(ctx, texObj);
36317117f1b4Smrg      {
36327117f1b4Smrg	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
36337117f1b4Smrg	 if (!texImage) {
36347117f1b4Smrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
36357117f1b4Smrg	    goto out;
36367117f1b4Smrg	 }
36377117f1b4Smrg
36387117f1b4Smrg	 if (texImage->Data) {
36397117f1b4Smrg	    ctx->Driver.FreeTexImageData( ctx, texImage );
36407117f1b4Smrg	 }
36417117f1b4Smrg	 ASSERT(texImage->Data == NULL);
36427117f1b4Smrg
36437117f1b4Smrg	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
36447117f1b4Smrg				    border, internalFormat);
36457117f1b4Smrg
36467117f1b4Smrg	 ASSERT(ctx->Driver.CompressedTexImage3D);
36477117f1b4Smrg	 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
36487117f1b4Smrg					     internalFormat,
36497117f1b4Smrg					     width, height, depth,
36507117f1b4Smrg					     border, imageSize, data,
36517117f1b4Smrg					     texObj, texImage);
36527117f1b4Smrg
36537117f1b4Smrg	 /* state update */
3654c1f859d4Smrg	 texObj->_Complete = GL_FALSE;
36557117f1b4Smrg	 ctx->NewState |= _NEW_TEXTURE;
36567117f1b4Smrg      }
36577117f1b4Smrg   out:
36587117f1b4Smrg      _mesa_unlock_texture(ctx, texObj);
36597117f1b4Smrg   }
36607117f1b4Smrg   else if (target == GL_PROXY_TEXTURE_3D) {
36617117f1b4Smrg      /* Proxy texture: check for errors and update proxy state */
36627117f1b4Smrg      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
36637117f1b4Smrg                      internalFormat, width, height, depth, border, imageSize);
36647117f1b4Smrg      if (!error) {
36657117f1b4Smrg         ASSERT(ctx->Driver.TestProxyTexImage);
36667117f1b4Smrg         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
36677117f1b4Smrg                                             internalFormat, GL_NONE, GL_NONE,
36687117f1b4Smrg                                             width, height, depth, border);
36697117f1b4Smrg      }
36707117f1b4Smrg      if (error) {
36717117f1b4Smrg         /* if error, clear all proxy texture image parameters */
36727117f1b4Smrg         struct gl_texture_image *texImage;
36737117f1b4Smrg         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
36747117f1b4Smrg         if (texImage)
36757117f1b4Smrg            clear_teximage_fields(texImage);
36767117f1b4Smrg      }
36777117f1b4Smrg      else {
36787117f1b4Smrg         /* store the teximage parameters */
36797117f1b4Smrg         struct gl_texture_unit *texUnit;
36807117f1b4Smrg         struct gl_texture_object *texObj;
36817117f1b4Smrg         struct gl_texture_image *texImage;
36827117f1b4Smrg         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
36837117f1b4Smrg	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
36847117f1b4Smrg	 _mesa_lock_texture(ctx, texObj);
36857117f1b4Smrg	 {
36867117f1b4Smrg	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
36877117f1b4Smrg	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
36887117f1b4Smrg				       depth, border, internalFormat);
36897117f1b4Smrg	 }
36907117f1b4Smrg	 _mesa_unlock_texture(ctx, texObj);
36917117f1b4Smrg      }
36927117f1b4Smrg   }
36937117f1b4Smrg   else {
36947117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
36957117f1b4Smrg      return;
36967117f1b4Smrg   }
36977117f1b4Smrg}
36987117f1b4Smrg
36997117f1b4Smrg
37007117f1b4Smrgvoid GLAPIENTRY
37017117f1b4Smrg_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
37027117f1b4Smrg                                 GLsizei width, GLenum format,
37037117f1b4Smrg                                 GLsizei imageSize, const GLvoid *data)
37047117f1b4Smrg{
37057117f1b4Smrg   struct gl_texture_unit *texUnit;
37067117f1b4Smrg   struct gl_texture_object *texObj;
37077117f1b4Smrg   struct gl_texture_image *texImage;
37087117f1b4Smrg   GLenum error;
37097117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
37107117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
37117117f1b4Smrg
37127117f1b4Smrg   error = compressed_subtexture_error_check(ctx, 1, target, level,
37137117f1b4Smrg                                             xoffset, 0, 0, /* pos */
37147117f1b4Smrg                                             width, 1, 1,   /* size */
37157117f1b4Smrg                                             format, imageSize);
37167117f1b4Smrg   if (error) {
37177117f1b4Smrg      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
37187117f1b4Smrg      return;
37197117f1b4Smrg   }
37207117f1b4Smrg
37217117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
37227117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
37237117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
37247117f1b4Smrg   {
37257117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
37267117f1b4Smrg      assert(texImage);
37277117f1b4Smrg
37287117f1b4Smrg      if ((GLint) format != texImage->InternalFormat) {
37297117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION,
37307117f1b4Smrg		     "glCompressedTexSubImage1D(format)");
37317117f1b4Smrg	 goto out;
37327117f1b4Smrg      }
37337117f1b4Smrg
37347117f1b4Smrg      if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
37357117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
37367117f1b4Smrg	 goto out;
37377117f1b4Smrg      }
37387117f1b4Smrg
37397117f1b4Smrg      if (width == 0)
37407117f1b4Smrg	 goto out;  /* no-op, not an error */
37417117f1b4Smrg
37427117f1b4Smrg      if (ctx->Driver.CompressedTexSubImage1D) {
37437117f1b4Smrg	 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
37447117f1b4Smrg						xoffset, width,
37457117f1b4Smrg						format, imageSize, data,
37467117f1b4Smrg						texObj, texImage);
37477117f1b4Smrg      }
37487117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
37497117f1b4Smrg   }
37507117f1b4Smrg out:
37517117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
37527117f1b4Smrg}
37537117f1b4Smrg
37547117f1b4Smrg
37557117f1b4Smrgvoid GLAPIENTRY
37567117f1b4Smrg_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
37577117f1b4Smrg                                 GLint yoffset, GLsizei width, GLsizei height,
37587117f1b4Smrg                                 GLenum format, GLsizei imageSize,
37597117f1b4Smrg                                 const GLvoid *data)
37607117f1b4Smrg{
37617117f1b4Smrg   struct gl_texture_unit *texUnit;
37627117f1b4Smrg   struct gl_texture_object *texObj;
37637117f1b4Smrg   struct gl_texture_image *texImage;
37647117f1b4Smrg   GLenum error;
37657117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
37667117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
37677117f1b4Smrg
37687117f1b4Smrg   error = compressed_subtexture_error_check(ctx, 2, target, level,
37697117f1b4Smrg                                             xoffset, yoffset, 0, /* pos */
37707117f1b4Smrg                                             width, height, 1,    /* size */
37717117f1b4Smrg                                             format, imageSize);
37727117f1b4Smrg   if (error) {
37737117f1b4Smrg      /* XXX proxy target? */
37747117f1b4Smrg      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
37757117f1b4Smrg      return;
37767117f1b4Smrg   }
37777117f1b4Smrg
37787117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
37797117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
37807117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
37817117f1b4Smrg   {
37827117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
37837117f1b4Smrg      assert(texImage);
37847117f1b4Smrg
37857117f1b4Smrg      if ((GLint) format != texImage->InternalFormat) {
37867117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION,
37877117f1b4Smrg		     "glCompressedTexSubImage2D(format)");
37887117f1b4Smrg	 goto out;
37897117f1b4Smrg      }
37907117f1b4Smrg
37917117f1b4Smrg      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
37927117f1b4Smrg	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
37937117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
37947117f1b4Smrg	 goto out;
37957117f1b4Smrg      }
37967117f1b4Smrg
37977117f1b4Smrg      if (width == 0 || height == 0)
37987117f1b4Smrg	 goto out;  /* no-op, not an error */
37997117f1b4Smrg
38007117f1b4Smrg      if (ctx->Driver.CompressedTexSubImage2D) {
38017117f1b4Smrg	 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
38027117f1b4Smrg						xoffset, yoffset, width, height,
38037117f1b4Smrg						format, imageSize, data,
38047117f1b4Smrg						texObj, texImage);
38057117f1b4Smrg      }
38067117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
38077117f1b4Smrg   }
38087117f1b4Smrg out:
38097117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
38107117f1b4Smrg}
38117117f1b4Smrg
38127117f1b4Smrg
38137117f1b4Smrgvoid GLAPIENTRY
38147117f1b4Smrg_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
38157117f1b4Smrg                                 GLint yoffset, GLint zoffset, GLsizei width,
38167117f1b4Smrg                                 GLsizei height, GLsizei depth, GLenum format,
38177117f1b4Smrg                                 GLsizei imageSize, const GLvoid *data)
38187117f1b4Smrg{
38197117f1b4Smrg   struct gl_texture_unit *texUnit;
38207117f1b4Smrg   struct gl_texture_object *texObj;
38217117f1b4Smrg   struct gl_texture_image *texImage;
38227117f1b4Smrg   GLenum error;
38237117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
38247117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
38257117f1b4Smrg
38267117f1b4Smrg   error = compressed_subtexture_error_check(ctx, 3, target, level,
38277117f1b4Smrg                                             xoffset, yoffset, zoffset,/*pos*/
38287117f1b4Smrg                                             width, height, depth, /*size*/
38297117f1b4Smrg                                             format, imageSize);
38307117f1b4Smrg   if (error) {
3831c1f859d4Smrg      _mesa_error(ctx, error, "glCompressedTexSubImage3D");
38327117f1b4Smrg      return;
38337117f1b4Smrg   }
38347117f1b4Smrg
38357117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
38367117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
38377117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
38387117f1b4Smrg   {
38397117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
38407117f1b4Smrg      assert(texImage);
38417117f1b4Smrg
38427117f1b4Smrg      if ((GLint) format != texImage->InternalFormat) {
38437117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_OPERATION,
38447117f1b4Smrg		     "glCompressedTexSubImage3D(format)");
38457117f1b4Smrg	 goto out;
38467117f1b4Smrg      }
38477117f1b4Smrg
38487117f1b4Smrg      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
38497117f1b4Smrg	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
38507117f1b4Smrg	  ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
38517117f1b4Smrg	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
38527117f1b4Smrg	 goto out;
38537117f1b4Smrg      }
38547117f1b4Smrg
38557117f1b4Smrg      if (width == 0 || height == 0 || depth == 0)
38567117f1b4Smrg	 goto out;  /* no-op, not an error */
38577117f1b4Smrg
38587117f1b4Smrg      if (ctx->Driver.CompressedTexSubImage3D) {
38597117f1b4Smrg	 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
38607117f1b4Smrg						xoffset, yoffset, zoffset,
38617117f1b4Smrg						width, height, depth,
38627117f1b4Smrg						format, imageSize, data,
38637117f1b4Smrg						texObj, texImage);
38647117f1b4Smrg      }
38657117f1b4Smrg      ctx->NewState |= _NEW_TEXTURE;
38667117f1b4Smrg   }
38677117f1b4Smrg out:
38687117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
38697117f1b4Smrg}
38707117f1b4Smrg
38717117f1b4Smrg
38727117f1b4Smrgvoid GLAPIENTRY
38737117f1b4Smrg_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
38747117f1b4Smrg{
38757117f1b4Smrg   const struct gl_texture_unit *texUnit;
38767117f1b4Smrg   struct gl_texture_object *texObj;
38777117f1b4Smrg   struct gl_texture_image *texImage;
38787117f1b4Smrg   GLint maxLevels;
38797117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
38807117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
38817117f1b4Smrg
38827117f1b4Smrg   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
38837117f1b4Smrg   texObj = _mesa_select_tex_object(ctx, texUnit, target);
38847117f1b4Smrg   if (!texObj) {
38857117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
38867117f1b4Smrg      return;
38877117f1b4Smrg   }
38887117f1b4Smrg
38897117f1b4Smrg   maxLevels = _mesa_max_texture_levels(ctx, target);
38907117f1b4Smrg   ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
38917117f1b4Smrg
38927117f1b4Smrg   if (level < 0 || level >= maxLevels) {
38937117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
38947117f1b4Smrg      return;
38957117f1b4Smrg   }
38967117f1b4Smrg
38977117f1b4Smrg   if (_mesa_is_proxy_texture(target)) {
38987117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
38997117f1b4Smrg      return;
39007117f1b4Smrg   }
39017117f1b4Smrg
39027117f1b4Smrg   _mesa_lock_texture(ctx, texObj);
39037117f1b4Smrg   {
39047117f1b4Smrg      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3905c1f859d4Smrg      if (texImage) {
3906c1f859d4Smrg         if (texImage->IsCompressed) {
3907c1f859d4Smrg            /* this typically calls _mesa_get_compressed_teximage() */
3908c1f859d4Smrg            ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
3909c1f859d4Smrg                                              texObj, texImage);
3910c1f859d4Smrg         }
3911c1f859d4Smrg         else {
3912c1f859d4Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
3913c1f859d4Smrg                        "glGetCompressedTexImageARB");
3914c1f859d4Smrg         }
39157117f1b4Smrg      }
3916c1f859d4Smrg      else {
3917c1f859d4Smrg         /* probably invalid mipmap level */
3918c1f859d4Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
3919c1f859d4Smrg                     "glGetCompressedTexImageARB(level)");
39207117f1b4Smrg      }
39217117f1b4Smrg   }
39227117f1b4Smrg   _mesa_unlock_texture(ctx, texObj);
39237117f1b4Smrg}
3924