teximage.c revision 4406f79402e8f986913c20c3138d12d0af670bd4
1242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * mesa 3-D graphics library
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Version:  7.6
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com *
8242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * Permission is hereby granted, free of charge, to any person obtaining a
985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * copy of this software and associated documentation files (the "Software"),
1085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * to deal in the Software without restriction, including without limitation
111ee76510f5dbf632d30975fc3509ef4f609156d2mtklein * the rights to use, copy, modify, merge, publish, distribute, sublicense,
121ee76510f5dbf632d30975fc3509ef4f609156d2mtklein * and/or sell copies of the Software, and to permit persons to whom the
1385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * Software is furnished to do so, subject to the following conditions:
1485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com *
1585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * The above copyright notice and this permission notice shall be included
1685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * in all copies or substantial portions of the Software.
1785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com *
1885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2185302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2285302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com */
2585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com
2685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com
2785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com/**
2885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * \file teximage.c
2985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * Texture image-related functions.
3085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com */
31ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
32242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
339df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "glheader.h"
34242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "bufferobj.h"
35242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "context.h"
369df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#if FEATURE_convolve
37242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "convolve.h"
38242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif
399df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "fbobject.h"
4059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com#include "framebuffer.h"
41242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "hash.h"
42c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "image.h"
43c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "imports.h"
44c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "macros.h"
45c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "state.h"
46c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texcompress.h"
47c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texformat.h"
48c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "teximage.h"
49c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texstate.h"
50c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texstore.h"
51242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "mtypes.h"
5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/**
5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * State changes which we care about for glCopyTex[Sub]Image() calls.
5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * In particular, we care about pixel transfer state and buffer state
5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * (such as glReadBuffer to make sure we read from the right renderbuffer).
5839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */
5939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                            _NEW_BUFFERS | \
6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                            _NEW_PIXEL)
6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
6439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
6596fcdcc219d2a0d3579719b84b28bede76efba64halcanary/**
6639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
6739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * elsewhere.
6839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */
6939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comvoid *
7039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com_mesa_alloc_texmemory(GLsizei bytes)
71242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{
7236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein   return _mesa_align_malloc(bytes, 512);
7339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
7439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
7639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/**
7739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * Free texture memory allocated with _mesa_alloc_texmemory()
78242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */
79242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comvoid
8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com_mesa_free_texmemory(void *m)
8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{
8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   _mesa_align_free(m);
8339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
8439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
8539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
8639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#if 0
8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{
9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#if CHAN_TYPE != GL_UNSIGNED_BYTE
9239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   _mesa_problem(NULL, "PrintTexture not supported");
9339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#else
9439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   GLuint i, j, c;
9539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   const GLubyte *data = (const GLubyte *) img->Data;
9639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
972a1208017dd676f94a53bbb228197c3978dbdd8ascroggo   if (!data) {
9839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      _mesa_printf("No texture data\n");
9939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      return;
10039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   }
10139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
10239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   switch (img->Format) {
10339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_ALPHA:
10439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_LUMINANCE:
10539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_INTENSITY:
10639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_COLOR_INDEX:
10796fcdcc219d2a0d3579719b84b28bede76efba64halcanary         c = 1;
10839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com         break;
10939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_LUMINANCE_ALPHA:
11039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com         c = 2;
11139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com         break;
112242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB:
1132e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com         c = 3;
1142e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com         break;
1152e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com      case GL_RGBA:
1162e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com         c = 4;
117d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com         break;
1182e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com      default:
119d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com         _mesa_problem(NULL, "error in PrintTexture\n");
120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return;
1219df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com   }
122242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   for (i = 0; i < img->Height; i++) {
124242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      for (j = 0; j < img->Width; j++) {
12596fcdcc219d2a0d3579719b84b28bede76efba64halcanary         if (c==1)
126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            _mesa_printf("%02x  ", data[0]);
127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         else if (c==2)
128242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            _mesa_printf("%02x%02x  ", data[0], data[1]);
129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         else if (c==3)
130d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            _mesa_printf("%02x%02x%02x  ", data[0], data[1], data[2]);
131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         else if (c==4)
1329df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com            _mesa_printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
133242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         data += (img->RowStride - img->Width) * c;
1349df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com      }
135242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      /* XXX use img->ImageStride here */
136d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      _mesa_printf("\n");
137242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
138242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif
139242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary#endif
141242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
142d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
143242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/*
1449df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * Compute floor(log_base_2(n)).
145242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * If n < 0 return -1.
146242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */
147242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comstatic int
14896fcdcc219d2a0d3579719b84b28bede76efba64halcanarylogbase2( int n )
149242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{
150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   GLint i = 1;
151242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   GLint log2 = 0;
152242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
153d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com   if (n < 0)
15439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      return -1;
15596fcdcc219d2a0d3579719b84b28bede76efba64halcanary
15639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   if (n == 0)
15739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      return 0;
15839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
15939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   while ( n > i ) {
16039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      i *= 2;
16139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      log2++;
16239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   }
16339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   if (i != n) {
16439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      return log2 - 1;
16539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   }
16639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com   else {
16739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      return log2;
168242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
1699df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com}
170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
171242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
172242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
173d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com/**
174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * Return the simple base format for a given internal texture format.
1759df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com *
177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \param ctx GL context.
178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
179242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com *
180242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
181d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
182242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com *
183242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * This is the format which is used during texture application (i.e. the
184242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * texture format and env mode determine the arithmetic used.
185242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */
186242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comGLint
187242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
188d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{
189242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   switch (internalFormat) {
190242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA:
191a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org      case GL_ALPHA4:
19239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_ALPHA8:
193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA12:
194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA16:
19596fcdcc219d2a0d3579719b84b28bede76efba64halcanary         return GL_ALPHA;
196242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case 1:
197242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE:
198242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE4:
199d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_LUMINANCE8:
200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE12:
2019df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com      case GL_LUMINANCE16:
202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_LUMINANCE;
203242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case 2:
204242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE_ALPHA:
205d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_LUMINANCE4_ALPHA4:
2062bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_LUMINANCE6_ALPHA2:
2072bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_LUMINANCE8_ALPHA8:
2082bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_LUMINANCE12_ALPHA4:
2092bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_LUMINANCE12_ALPHA12:
2102bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_LUMINANCE16_ALPHA16:
2112bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com         return GL_LUMINANCE_ALPHA;
2122bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_INTENSITY:
213242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_INTENSITY4:
214242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_INTENSITY8:
215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_INTENSITY12:
2162bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com      case GL_INTENSITY16:
217242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_INTENSITY;
21896fcdcc219d2a0d3579719b84b28bede76efba64halcanary      case 3:
219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB:
220242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_R3_G3_B2:
221242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB4:
222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB5:
223d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_RGB8:
224242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB10:
2259df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com      case GL_RGB12:
226242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB16:
227242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_RGB;
228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case 4:
229242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGBA:
230242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGBA2:
231d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_RGBA4:
232242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGB5_A1:
233242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_RGBA8:
234955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com      case GL_RGB10_A2:
235dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com      case GL_RGBA12:
2368b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com      case GL_RGBA16:
237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_RGBA;
23896fcdcc219d2a0d3579719b84b28bede76efba64halcanary      default:
239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         ; /* fallthrough */
240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
241242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
242242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   if (ctx->Extensions.EXT_paletted_texture) {
24359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com      switch (internalFormat) {
24459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         case GL_COLOR_INDEX:
245e7e29b7815e97e9c4db55fa9dac48b419352b2c6reed@google.com         case GL_COLOR_INDEX1_EXT:
246383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com         case GL_COLOR_INDEX2_EXT:
247383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com         case GL_COLOR_INDEX4_EXT:
248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COLOR_INDEX8_EXT:
249d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com         case GL_COLOR_INDEX12_EXT:
250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COLOR_INDEX16_EXT:
251242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_COLOR_INDEX;
252242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         default:
253242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
254242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
255b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com   }
2564c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
257b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com   if (ctx->Extensions.ARB_depth_texture) {
2584c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      switch (internalFormat) {
25996fcdcc219d2a0d3579719b84b28bede76efba64halcanary         case GL_DEPTH_COMPONENT:
2604c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com         case GL_DEPTH_COMPONENT16:
261385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary         case GL_DEPTH_COMPONENT24:
2624c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com         case GL_DEPTH_COMPONENT32:
2634c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            return GL_DEPTH_COMPONENT;
2644c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com         default:
265242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
266242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
267242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
268242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
269b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com   switch (internalFormat) {
27096fcdcc219d2a0d3579719b84b28bede76efba64halcanary   case GL_COMPRESSED_ALPHA:
271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      return GL_ALPHA;
272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   case GL_COMPRESSED_LUMINANCE:
273242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      return GL_LUMINANCE;
274242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   case GL_COMPRESSED_LUMINANCE_ALPHA:
275242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      return GL_LUMINANCE_ALPHA;
276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   case GL_COMPRESSED_INTENSITY:
277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      return GL_INTENSITY;
278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   case GL_COMPRESSED_RGB:
279242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      return GL_RGB;
280242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   case GL_COMPRESSED_RGBA:
281242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      return GL_RGBA;
282242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   default:
283242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      ; /* fallthrough */
284242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
285242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
286242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   if (ctx->Extensions.TDFX_texture_compression_FXT1) {
28722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com      switch (internalFormat) {
288242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COMPRESSED_RGB_FXT1_3DFX:
289242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_RGB;
290242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COMPRESSED_RGBA_FXT1_3DFX:
291242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_RGBA;
2924c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com         default:
2934c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            ; /* fallthrough */
2944c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      }
2954c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com   }
2964c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
2974c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com   if (ctx->Extensions.EXT_texture_compression_s3tc) {
298242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      switch (internalFormat) {
299242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
300242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_RGB;
301242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
302242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
303242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
304242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_RGBA;
305242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         default:
306242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
307242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
30822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com   }
30922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com
31022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com   if (ctx->Extensions.S3_s3tc) {
31128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org      switch (internalFormat) {
31222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com         case GL_RGB_S3TC:
31322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com         case GL_RGB4_S3TC:
31428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org            return GL_RGB;
31522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com         case GL_RGBA_S3TC:
31622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com         case GL_RGBA4_S3TC:
31722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            return GL_RGBA;
31822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com         default:
31922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            ; /* fallthrough */
32059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com      }
32159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com   }
32259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
32359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com   if (ctx->Extensions.MESA_ycbcr_texture) {
32459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com      if (internalFormat == GL_YCBCR_MESA)
32559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         return GL_YCBCR_MESA;
32659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com   }
32759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
32859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com   if (ctx->Extensions.ARB_texture_float) {
32959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com      switch (internalFormat) {
33059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         case GL_ALPHA16F_ARB:
33159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         case GL_ALPHA32F_ARB:
33259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            return GL_ALPHA;
33359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         case GL_RGBA16F_ARB:
33459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         case GL_RGBA32F_ARB:
33559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            return GL_RGBA;
33659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com         case GL_RGB16F_ARB:
337242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_RGB32F_ARB:
3382e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com            return GL_RGB;
3392e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com         case GL_INTENSITY16F_ARB:
3402e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com         case GL_INTENSITY32F_ARB:
3412e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com            return GL_INTENSITY;
342d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com         case GL_LUMINANCE16F_ARB:
3432e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com         case GL_LUMINANCE32F_ARB:
344d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            return GL_LUMINANCE;
345242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_LUMINANCE_ALPHA16F_ARB:
3469df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com         case GL_LUMINANCE_ALPHA32F_ARB:
347242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_LUMINANCE_ALPHA;
348242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         default:
349242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
35096fcdcc219d2a0d3579719b84b28bede76efba64halcanary      }
351242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
352242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
353242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   if (ctx->Extensions.ATI_envmap_bumpmap) {
354242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      switch (internalFormat) {
355d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com         case GL_DUDV_ATI:
3569df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com         case GL_DU8DV8_ATI:
3579df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com            return GL_DUDV_ATI;
358242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         default:
3599df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com            ; /* fallthrough */
360242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
361d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com   }
362242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
3639df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com   if (ctx->Extensions.MESA_texture_signed_rgba) {
364242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      switch (internalFormat) {
36596fcdcc219d2a0d3579719b84b28bede76efba64halcanary         case GL_RGBA_SNORM:
366242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_RGBA8_SNORM:
367d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            return GL_RGBA;
368242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         default:
369242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
370242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
371d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com   }
372242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
3739df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com   if (ctx->Extensions.EXT_packed_depth_stencil) {
3749df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com      switch (internalFormat) {
375242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_DEPTH_STENCIL_EXT:
376242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         case GL_DEPTH24_STENCIL8_EXT:
377242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return GL_DEPTH_STENCIL_EXT;
378d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com         default:
379242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
380242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
381242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
382242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
383242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#if FEATURE_EXT_texture_sRGB
384d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com   if (ctx->Extensions.EXT_texture_sRGB) {
385242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      switch (internalFormat) {
386242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SRGB_EXT:
387242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SRGB8_EXT:
388242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_COMPRESSED_SRGB_EXT:
389d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
390242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_RGB;
391242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SRGB_ALPHA_EXT:
392242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SRGB8_ALPHA8_EXT:
393242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_COMPRESSED_SRGB_ALPHA_EXT:
394242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
395242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
396242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
397242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_RGBA;
398242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SLUMINANCE_ALPHA_EXT:
399d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_SLUMINANCE8_ALPHA8_EXT:
400242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_COMPRESSED_SLUMINANCE_EXT:
40122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com      case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
40222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com         return GL_LUMINANCE_ALPHA;
403242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SLUMINANCE_EXT:
404242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_SLUMINANCE8_EXT:
405242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com         return GL_LUMINANCE;
406d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      default:
407242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            ; /* fallthrough */
408242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      }
409242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   }
410242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
411242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif /* FEATURE_EXT_texture_sRGB */
412242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
413242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   return -1; /* error */
414242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
415242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
416242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
417d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com/**
418242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * Test if the given image format is a color/RGBA format (i.e., not color
419242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * index, depth, stencil, etc).
420955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com * \param format  the image format value (may by an internal texture format)
4218b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
422242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * XXX maybe move this func to image.c
423242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */
4244b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.comGLboolean
4254b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com_mesa_is_color_format(GLenum format)
42622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com{
427242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com   switch (format) {
428d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_RED:
429242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_GREEN:
430242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_BLUE:
431242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA:
432d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case GL_ALPHA4:
433242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA8:
434242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA12:
435242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_ALPHA16:
436d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com      case 1:
437242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE:
438242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE4:
439242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE8:
4404c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_LUMINANCE12:
4414c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_LUMINANCE16:
4424c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case 2:
443242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE_ALPHA:
4444c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_LUMINANCE4_ALPHA4:
4454c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_LUMINANCE6_ALPHA2:
4464c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_LUMINANCE8_ALPHA8:
4474c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_LUMINANCE12_ALPHA4:
448242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE12_ALPHA12:
449242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_LUMINANCE16_ALPHA16:
45096fcdcc219d2a0d3579719b84b28bede76efba64halcanary      case GL_INTENSITY:
451242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_INTENSITY4:
452385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary      case GL_INTENSITY8:
453242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com      case GL_INTENSITY12:
4544c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com      case GL_INTENSITY16:
455b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com      case 3:
45639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_RGB:
457b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com      case GL_BGR:
45839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_R3_G3_B2:
45939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_RGB4:
46096fcdcc219d2a0d3579719b84b28bede76efba64halcanary      case GL_RGB5:
46139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_RGB8:
46239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_RGB10:
46339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_RGB12:
46439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case GL_RGB16:
46539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com      case 4:
466b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com      case GL_ABGR_EXT:
4671ee76510f5dbf632d30975fc3509ef4f609156d2mtklein      case GL_RGBA:
4681ee76510f5dbf632d30975fc3509ef4f609156d2mtklein      case GL_BGRA:
469      case GL_RGBA2:
470      case GL_RGBA4:
471      case GL_RGB5_A1:
472      case GL_RGBA8:
473      case GL_RGB10_A2:
474      case GL_RGBA12:
475      case GL_RGBA16:
476      /* float texture formats */
477      case GL_ALPHA16F_ARB:
478      case GL_ALPHA32F_ARB:
479      case GL_LUMINANCE16F_ARB:
480      case GL_LUMINANCE32F_ARB:
481      case GL_LUMINANCE_ALPHA16F_ARB:
482      case GL_LUMINANCE_ALPHA32F_ARB:
483      case GL_INTENSITY16F_ARB:
484      case GL_INTENSITY32F_ARB:
485      case GL_RGB16F_ARB:
486      case GL_RGB32F_ARB:
487      case GL_RGBA16F_ARB:
488      case GL_RGBA32F_ARB:
489      /* compressed formats */
490      case GL_COMPRESSED_ALPHA:
491      case GL_COMPRESSED_LUMINANCE:
492      case GL_COMPRESSED_LUMINANCE_ALPHA:
493      case GL_COMPRESSED_INTENSITY:
494      case GL_COMPRESSED_RGB:
495      case GL_COMPRESSED_RGBA:
496      case GL_RGB_S3TC:
497      case GL_RGB4_S3TC:
498      case GL_RGBA_S3TC:
499      case GL_RGBA4_S3TC:
500      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
501      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
502      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
503      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
504      case GL_COMPRESSED_RGB_FXT1_3DFX:
505      case GL_COMPRESSED_RGBA_FXT1_3DFX:
506#if FEATURE_EXT_texture_sRGB
507      case GL_SRGB_EXT:
508      case GL_SRGB8_EXT:
509      case GL_SRGB_ALPHA_EXT:
510      case GL_SRGB8_ALPHA8_EXT:
511      case GL_SLUMINANCE_ALPHA_EXT:
512      case GL_SLUMINANCE8_ALPHA8_EXT:
513      case GL_SLUMINANCE_EXT:
514      case GL_SLUMINANCE8_EXT:
515      case GL_COMPRESSED_SRGB_EXT:
516      case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
517      case GL_COMPRESSED_SRGB_ALPHA_EXT:
518      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
519      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
520      case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
521      case GL_COMPRESSED_SLUMINANCE_EXT:
522      case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
523#endif /* FEATURE_EXT_texture_sRGB */
524         return GL_TRUE;
525      /* signed texture formats */
526      case GL_RGBA_SNORM:
527      case GL_RGBA8_SNORM:
528         return GL_TRUE;
529      case GL_YCBCR_MESA:  /* not considered to be RGB */
530         /* fall-through */
531      default:
532         return GL_FALSE;
533   }
534}
535
536
537/**
538 * Test if the given image format is a color index format.
539 */
540static GLboolean
541is_index_format(GLenum format)
542{
543   switch (format) {
544      case GL_COLOR_INDEX:
545      case GL_COLOR_INDEX1_EXT:
546      case GL_COLOR_INDEX2_EXT:
547      case GL_COLOR_INDEX4_EXT:
548      case GL_COLOR_INDEX8_EXT:
549      case GL_COLOR_INDEX12_EXT:
550      case GL_COLOR_INDEX16_EXT:
551         return GL_TRUE;
552      default:
553         return GL_FALSE;
554   }
555}
556
557
558/**
559 * Test if the given image format is a depth component format.
560 */
561static GLboolean
562is_depth_format(GLenum format)
563{
564   switch (format) {
565      case GL_DEPTH_COMPONENT16:
566      case GL_DEPTH_COMPONENT24:
567      case GL_DEPTH_COMPONENT32:
568      case GL_DEPTH_COMPONENT:
569         return GL_TRUE;
570      default:
571         return GL_FALSE;
572   }
573}
574
575
576/**
577 * Test if the given image format is a YCbCr format.
578 */
579static GLboolean
580is_ycbcr_format(GLenum format)
581{
582   switch (format) {
583      case GL_YCBCR_MESA:
584         return GL_TRUE;
585      default:
586         return GL_FALSE;
587   }
588}
589
590
591/**
592 * Test if the given image format is a Depth/Stencil format.
593 */
594static GLboolean
595is_depthstencil_format(GLenum format)
596{
597   switch (format) {
598      case GL_DEPTH24_STENCIL8_EXT:
599      case GL_DEPTH_STENCIL_EXT:
600         return GL_TRUE;
601      default:
602         return GL_FALSE;
603   }
604}
605
606/**
607 * Test if the given image format is a dudv format.
608 */
609static GLboolean
610is_dudv_format(GLenum format)
611{
612   switch (format) {
613      case GL_DUDV_ATI:
614      case GL_DU8DV8_ATI:
615         return GL_TRUE;
616      default:
617         return GL_FALSE;
618   }
619}
620
621
622/**
623 * Test if it is a supported compressed format.
624 *
625 * \param internalFormat the internal format token provided by the user.
626 *
627 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
628 * GL_FALSE otherwise.
629 *
630 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
631 * are supported.
632 */
633static GLboolean
634is_compressed_format(GLcontext *ctx, GLenum internalFormat)
635{
636   GLint supported[100]; /* 100 should be plenty */
637   GLuint i, n;
638
639   n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE);
640   ASSERT(n < 100);
641   for (i = 0; i < n; i++) {
642      if ((GLint) internalFormat == supported[i]) {
643         return GL_TRUE;
644      }
645   }
646   return GL_FALSE;
647}
648
649
650/**
651 * For cube map faces, return a face index in [0,5].
652 * For other targets return 0;
653 */
654GLuint
655_mesa_tex_target_to_face(GLenum target)
656{
657   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
658       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
659      return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
660   else
661      return 0;
662}
663
664
665
666/**
667 * Store a gl_texture_image pointer in a gl_texture_object structure
668 * according to the target and level parameters.
669 *
670 * \param tObj texture object.
671 * \param target texture target.
672 * \param level image level.
673 * \param texImage texture image.
674 *
675 * This was basically prompted by the introduction of cube maps.
676 */
677void
678_mesa_set_tex_image(struct gl_texture_object *tObj,
679                    GLenum target, GLint level,
680                    struct gl_texture_image *texImage)
681{
682   const GLuint face = _mesa_tex_target_to_face(target);
683
684   ASSERT(tObj);
685   ASSERT(texImage);
686   ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
687
688   tObj->Image[face][level] = texImage;
689
690   /* Set the 'back' pointer */
691   texImage->TexObject = tObj;
692}
693
694
695/**
696 * Allocate a texture image structure.
697 *
698 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
699 * driver.
700 *
701 * \return a pointer to gl_texture_image struct with all fields initialized to
702 * zero.
703 */
704struct gl_texture_image *
705_mesa_new_texture_image( GLcontext *ctx )
706{
707   (void) ctx;
708   return CALLOC_STRUCT(gl_texture_image);
709}
710
711
712/**
713 * Free texture image data.
714 * This function is a fallback called via ctx->Driver.FreeTexImageData().
715 *
716 * \param texImage texture image.
717 *
718 * Free the texture image data if it's not marked as client data.
719 */
720void
721_mesa_free_texture_image_data(GLcontext *ctx,
722                              struct gl_texture_image *texImage)
723{
724   (void) ctx;
725
726   if (texImage->Data && !texImage->IsClientData) {
727      /* free the old texture data */
728      _mesa_free_texmemory(texImage->Data);
729   }
730
731   texImage->Data = NULL;
732}
733
734
735/**
736 * Free texture image.
737 *
738 * \param texImage texture image.
739 *
740 * Free the texture image structure and the associated image data.
741 */
742void
743_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
744{
745   /* Free texImage->Data and/or any other driver-specific texture
746    * image storage.
747    */
748   ASSERT(ctx->Driver.FreeTexImageData);
749   ctx->Driver.FreeTexImageData( ctx, texImage );
750
751   ASSERT(texImage->Data == NULL);
752   if (texImage->ImageOffsets)
753      _mesa_free(texImage->ImageOffsets);
754   _mesa_free(texImage);
755}
756
757
758/**
759 * Test if a target is a proxy target.
760 *
761 * \param target texture target.
762 *
763 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
764 */
765GLboolean
766_mesa_is_proxy_texture(GLenum target)
767{
768   return (target == GL_PROXY_TEXTURE_1D ||
769           target == GL_PROXY_TEXTURE_2D ||
770           target == GL_PROXY_TEXTURE_3D ||
771           target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
772           target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
773           target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
774           target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
775}
776
777
778/**
779 * Return pointer to current texture unit.
780 * This the texture unit set by glActiveTexture(), not glClientActiveTexture().
781 */
782static INLINE struct gl_texture_unit *
783get_current_tex_unit(GLcontext *ctx)
784{
785   ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit));
786   return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
787}
788
789
790/**
791 * Get the texture object that corresponds to the target of the given texture unit.
792 *
793 * \param ctx GL context.
794 * \param texUnit texture unit.
795 * \param target texture target.
796 *
797 * \return pointer to the texture object on success, or NULL on failure.
798 *
799 * \sa gl_texture_unit.
800 */
801struct gl_texture_object *
802_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
803                        GLenum target)
804{
805   switch (target) {
806      case GL_TEXTURE_1D:
807         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
808      case GL_PROXY_TEXTURE_1D:
809         return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
810      case GL_TEXTURE_2D:
811         return texUnit->CurrentTex[TEXTURE_2D_INDEX];
812      case GL_PROXY_TEXTURE_2D:
813         return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
814      case GL_TEXTURE_3D:
815         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
816      case GL_PROXY_TEXTURE_3D:
817         return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
818      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
819      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
820      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
821      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
822      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
823      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
824      case GL_TEXTURE_CUBE_MAP_ARB:
825         return ctx->Extensions.ARB_texture_cube_map
826                ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
827      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
828         return ctx->Extensions.ARB_texture_cube_map
829                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
830      case GL_TEXTURE_RECTANGLE_NV:
831         return ctx->Extensions.NV_texture_rectangle
832                ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
833      case GL_PROXY_TEXTURE_RECTANGLE_NV:
834         return ctx->Extensions.NV_texture_rectangle
835                ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
836      case GL_TEXTURE_1D_ARRAY_EXT:
837         return ctx->Extensions.MESA_texture_array
838                ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
839      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
840         return ctx->Extensions.MESA_texture_array
841                ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
842      case GL_TEXTURE_2D_ARRAY_EXT:
843         return ctx->Extensions.MESA_texture_array
844                ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
845      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
846         return ctx->Extensions.MESA_texture_array
847                ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
848      default:
849         _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
850         return NULL;
851   }
852}
853
854
855/**
856 * Get a texture image pointer from a texture object, given a texture
857 * target and mipmap level.  The target and level parameters should
858 * have already been error-checked.
859 *
860 * \param ctx GL context.
861 * \param texObj texture unit.
862 * \param target texture target.
863 * \param level image level.
864 *
865 * \return pointer to the texture image structure, or NULL on failure.
866 */
867struct gl_texture_image *
868_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
869		       GLenum target, GLint level)
870{
871   const GLuint face = _mesa_tex_target_to_face(target);
872
873   ASSERT(texObj);
874   ASSERT(level >= 0);
875   ASSERT(level < MAX_TEXTURE_LEVELS);
876
877   return texObj->Image[face][level];
878}
879
880
881/**
882 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
883 * it and install it.  Only return NULL if passed a bad parameter or run
884 * out of memory.
885 */
886struct gl_texture_image *
887_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
888                    GLenum target, GLint level)
889{
890   struct gl_texture_image *texImage;
891
892   if (!texObj)
893      return NULL;
894
895   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
896   if (!texImage) {
897      texImage = ctx->Driver.NewTextureImage(ctx);
898      if (!texImage) {
899         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
900         return NULL;
901      }
902
903      _mesa_set_tex_image(texObj, target, level, texImage);
904   }
905
906   return texImage;
907}
908
909
910/**
911 * Return pointer to the specified proxy texture image.
912 * Note that proxy textures are per-context, not per-texture unit.
913 * \return pointer to texture image or NULL if invalid target, invalid
914 *         level, or out of memory.
915 */
916struct gl_texture_image *
917_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
918{
919   struct gl_texture_image *texImage;
920   GLuint texIndex;
921
922   if (level < 0 )
923      return NULL;
924
925   switch (target) {
926   case GL_PROXY_TEXTURE_1D:
927      if (level >= ctx->Const.MaxTextureLevels)
928         return NULL;
929      texIndex = TEXTURE_1D_INDEX;
930      break;
931   case GL_PROXY_TEXTURE_2D:
932      if (level >= ctx->Const.MaxTextureLevels)
933         return NULL;
934      texIndex = TEXTURE_2D_INDEX;
935      break;
936   case GL_PROXY_TEXTURE_3D:
937      if (level >= ctx->Const.Max3DTextureLevels)
938         return NULL;
939      texIndex = TEXTURE_3D_INDEX;
940      break;
941   case GL_PROXY_TEXTURE_CUBE_MAP:
942      if (level >= ctx->Const.MaxCubeTextureLevels)
943         return NULL;
944      texIndex = TEXTURE_CUBE_INDEX;
945      break;
946   case GL_PROXY_TEXTURE_RECTANGLE_NV:
947      if (level > 0)
948         return NULL;
949      texIndex = TEXTURE_RECT_INDEX;
950      break;
951   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
952      if (level >= ctx->Const.MaxTextureLevels)
953         return NULL;
954      texIndex = TEXTURE_1D_ARRAY_INDEX;
955      break;
956   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
957      if (level >= ctx->Const.MaxTextureLevels)
958         return NULL;
959      texIndex = TEXTURE_2D_ARRAY_INDEX;
960      break;
961   default:
962      return NULL;
963   }
964
965   texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
966   if (!texImage) {
967      texImage = ctx->Driver.NewTextureImage(ctx);
968      if (!texImage) {
969         _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
970         return NULL;
971      }
972      ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
973      /* Set the 'back' pointer */
974      texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
975   }
976   return texImage;
977}
978
979
980/**
981 * Get the maximum number of allowed mipmap levels.
982 *
983 * \param ctx GL context.
984 * \param target texture target.
985 *
986 * \return the maximum number of allowed mipmap levels for the given
987 * texture target, or zero if passed a bad target.
988 *
989 * \sa gl_constants.
990 */
991GLint
992_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
993{
994   switch (target) {
995   case GL_TEXTURE_1D:
996   case GL_PROXY_TEXTURE_1D:
997   case GL_TEXTURE_2D:
998   case GL_PROXY_TEXTURE_2D:
999   case GL_TEXTURE_1D_ARRAY_EXT:
1000   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1001   case GL_TEXTURE_2D_ARRAY_EXT:
1002   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1003      return ctx->Const.MaxTextureLevels;
1004   case GL_TEXTURE_3D:
1005   case GL_PROXY_TEXTURE_3D:
1006      return ctx->Const.Max3DTextureLevels;
1007   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
1008   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
1009   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
1010   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
1011   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
1012   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
1013   case GL_TEXTURE_CUBE_MAP_ARB:
1014   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1015      return ctx->Const.MaxCubeTextureLevels;
1016   case GL_TEXTURE_RECTANGLE_NV:
1017   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1018      return 1;
1019   default:
1020      return 0; /* bad target */
1021   }
1022}
1023
1024
1025
1026#if 000 /* not used anymore */
1027/*
1028 * glTexImage[123]D can accept a NULL image pointer.  In this case we
1029 * create a texture image with unspecified image contents per the OpenGL
1030 * spec.
1031 */
1032static GLubyte *
1033make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
1034{
1035   const GLint components = _mesa_components_in_format(format);
1036   const GLint numPixels = width * height * depth;
1037   GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
1038
1039#ifdef DEBUG
1040   /*
1041    * Let's see if anyone finds this.  If glTexImage2D() is called with
1042    * a NULL image pointer then load the texture image with something
1043    * interesting instead of leaving it indeterminate.
1044    */
1045   if (data) {
1046      static const char message[8][32] = {
1047         "   X   X  XXXXX   XXX     X    ",
1048         "   XX XX  X      X   X   X X   ",
1049         "   X X X  X      X      X   X  ",
1050         "   X   X  XXXX    XXX   XXXXX  ",
1051         "   X   X  X          X  X   X  ",
1052         "   X   X  X      X   X  X   X  ",
1053         "   X   X  XXXXX   XXX   X   X  ",
1054         "                               "
1055      };
1056
1057      GLubyte *imgPtr = data;
1058      GLint h, i, j, k;
1059      for (h = 0; h < depth; h++) {
1060         for (i = 0; i < height; i++) {
1061            GLint srcRow = 7 - (i % 8);
1062            for (j = 0; j < width; j++) {
1063               GLint srcCol = j % 32;
1064               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
1065               for (k = 0; k < components; k++) {
1066                  *imgPtr++ = texel;
1067               }
1068            }
1069         }
1070      }
1071   }
1072#endif
1073
1074   return data;
1075}
1076#endif
1077
1078
1079
1080/**
1081 * Reset the fields of a gl_texture_image struct to zero.
1082 *
1083 * \param img texture image structure.
1084 *
1085 * This is called when a proxy texture test fails, we set all the
1086 * image members (except DriverData) to zero.
1087 * It's also used in glTexImage[123]D as a safeguard to be sure all
1088 * required fields get initialized properly by the Driver.TexImage[123]D
1089 * functions.
1090 */
1091static void
1092clear_teximage_fields(struct gl_texture_image *img)
1093{
1094   ASSERT(img);
1095   img->_BaseFormat = 0;
1096   img->InternalFormat = 0;
1097   img->Border = 0;
1098   img->Width = 0;
1099   img->Height = 0;
1100   img->Depth = 0;
1101   img->RowStride = 0;
1102   if (img->ImageOffsets) {
1103      _mesa_free(img->ImageOffsets);
1104      img->ImageOffsets = NULL;
1105   }
1106   img->Width2 = 0;
1107   img->Height2 = 0;
1108   img->Depth2 = 0;
1109   img->WidthLog2 = 0;
1110   img->HeightLog2 = 0;
1111   img->DepthLog2 = 0;
1112   img->Data = NULL;
1113   img->TexFormat = &_mesa_null_texformat;
1114   img->FetchTexelc = NULL;
1115   img->FetchTexelf = NULL;
1116   img->IsCompressed = 0;
1117   img->CompressedSize = 0;
1118}
1119
1120
1121/**
1122 * Initialize basic fields of the gl_texture_image struct.
1123 *
1124 * \param ctx GL context.
1125 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
1126 * \param img texture image structure to be initialized.
1127 * \param width image width.
1128 * \param height image height.
1129 * \param depth image depth.
1130 * \param border image border.
1131 * \param internalFormat internal format.
1132 *
1133 * Fills in the fields of \p img with the given information.
1134 * Note: width, height and depth include the border.
1135 */
1136void
1137_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
1138                           struct gl_texture_image *img,
1139                           GLsizei width, GLsizei height, GLsizei depth,
1140                           GLint border, GLenum internalFormat)
1141{
1142   GLint i;
1143
1144   ASSERT(img);
1145   ASSERT(width >= 0);
1146   ASSERT(height >= 0);
1147   ASSERT(depth >= 0);
1148
1149   img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
1150   ASSERT(img->_BaseFormat > 0);
1151   img->InternalFormat = internalFormat;
1152   img->Border = border;
1153   img->Width = width;
1154   img->Height = height;
1155   img->Depth = depth;
1156
1157   img->Width2 = width - 2 * border;   /* == 1 << img->WidthLog2; */
1158   img->WidthLog2 = logbase2(img->Width2);
1159
1160   if (height == 1) { /* 1-D texture */
1161      img->Height2 = 1;
1162      img->HeightLog2 = 0;
1163   }
1164   else {
1165      img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
1166      img->HeightLog2 = logbase2(img->Height2);
1167   }
1168
1169   if (depth == 1) {  /* 2-D texture */
1170      img->Depth2 = 1;
1171      img->DepthLog2 = 0;
1172   }
1173   else {
1174      img->Depth2 = depth - 2 * border;   /* == 1 << img->DepthLog2; */
1175      img->DepthLog2 = logbase2(img->Depth2);
1176   }
1177
1178   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
1179
1180   img->IsCompressed = GL_FALSE;
1181   img->CompressedSize = 0;
1182
1183   if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
1184       (height == 1 || _mesa_is_pow_two(img->Height2)) &&
1185       (depth == 1 || _mesa_is_pow_two(img->Depth2)))
1186      img->_IsPowerOfTwo = GL_TRUE;
1187   else
1188      img->_IsPowerOfTwo = GL_FALSE;
1189
1190   /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
1191   img->RowStride = width;
1192   /* Allocate the ImageOffsets array and initialize to typical values.
1193    * We allocate the array for 1D/2D textures too in order to avoid special-
1194    * case code in the texstore routines.
1195    */
1196   if (img->ImageOffsets)
1197      _mesa_free(img->ImageOffsets);
1198   img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
1199   for (i = 0; i < depth; i++) {
1200      img->ImageOffsets[i] = i * width * height;
1201   }
1202
1203   /* Compute Width/Height/DepthScale for mipmap lod computation */
1204   if (target == GL_TEXTURE_RECTANGLE_NV) {
1205      /* scale = 1.0 since texture coords directly map to texels */
1206      img->WidthScale = 1.0;
1207      img->HeightScale = 1.0;
1208      img->DepthScale = 1.0;
1209   }
1210   else {
1211      img->WidthScale = (GLfloat) img->Width;
1212      img->HeightScale = (GLfloat) img->Height;
1213      img->DepthScale = (GLfloat) img->Depth;
1214   }
1215}
1216
1217
1218/**
1219 * This is the fallback for Driver.TestProxyTexImage().  Test the texture
1220 * level, width, height and depth against the ctx->Const limits for textures.
1221 *
1222 * A hardware driver might override this function if, for example, the
1223 * max 3D texture size is 512x512x64 (i.e. not a cube).
1224 *
1225 * Note that width, height, depth == 0 is not an error.  However, a
1226 * texture with zero width/height/depth will be considered "incomplete"
1227 * and texturing will effectively be disabled.
1228 *
1229 * \param target  one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1230 *                GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1231 *                GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1232 * \param level  as passed to glTexImage
1233 * \param internalFormat  as passed to glTexImage
1234 * \param format  as passed to glTexImage
1235 * \param type  as passed to glTexImage
1236 * \param width  as passed to glTexImage
1237 * \param height  as passed to glTexImage
1238 * \param depth  as passed to glTexImage
1239 * \param border  as passed to glTexImage
1240 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1241 */
1242GLboolean
1243_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1244                          GLint internalFormat, GLenum format, GLenum type,
1245                          GLint width, GLint height, GLint depth, GLint border)
1246{
1247   GLint maxSize;
1248
1249   (void) internalFormat;
1250   (void) format;
1251   (void) type;
1252
1253   switch (target) {
1254   case GL_PROXY_TEXTURE_1D:
1255      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1256      if (width < 2 * border || width > 2 + maxSize ||
1257          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1258           width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
1259          level >= ctx->Const.MaxTextureLevels) {
1260         /* bad width or level */
1261         return GL_FALSE;
1262      }
1263      return GL_TRUE;
1264   case GL_PROXY_TEXTURE_2D:
1265      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1266      if (width < 2 * border || width > 2 + maxSize ||
1267          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1268           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1269          height < 2 * border || height > 2 + maxSize ||
1270          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1271           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1272          level >= ctx->Const.MaxTextureLevels) {
1273         /* bad width or height or level */
1274         return GL_FALSE;
1275      }
1276      return GL_TRUE;
1277   case GL_PROXY_TEXTURE_3D:
1278      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1279      if (width < 2 * border || width > 2 + maxSize ||
1280          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1281           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1282          height < 2 * border || height > 2 + maxSize ||
1283          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1284           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1285          depth < 2 * border || depth > 2 + maxSize ||
1286          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1287           depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
1288          level >= ctx->Const.Max3DTextureLevels) {
1289         /* bad width or height or depth or level */
1290         return GL_FALSE;
1291      }
1292      return GL_TRUE;
1293   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1294      if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
1295          height < 0 || height > ctx->Const.MaxTextureRectSize ||
1296          level != 0) {
1297         /* bad width or height or level */
1298         return GL_FALSE;
1299      }
1300      return GL_TRUE;
1301   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1302      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1303      if (width < 2 * border || width > 2 + maxSize ||
1304          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1305           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1306          height < 2 * border || height > 2 + maxSize ||
1307          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1308           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1309          level >= ctx->Const.MaxCubeTextureLevels) {
1310         /* bad width or height */
1311         return GL_FALSE;
1312      }
1313      return GL_TRUE;
1314   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1315      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1316      if (width < 2 * border || width > 2 + maxSize ||
1317          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1318           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1319          level >= ctx->Const.MaxTextureLevels) {
1320         /* bad width or level */
1321         return GL_FALSE;
1322      }
1323
1324      if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
1325         return GL_FALSE;
1326      }
1327      return GL_TRUE;
1328   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1329      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1330      if (width < 2 * border || width > 2 + maxSize ||
1331          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1332           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1333          height < 2 * border || height > 2 + maxSize ||
1334          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1335           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1336          level >= ctx->Const.MaxTextureLevels) {
1337         /* bad width or height or level */
1338         return GL_FALSE;
1339      }
1340      if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
1341         return GL_FALSE;
1342      }
1343      return GL_TRUE;
1344   default:
1345      _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1346      return GL_FALSE;
1347   }
1348}
1349
1350
1351/**
1352 * Helper function to determine whether a target supports compressed textures
1353 */
1354static GLboolean
1355target_can_be_compressed(GLcontext *ctx, GLenum target)
1356{
1357   return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
1358           || ((ctx->Extensions.ARB_texture_cube_map &&
1359                (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1360                 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1361                  target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
1362           || ((ctx->Extensions.MESA_texture_array &&
1363                ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
1364                 (target == GL_TEXTURE_2D_ARRAY_EXT)))));
1365}
1366
1367
1368/**
1369 * Test the glTexImage[123]D() parameters for errors.
1370 *
1371 * \param ctx GL context.
1372 * \param target texture target given by the user.
1373 * \param level image level given by the user.
1374 * \param internalFormat internal format given by the user.
1375 * \param format pixel data format given by the user.
1376 * \param type pixel data type given by the user.
1377 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1378 * \param width image width given by the user.
1379 * \param height image height given by the user.
1380 * \param depth image depth given by the user.
1381 * \param border image border given by the user.
1382 *
1383 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1384 *
1385 * Verifies each of the parameters against the constants specified in
1386 * __GLcontextRec::Const and the supported extensions, and according to the
1387 * OpenGL specification.
1388 */
1389static GLboolean
1390texture_error_check( GLcontext *ctx, GLenum target,
1391                     GLint level, GLint internalFormat,
1392                     GLenum format, GLenum type,
1393                     GLuint dimensions,
1394                     GLint width, GLint height,
1395                     GLint depth, GLint border )
1396{
1397   const GLboolean isProxy = _mesa_is_proxy_texture(target);
1398   GLboolean sizeOK = GL_TRUE;
1399   GLboolean colorFormat, indexFormat;
1400   GLenum proxy_target;
1401
1402   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1403   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1404      if (!isProxy) {
1405         _mesa_error(ctx, GL_INVALID_VALUE,
1406                     "glTexImage%dD(level=%d)", dimensions, level);
1407      }
1408      return GL_TRUE;
1409   }
1410
1411   /* Check border */
1412   if (border < 0 || border > 1 ||
1413       ((target == GL_TEXTURE_RECTANGLE_NV ||
1414         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1415      if (!isProxy) {
1416         _mesa_error(ctx, GL_INVALID_VALUE,
1417                     "glTexImage%dD(border=%d)", dimensions, border);
1418      }
1419      return GL_TRUE;
1420   }
1421
1422   if (width < 0 || height < 0 || depth < 0) {
1423      if (!isProxy) {
1424         _mesa_error(ctx, GL_INVALID_VALUE,
1425                     "glTexImage%dD(width, height or depth < 0)", dimensions);
1426      }
1427      return GL_TRUE;
1428   }
1429
1430   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1431    * level, width, height and depth.
1432    */
1433   if (dimensions == 1) {
1434      if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1435         proxy_target = GL_PROXY_TEXTURE_1D;
1436         height = 1;
1437         depth = 1;
1438      }
1439      else {
1440         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1441         return GL_TRUE;
1442      }
1443   }
1444   else if (dimensions == 2) {
1445      depth = 1;
1446      if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1447         proxy_target = GL_PROXY_TEXTURE_2D;
1448      }
1449      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1450               (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1451                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1452         if (!ctx->Extensions.ARB_texture_cube_map) {
1453            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1454            return GL_TRUE;
1455         }
1456         proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
1457         sizeOK = (width == height);
1458      }
1459      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1460               target == GL_TEXTURE_RECTANGLE_NV) {
1461         if (!ctx->Extensions.NV_texture_rectangle) {
1462            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1463            return GL_TRUE;
1464         }
1465         proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
1466      }
1467      else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
1468               target == GL_TEXTURE_1D_ARRAY_EXT) {
1469         proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
1470      }
1471      else {
1472         _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1473         return GL_TRUE;
1474      }
1475   }
1476   else if (dimensions == 3) {
1477      if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1478         proxy_target = GL_PROXY_TEXTURE_3D;
1479      }
1480      else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
1481               target == GL_TEXTURE_2D_ARRAY_EXT) {
1482         proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
1483      }
1484      else {
1485         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1486         return GL_TRUE;
1487      }
1488   }
1489   else {
1490      _mesa_problem( ctx, "bad dims in texture_error_check" );
1491      return GL_TRUE;
1492   }
1493
1494   sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
1495                                                    internalFormat, format,
1496                                                    type, width, height,
1497                                                    depth, border);
1498   if (!sizeOK) {
1499      if (!isProxy) {
1500         _mesa_error(ctx, GL_INVALID_VALUE,
1501                     "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1502                     dimensions, level, width, height, depth);
1503      }
1504      return GL_TRUE;
1505   }
1506
1507   /* Check internalFormat */
1508   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1509      if (!isProxy) {
1510         _mesa_error(ctx, GL_INVALID_VALUE,
1511                     "glTexImage%dD(internalFormat=0x%x)",
1512                     dimensions, internalFormat);
1513      }
1514      return GL_TRUE;
1515   }
1516
1517   /* Check incoming image format and type */
1518   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1519      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1520       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
1521       */
1522      if (!isProxy) {
1523         _mesa_error(ctx, GL_INVALID_OPERATION,
1524                     "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
1525                     dimensions, format, type);
1526      }
1527      return GL_TRUE;
1528   }
1529
1530   /* make sure internal format and format basically agree */
1531   colorFormat = _mesa_is_color_format(format);
1532   indexFormat = is_index_format(format);
1533   if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1534       (is_index_format(internalFormat) && !indexFormat) ||
1535       (is_depth_format(internalFormat) != is_depth_format(format)) ||
1536       (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
1537       (is_depthstencil_format(internalFormat) != is_depthstencil_format(format)) ||
1538       (is_dudv_format(internalFormat) != is_dudv_format(format))) {
1539      if (!isProxy)
1540         _mesa_error(ctx, GL_INVALID_OPERATION,
1541                     "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
1542                     dimensions, internalFormat, format);
1543      return GL_TRUE;
1544   }
1545
1546   /* additional checks for ycbcr textures */
1547   if (internalFormat == GL_YCBCR_MESA) {
1548      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1549      if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1550          type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1551         char message[100];
1552         _mesa_sprintf(message,
1553                 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1554         _mesa_error(ctx, GL_INVALID_ENUM, message);
1555         return GL_TRUE; /* error */
1556      }
1557      if (target != GL_TEXTURE_2D &&
1558          target != GL_PROXY_TEXTURE_2D &&
1559          target != GL_TEXTURE_RECTANGLE_NV &&
1560          target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1561         if (!isProxy)
1562            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1563         return GL_TRUE;
1564      }
1565      if (border != 0) {
1566         if (!isProxy) {
1567            char message[100];
1568            _mesa_sprintf(message,
1569                    "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1570                    dimensions, border);
1571            _mesa_error(ctx, GL_INVALID_VALUE, message);
1572         }
1573         return GL_TRUE;
1574      }
1575   }
1576
1577   /* additional checks for depth textures */
1578   if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1579      /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1580      if (target != GL_TEXTURE_1D &&
1581          target != GL_PROXY_TEXTURE_1D &&
1582          target != GL_TEXTURE_2D &&
1583          target != GL_PROXY_TEXTURE_2D &&
1584          target != GL_TEXTURE_RECTANGLE_ARB &&
1585          target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
1586         if (!isProxy)
1587            _mesa_error(ctx, GL_INVALID_ENUM,
1588                        "glTexImage(target/internalFormat)");
1589         return GL_TRUE;
1590      }
1591   }
1592
1593   /* additional checks for compressed textures */
1594   if (is_compressed_format(ctx, internalFormat)) {
1595      if (!target_can_be_compressed(ctx, target) && !isProxy) {
1596         _mesa_error(ctx, GL_INVALID_ENUM,
1597                     "glTexImage%d(target)", dimensions);
1598         return GL_TRUE;
1599      }
1600      if (border != 0) {
1601         if (!isProxy) {
1602            _mesa_error(ctx, GL_INVALID_OPERATION,
1603                        "glTexImage%D(border!=0)", dimensions);
1604         }
1605         return GL_TRUE;
1606      }
1607   }
1608
1609   /* if we get here, the parameters are OK */
1610   return GL_FALSE;
1611}
1612
1613
1614/**
1615 * Test glTexSubImage[123]D() parameters for errors.
1616 *
1617 * \param ctx GL context.
1618 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1619 * \param target texture target given by the user.
1620 * \param level image level given by the user.
1621 * \param xoffset sub-image x offset given by the user.
1622 * \param yoffset sub-image y offset given by the user.
1623 * \param zoffset sub-image z offset given by the user.
1624 * \param format pixel data format given by the user.
1625 * \param type pixel data type given by the user.
1626 * \param width image width given by the user.
1627 * \param height image height given by the user.
1628 * \param depth image depth given by the user.
1629 *
1630 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1631 *
1632 * Verifies each of the parameters against the constants specified in
1633 * __GLcontextRec::Const and the supported extensions, and according to the
1634 * OpenGL specification.
1635 */
1636static GLboolean
1637subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1638                        GLenum target, GLint level,
1639                        GLint xoffset, GLint yoffset, GLint zoffset,
1640                        GLint width, GLint height, GLint depth,
1641                        GLenum format, GLenum type )
1642{
1643   /* Check target */
1644   if (dimensions == 1) {
1645      if (target != GL_TEXTURE_1D) {
1646         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1647         return GL_TRUE;
1648      }
1649   }
1650   else if (dimensions == 2) {
1651      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1652          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1653         if (!ctx->Extensions.ARB_texture_cube_map) {
1654            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1655            return GL_TRUE;
1656         }
1657      }
1658      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1659         if (!ctx->Extensions.NV_texture_rectangle) {
1660            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1661            return GL_TRUE;
1662         }
1663      }
1664      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1665        if (!ctx->Extensions.MESA_texture_array) {
1666           _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1667           return GL_TRUE;
1668        }
1669      }
1670      else if (target != GL_TEXTURE_2D) {
1671         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1672         return GL_TRUE;
1673      }
1674   }
1675   else if (dimensions == 3) {
1676      if (target == GL_TEXTURE_2D_ARRAY_EXT) {
1677         if (!ctx->Extensions.MESA_texture_array) {
1678            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1679            return GL_TRUE;
1680         }
1681      }
1682      else if (target != GL_TEXTURE_3D) {
1683         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1684         return GL_TRUE;
1685      }
1686   }
1687   else {
1688      _mesa_problem( ctx, "invalid dims in texture_error_check" );
1689      return GL_TRUE;
1690   }
1691
1692   /* Basic level check */
1693   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1694      _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1695      return GL_TRUE;
1696   }
1697
1698   if (width < 0) {
1699      _mesa_error(ctx, GL_INVALID_VALUE,
1700                  "glTexSubImage%dD(width=%d)", dimensions, width);
1701      return GL_TRUE;
1702   }
1703   if (height < 0 && dimensions > 1) {
1704      _mesa_error(ctx, GL_INVALID_VALUE,
1705                  "glTexSubImage%dD(height=%d)", dimensions, height);
1706      return GL_TRUE;
1707   }
1708   if (depth < 0 && dimensions > 2) {
1709      _mesa_error(ctx, GL_INVALID_VALUE,
1710                  "glTexSubImage%dD(depth=%d)", dimensions, depth);
1711      return GL_TRUE;
1712   }
1713
1714   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1715      _mesa_error(ctx, GL_INVALID_ENUM,
1716                  "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
1717                  dimensions, format, type);
1718      return GL_TRUE;
1719   }
1720
1721   return GL_FALSE;
1722}
1723
1724static GLboolean
1725subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
1726			 GLenum target, GLint level,
1727			 GLint xoffset, GLint yoffset, GLint zoffset,
1728			 GLint width, GLint height, GLint depth,
1729			 GLenum format, GLenum type,
1730			 const struct gl_texture_image *destTex )
1731{
1732   if (!destTex) {
1733      /* undefined image level */
1734      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
1735      return GL_TRUE;
1736   }
1737
1738   if (xoffset < -((GLint)destTex->Border)) {
1739      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
1740                  dimensions);
1741      return GL_TRUE;
1742   }
1743   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1744      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
1745                  dimensions);
1746      return GL_TRUE;
1747   }
1748   if (dimensions > 1) {
1749      if (yoffset < -((GLint)destTex->Border)) {
1750         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
1751                     dimensions);
1752         return GL_TRUE;
1753      }
1754      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1755         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
1756                     dimensions);
1757         return GL_TRUE;
1758      }
1759   }
1760   if (dimensions > 2) {
1761      if (zoffset < -((GLint)destTex->Border)) {
1762         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1763         return GL_TRUE;
1764      }
1765      if (zoffset + depth  > (GLint) (destTex->Depth + destTex->Border)) {
1766         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1767         return GL_TRUE;
1768      }
1769   }
1770
1771#if FEATURE_EXT_texture_sRGB
1772   if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
1773       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
1774       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
1775       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
1776      if ((width & 0x3) || (height & 0x3) ||
1777          (xoffset & 0x3) || (yoffset & 0x3))
1778         _mesa_error(ctx, GL_INVALID_OPERATION,
1779                     "glTexSubImage%dD(size or offset not multiple of 4)",
1780                     dimensions);
1781      return GL_TRUE;
1782   }
1783#endif
1784
1785   if (destTex->IsCompressed) {
1786      if (!target_can_be_compressed(ctx, target)) {
1787         _mesa_error(ctx, GL_INVALID_ENUM,
1788                     "glTexSubImage%D(target)", dimensions);
1789         return GL_TRUE;
1790      }
1791      /* offset must be multiple of 4 */
1792      if ((xoffset & 3) || (yoffset & 3)) {
1793         _mesa_error(ctx, GL_INVALID_OPERATION,
1794                     "glTexSubImage%D(xoffset or yoffset)", dimensions);
1795         return GL_TRUE;
1796      }
1797      /* size must be multiple of 4 or equal to whole texture size */
1798      if ((width & 3) && (GLuint) width != destTex->Width) {
1799         _mesa_error(ctx, GL_INVALID_OPERATION,
1800                     "glTexSubImage%D(width)", dimensions);
1801         return GL_TRUE;
1802      }
1803      if ((height & 3) && (GLuint) height != destTex->Height) {
1804         _mesa_error(ctx, GL_INVALID_OPERATION,
1805                     "glTexSubImage%D(width)", dimensions);
1806         return GL_TRUE;
1807      }
1808   }
1809
1810   return GL_FALSE;
1811}
1812
1813
1814/**
1815 * Test glCopyTexImage[12]D() parameters for errors.
1816 *
1817 * \param ctx GL context.
1818 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1819 * \param target texture target given by the user.
1820 * \param level image level given by the user.
1821 * \param internalFormat internal format given by the user.
1822 * \param width image width given by the user.
1823 * \param height image height given by the user.
1824 * \param border texture border.
1825 *
1826 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1827 *
1828 * Verifies each of the parameters against the constants specified in
1829 * __GLcontextRec::Const and the supported extensions, and according to the
1830 * OpenGL specification.
1831 */
1832static GLboolean
1833copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1834                         GLenum target, GLint level, GLint internalFormat,
1835                         GLint width, GLint height, GLint border )
1836{
1837   GLenum type;
1838   GLboolean sizeOK;
1839   GLint format;
1840
1841   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1842   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1843      _mesa_error(ctx, GL_INVALID_VALUE,
1844                  "glCopyTexImage%dD(level=%d)", dimensions, level);
1845      return GL_TRUE;
1846   }
1847
1848   /* Check that the source buffer is complete */
1849   if (ctx->ReadBuffer->Name) {
1850      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1851      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1852         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1853                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1854         return GL_TRUE;
1855      }
1856   }
1857
1858   /* Check border */
1859   if (border < 0 || border > 1 ||
1860       ((target == GL_TEXTURE_RECTANGLE_NV ||
1861         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1862      return GL_TRUE;
1863   }
1864
1865   format = _mesa_base_tex_format(ctx, internalFormat);
1866   if (format < 0) {
1867      _mesa_error(ctx, GL_INVALID_VALUE,
1868                  "glCopyTexImage%dD(internalFormat)", dimensions);
1869      return GL_TRUE;
1870   }
1871
1872   /* NOTE: the format and type aren't really significant for
1873    * TestProxyTexImage().  Only the internalformat really matters.
1874   if (!_mesa_source_buffer_exists(ctx, format)) {
1875      _mesa_error(ctx, GL_INVALID_OPERATION,
1876                  "glCopyTexImage%dD(missing readbuffer)", dimensions);
1877      return GL_TRUE;
1878   }
1879
1880    */
1881   type = GL_FLOAT;
1882
1883   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1884    * level, width, height and depth.
1885    */
1886   if (dimensions == 1) {
1887      if (target == GL_TEXTURE_1D) {
1888         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1889                                                level, internalFormat,
1890                                                format, type,
1891                                                width, 1, 1, border);
1892      }
1893      else {
1894         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1895         return GL_TRUE;
1896      }
1897   }
1898   else if (dimensions == 2) {
1899      if (target == GL_TEXTURE_2D) {
1900         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1901                                                level, internalFormat,
1902                                                format, type,
1903                                                width, height, 1, border);
1904      }
1905      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1906               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1907         if (!ctx->Extensions.ARB_texture_cube_map) {
1908            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1909            return GL_TRUE;
1910         }
1911         sizeOK = (width == height) &&
1912            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1913                                          level, internalFormat, format, type,
1914                                          width, height, 1, border);
1915      }
1916      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1917         if (!ctx->Extensions.NV_texture_rectangle) {
1918            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1919            return GL_TRUE;
1920         }
1921         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1922                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
1923                                                level, internalFormat,
1924                                                format, type,
1925                                                width, height, 1, border);
1926      }
1927      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1928         if (!ctx->Extensions.MESA_texture_array) {
1929            _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
1930            return GL_TRUE;
1931         }
1932         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1933                                                GL_PROXY_TEXTURE_1D_ARRAY_EXT,
1934                                                level, internalFormat,
1935                                                format, type,
1936                                                width, height, 1, border);
1937      }
1938      else {
1939         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1940         return GL_TRUE;
1941      }
1942   }
1943   else {
1944      _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1945      return GL_TRUE;
1946   }
1947
1948   if (!sizeOK) {
1949      if (dimensions == 1) {
1950         _mesa_error(ctx, GL_INVALID_VALUE,
1951                     "glCopyTexImage1D(width=%d)", width);
1952      }
1953      else {
1954         ASSERT(dimensions == 2);
1955         _mesa_error(ctx, GL_INVALID_VALUE,
1956                     "glCopyTexImage2D(width=%d, height=%d)", width, height);
1957      }
1958      return GL_TRUE;
1959   }
1960
1961   if (is_compressed_format(ctx, internalFormat)) {
1962      if (!target_can_be_compressed(ctx, target)) {
1963         _mesa_error(ctx, GL_INVALID_ENUM,
1964                     "glCopyTexImage%d(target)", dimensions);
1965         return GL_TRUE;
1966      }
1967      if (border != 0) {
1968         _mesa_error(ctx, GL_INVALID_OPERATION,
1969                     "glCopyTexImage%D(border!=0)", dimensions);
1970         return GL_TRUE;
1971      }
1972   }
1973   else if (is_depth_format(internalFormat)) {
1974      /* make sure we have depth/stencil buffers */
1975      if (!ctx->ReadBuffer->_DepthBuffer) {
1976         _mesa_error(ctx, GL_INVALID_OPERATION,
1977                     "glCopyTexImage%D(no depth)", dimensions);
1978         return GL_TRUE;
1979      }
1980   }
1981   else if (is_depthstencil_format(internalFormat)) {
1982      /* make sure we have depth/stencil buffers */
1983      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1984         _mesa_error(ctx, GL_INVALID_OPERATION,
1985                     "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
1986         return GL_TRUE;
1987      }
1988   }
1989
1990   /* if we get here, the parameters are OK */
1991   return GL_FALSE;
1992}
1993
1994
1995/**
1996 * Test glCopyTexSubImage[12]D() parameters for errors.
1997 * Note that this is the first part of error checking.
1998 * See also copytexsubimage_error_check2() below for the second part.
1999 *
2000 * \param ctx GL context.
2001 * \param dimensions texture image dimensions (must be 1, 2 or 3).
2002 * \param target texture target given by the user.
2003 * \param level image level given by the user.
2004 *
2005 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
2006 */
2007static GLboolean
2008copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
2009                              GLenum target, GLint level)
2010{
2011   /* Check that the source buffer is complete */
2012   if (ctx->ReadBuffer->Name) {
2013      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
2014      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2015         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
2016                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
2017         return GL_TRUE;
2018      }
2019   }
2020
2021   /* Check target */
2022   if (dimensions == 1) {
2023      if (target != GL_TEXTURE_1D) {
2024         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
2025         return GL_TRUE;
2026      }
2027   }
2028   else if (dimensions == 2) {
2029      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2030          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2031         if (!ctx->Extensions.ARB_texture_cube_map) {
2032            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2033            return GL_TRUE;
2034         }
2035      }
2036      else if (target == GL_TEXTURE_RECTANGLE_NV) {
2037         if (!ctx->Extensions.NV_texture_rectangle) {
2038            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2039            return GL_TRUE;
2040         }
2041      }
2042      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
2043         if (!ctx->Extensions.MESA_texture_array) {
2044            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2045            return GL_TRUE;
2046         }
2047      }
2048      else if (target != GL_TEXTURE_2D) {
2049         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2050         return GL_TRUE;
2051      }
2052   }
2053   else if (dimensions == 3) {
2054      if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
2055	   (!ctx->Extensions.MESA_texture_array))
2056	  && (target != GL_TEXTURE_3D)) {
2057	 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
2058	 return GL_TRUE;
2059      }
2060   }
2061
2062   /* Check level */
2063   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
2064      _mesa_error(ctx, GL_INVALID_VALUE,
2065                  "glCopyTexSubImage%dD(level=%d)", dimensions, level);
2066      return GL_TRUE;
2067   }
2068
2069   return GL_FALSE;
2070}
2071
2072
2073/**
2074 * Second part of error checking for glCopyTexSubImage[12]D().
2075 * \param xoffset sub-image x offset given by the user.
2076 * \param yoffset sub-image y offset given by the user.
2077 * \param zoffset sub-image z offset given by the user.
2078 * \param width image width given by the user.
2079 * \param height image height given by the user.
2080 */
2081static GLboolean
2082copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
2083			      GLenum target, GLint level,
2084			      GLint xoffset, GLint yoffset, GLint zoffset,
2085			      GLsizei width, GLsizei height,
2086			      const struct gl_texture_image *teximage )
2087{
2088   /* check that dest tex image exists */
2089   if (!teximage) {
2090      _mesa_error(ctx, GL_INVALID_OPERATION,
2091                  "glCopyTexSubImage%dD(undefined texture level: %d)",
2092                  dimensions, level);
2093      return GL_TRUE;
2094   }
2095
2096   /* Check size */
2097   if (width < 0) {
2098      _mesa_error(ctx, GL_INVALID_VALUE,
2099                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
2100      return GL_TRUE;
2101   }
2102   if (dimensions > 1 && height < 0) {
2103      _mesa_error(ctx, GL_INVALID_VALUE,
2104                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
2105      return GL_TRUE;
2106   }
2107
2108   /* check x/y offsets */
2109   if (xoffset < -((GLint)teximage->Border)) {
2110      _mesa_error(ctx, GL_INVALID_VALUE,
2111                  "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
2112      return GL_TRUE;
2113   }
2114   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
2115      _mesa_error(ctx, GL_INVALID_VALUE,
2116                  "glCopyTexSubImage%dD(xoffset+width)", dimensions);
2117      return GL_TRUE;
2118   }
2119   if (dimensions > 1) {
2120      if (yoffset < -((GLint)teximage->Border)) {
2121         _mesa_error(ctx, GL_INVALID_VALUE,
2122                     "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
2123         return GL_TRUE;
2124      }
2125      /* NOTE: we're adding the border here, not subtracting! */
2126      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
2127         _mesa_error(ctx, GL_INVALID_VALUE,
2128                     "glCopyTexSubImage%dD(yoffset+height)", dimensions);
2129         return GL_TRUE;
2130      }
2131   }
2132
2133   /* check z offset */
2134   if (dimensions > 2) {
2135      if (zoffset < -((GLint)teximage->Border)) {
2136         _mesa_error(ctx, GL_INVALID_VALUE,
2137                     "glCopyTexSubImage%dD(zoffset)", dimensions);
2138         return GL_TRUE;
2139      }
2140      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
2141         _mesa_error(ctx, GL_INVALID_VALUE,
2142                     "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
2143         return GL_TRUE;
2144      }
2145   }
2146
2147   if (teximage->IsCompressed) {
2148      if (!target_can_be_compressed(ctx, target)) {
2149         _mesa_error(ctx, GL_INVALID_ENUM,
2150                     "glCopyTexSubImage%d(target)", dimensions);
2151         return GL_TRUE;
2152      }
2153      /* offset must be multiple of 4 */
2154      if ((xoffset & 3) || (yoffset & 3)) {
2155         _mesa_error(ctx, GL_INVALID_VALUE,
2156                     "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
2157         return GL_TRUE;
2158      }
2159      /* size must be multiple of 4 */
2160      if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
2161         _mesa_error(ctx, GL_INVALID_VALUE,
2162                     "glCopyTexSubImage%D(width)", dimensions);
2163         return GL_TRUE;
2164      }
2165      if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
2166         _mesa_error(ctx, GL_INVALID_VALUE,
2167                     "glCopyTexSubImage%D(height)", dimensions);
2168         return GL_TRUE;
2169      }
2170   }
2171
2172   if (teximage->InternalFormat == GL_YCBCR_MESA) {
2173      _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
2174      return GL_TRUE;
2175   }
2176
2177   if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
2178      _mesa_error(ctx, GL_INVALID_OPERATION,
2179                  "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
2180                  dimensions, teximage->_BaseFormat);
2181      return GL_TRUE;
2182   }
2183
2184   if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
2185      if (!ctx->ReadBuffer->_DepthBuffer) {
2186         _mesa_error(ctx, GL_INVALID_OPERATION,
2187                     "glCopyTexSubImage%D(no depth buffer)",
2188                     dimensions);
2189         return GL_TRUE;
2190      }
2191   }
2192   else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
2193      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
2194         _mesa_error(ctx, GL_INVALID_OPERATION,
2195                     "glCopyTexSubImage%D(no depth/stencil buffer)",
2196                     dimensions);
2197         return GL_TRUE;
2198      }
2199   }
2200
2201   /* if we get here, the parameters are OK */
2202   return GL_FALSE;
2203}
2204
2205
2206/**
2207 * Do error checking for a glGetTexImage() call.
2208 * \return GL_TRUE if any error, GL_FALSE if no errors.
2209 */
2210static GLboolean
2211getteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
2212                        GLenum format, GLenum type, GLvoid *pixels )
2213{
2214   const struct gl_texture_unit *texUnit;
2215   struct gl_texture_object *texObj;
2216   struct gl_texture_image *texImage;
2217   const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
2218
2219   ASSERT(maxLevels > 0);  /* 0 indicates bad target, caught above */
2220
2221   if (level < 0 || level >= maxLevels) {
2222      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2223      return GL_TRUE;
2224   }
2225
2226   if (_mesa_sizeof_packed_type(type) <= 0) {
2227      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2228      return GL_TRUE;
2229   }
2230
2231   if (_mesa_components_in_format(format) <= 0 ||
2232       format == GL_STENCIL_INDEX) {
2233      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2234      return GL_TRUE;
2235   }
2236
2237   if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
2238      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2239      return GL_TRUE;
2240   }
2241
2242   if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
2243      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2244      return GL_TRUE;
2245   }
2246
2247   if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
2248      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2249      return GL_TRUE;
2250   }
2251
2252   if (!ctx->Extensions.EXT_packed_depth_stencil
2253       && is_depthstencil_format(format)) {
2254      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2255      return GL_TRUE;
2256   }
2257
2258   if (!ctx->Extensions.ATI_envmap_bumpmap
2259       && is_dudv_format(format)) {
2260      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2261      return GL_TRUE;
2262   }
2263
2264
2265   texUnit = get_current_tex_unit(ctx);
2266   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2267   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2268   if (!texImage) {
2269      /* out of memory */
2270      return GL_TRUE;
2271   }
2272
2273   /* Make sure the requested image format is compatible with the
2274    * texture's format.  Note that a color index texture can be converted
2275    * to RGBA so that combo is allowed.
2276    */
2277   if (_mesa_is_color_format(format)
2278       && !_mesa_is_color_format(texImage->TexFormat->BaseFormat)
2279       && !is_index_format(texImage->TexFormat->BaseFormat)) {
2280      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2281      return GL_TRUE;
2282   }
2283   else if (is_index_format(format)
2284            && !is_index_format(texImage->TexFormat->BaseFormat)) {
2285      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2286      return GL_TRUE;
2287   }
2288   else if (is_depth_format(format)
2289            && !is_depth_format(texImage->TexFormat->BaseFormat)
2290            && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2291      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2292      return GL_TRUE;
2293   }
2294   else if (is_ycbcr_format(format)
2295            && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
2296      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2297      return GL_TRUE;
2298   }
2299   else if (is_depthstencil_format(format)
2300            && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2301      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2302      return GL_TRUE;
2303   }
2304   else if (is_dudv_format(format)
2305            && !is_dudv_format(texImage->TexFormat->BaseFormat)) {
2306      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2307      return GL_TRUE;
2308   }
2309
2310   if (ctx->Pack.BufferObj->Name) {
2311      /* packing texture image into a PBO */
2312      const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
2313      if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
2314                                     texImage->Height, texImage->Depth,
2315                                     format, type, pixels)) {
2316         _mesa_error(ctx, GL_INVALID_OPERATION,
2317                     "glGetTexImage(invalid PBO access)");
2318         return GL_TRUE;
2319      }
2320   }
2321
2322   return GL_FALSE;
2323}
2324
2325
2326
2327/**
2328 * Get texture image.  Called by glGetTexImage.
2329 *
2330 * \param target texture target.
2331 * \param level image level.
2332 * \param format pixel data format for returned image.
2333 * \param type pixel data type for returned image.
2334 * \param pixels returned pixel data.
2335 */
2336void GLAPIENTRY
2337_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2338                   GLenum type, GLvoid *pixels )
2339{
2340   const struct gl_texture_unit *texUnit;
2341   struct gl_texture_object *texObj;
2342   GET_CURRENT_CONTEXT(ctx);
2343   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2344
2345   texUnit = get_current_tex_unit(ctx);
2346   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2347   if (!texObj || _mesa_is_proxy_texture(target)) {
2348      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2349      return;
2350   }
2351
2352   if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
2353      return;
2354   }
2355
2356   _mesa_lock_texture(ctx, texObj);
2357   {
2358      struct gl_texture_image *texImage =
2359         _mesa_select_tex_image(ctx, texObj, target, level);
2360
2361      /* typically, this will call _mesa_get_teximage() */
2362      ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
2363                              texObj, texImage);
2364   }
2365   _mesa_unlock_texture(ctx, texObj);
2366}
2367
2368
2369/** Callback info for walking over FBO hash table */
2370struct cb_info
2371{
2372   GLcontext *ctx;
2373   struct gl_texture_object *texObj;
2374   GLuint level, face;
2375};
2376
2377
2378/**
2379 * Check render to texture callback.  Called from _mesa_HashWalk().
2380 */
2381static void
2382check_rtt_cb(GLuint key, void *data, void *userData)
2383{
2384   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2385   const struct cb_info *info = (struct cb_info *) userData;
2386   GLcontext *ctx = info->ctx;
2387   const struct gl_texture_object *texObj = info->texObj;
2388   const GLuint level = info->level, face = info->face;
2389
2390   /* If this is a user-created FBO */
2391   if (fb->Name) {
2392      GLuint i;
2393      /* check if any of the FBO's attachments point to 'texObj' */
2394      for (i = 0; i < BUFFER_COUNT; i++) {
2395         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2396         if (att->Type == GL_TEXTURE &&
2397             att->Texture == texObj &&
2398             att->TextureLevel == level &&
2399             att->CubeMapFace == face) {
2400            ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
2401            /* Tell driver about the new renderbuffer texture */
2402            ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
2403            /* Mark fb status as indeterminate to force re-validation */
2404            fb->_Status = 0;
2405         }
2406      }
2407   }
2408}
2409
2410
2411/**
2412 * When a texture image is specified we have to check if it's bound to
2413 * any framebuffer objects (render to texture) in order to detect changes
2414 * in size or format since that effects FBO completeness.
2415 * Any FBOs rendering into the texture must be re-validated.
2416 */
2417static void
2418update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
2419                   GLuint face, GLuint level)
2420{
2421   /* Only check this texture if it's been marked as RenderToTexture */
2422   if (texObj->_RenderToTexture) {
2423      struct cb_info info;
2424      info.ctx = ctx;
2425      info.texObj = texObj;
2426      info.level = level;
2427      info.face = face;
2428      _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
2429   }
2430}
2431
2432
2433/** Debug helper: override the user-requested internal format */
2434static GLenum
2435override_internal_format(GLenum internalFormat, GLint width, GLint height)
2436{
2437#if 0
2438   if (internalFormat == GL_RGBA16F_ARB ||
2439       internalFormat == GL_RGBA32F_ARB) {
2440      printf("Convert rgba float tex to int %d x %d\n", width, height);
2441      return GL_RGBA;
2442   }
2443   else if (internalFormat == GL_RGB16F_ARB ||
2444            internalFormat == GL_RGB32F_ARB) {
2445      printf("Convert rgb float tex to int %d x %d\n", width, height);
2446      return GL_RGB;
2447   }
2448   else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
2449            internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
2450      printf("Convert luminance float tex to int %d x %d\n", width, height);
2451      return GL_LUMINANCE_ALPHA;
2452   }
2453   else if (internalFormat == GL_LUMINANCE16F_ARB ||
2454            internalFormat == GL_LUMINANCE32F_ARB) {
2455      printf("Convert luminance float tex to int %d x %d\n", width, height);
2456      return GL_LUMINANCE;
2457   }
2458   else if (internalFormat == GL_ALPHA16F_ARB ||
2459            internalFormat == GL_ALPHA32F_ARB) {
2460      printf("Convert luminance float tex to int %d x %d\n", width, height);
2461      return GL_ALPHA;
2462   }
2463   /*
2464   else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
2465      internalFormat = GL_RGBA;
2466   }
2467   */
2468   else {
2469      return internalFormat;
2470   }
2471#else
2472   return internalFormat;
2473#endif
2474}
2475
2476
2477/*
2478 * Called from the API.  Note that width includes the border.
2479 */
2480void GLAPIENTRY
2481_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2482                  GLsizei width, GLint border, GLenum format,
2483                  GLenum type, const GLvoid *pixels )
2484{
2485   GLsizei postConvWidth = width;
2486   GET_CURRENT_CONTEXT(ctx);
2487   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2488
2489   internalFormat = override_internal_format(internalFormat, width, 1);
2490
2491#if FEATURE_convolve
2492   if (_mesa_is_color_format(internalFormat)) {
2493      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2494   }
2495#endif
2496
2497   if (target == GL_TEXTURE_1D) {
2498      /* non-proxy target */
2499      struct gl_texture_unit *texUnit;
2500      struct gl_texture_object *texObj;
2501      struct gl_texture_image *texImage;
2502      const GLuint face = _mesa_tex_target_to_face(target);
2503
2504      if (texture_error_check(ctx, target, level, internalFormat,
2505                              format, type, 1, postConvWidth, 1, 1, border)) {
2506         return;   /* error was recorded */
2507      }
2508
2509      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2510	 _mesa_update_state(ctx);
2511
2512      texUnit = get_current_tex_unit(ctx);
2513      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2514      _mesa_lock_texture(ctx, texObj);
2515      {
2516	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2517	 if (!texImage) {
2518	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2519	    goto out;
2520	 }
2521
2522	 if (texImage->Data) {
2523	    ctx->Driver.FreeTexImageData( ctx, texImage );
2524	 }
2525
2526	 ASSERT(texImage->Data == NULL);
2527
2528	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2529	 _mesa_init_teximage_fields(ctx, target, texImage,
2530				    postConvWidth, 1, 1,
2531				    border, internalFormat);
2532
2533	 ASSERT(ctx->Driver.TexImage1D);
2534
2535	 /* Give the texture to the driver!  <pixels> may be null! */
2536	 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
2537				   width, border, format, type, pixels,
2538				   &ctx->Unpack, texObj, texImage);
2539
2540	 ASSERT(texImage->TexFormat);
2541
2542	 update_fbo_texture(ctx, texObj, face, level);
2543
2544	 /* state update */
2545	 texObj->_Complete = GL_FALSE;
2546	 ctx->NewState |= _NEW_TEXTURE;
2547      }
2548   out:
2549      _mesa_unlock_texture(ctx, texObj);
2550   }
2551   else if (target == GL_PROXY_TEXTURE_1D) {
2552      /* Proxy texture: check for errors and update proxy state */
2553      struct gl_texture_image *texImage;
2554      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2555      if (texture_error_check(ctx, target, level, internalFormat,
2556                              format, type, 1, postConvWidth, 1, 1, border)) {
2557         /* when error, clear all proxy texture image parameters */
2558         if (texImage)
2559            clear_teximage_fields(texImage);
2560      }
2561      else {
2562         /* no error, set the tex image parameters */
2563         ASSERT(texImage);
2564         _mesa_init_teximage_fields(ctx, target, texImage,
2565                                    postConvWidth, 1, 1,
2566                                    border, internalFormat);
2567         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2568                                          internalFormat, format, type);
2569      }
2570   }
2571   else {
2572      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2573      return;
2574   }
2575}
2576
2577
2578void GLAPIENTRY
2579_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2580                  GLsizei width, GLsizei height, GLint border,
2581                  GLenum format, GLenum type,
2582                  const GLvoid *pixels )
2583{
2584   GLsizei postConvWidth = width, postConvHeight = height;
2585   GET_CURRENT_CONTEXT(ctx);
2586   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2587
2588   internalFormat = override_internal_format(internalFormat, width, height);
2589
2590#if FEATURE_convolve
2591   if (_mesa_is_color_format(internalFormat)) {
2592      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2593					 &postConvHeight);
2594   }
2595#endif
2596
2597   if (target == GL_TEXTURE_2D ||
2598       (ctx->Extensions.ARB_texture_cube_map &&
2599        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2600        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2601       (ctx->Extensions.NV_texture_rectangle &&
2602        target == GL_TEXTURE_RECTANGLE_NV) ||
2603       (ctx->Extensions.MESA_texture_array &&
2604        target == GL_TEXTURE_1D_ARRAY_EXT)) {
2605      /* non-proxy target */
2606      struct gl_texture_unit *texUnit;
2607      struct gl_texture_object *texObj;
2608      struct gl_texture_image *texImage;
2609      const GLuint face = _mesa_tex_target_to_face(target);
2610
2611      if (texture_error_check(ctx, target, level, internalFormat,
2612                              format, type, 2, postConvWidth, postConvHeight,
2613                              1, border)) {
2614         return;   /* error was recorded */
2615      }
2616
2617      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2618	 _mesa_update_state(ctx);
2619
2620      texUnit = get_current_tex_unit(ctx);
2621      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2622      _mesa_lock_texture(ctx, texObj);
2623      {
2624	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2625	 if (!texImage) {
2626	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2627	    goto out;
2628	 }
2629
2630	 if (texImage->Data) {
2631	    ctx->Driver.FreeTexImageData( ctx, texImage );
2632	 }
2633
2634	 ASSERT(texImage->Data == NULL);
2635	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2636	 _mesa_init_teximage_fields(ctx, target, texImage,
2637				    postConvWidth, postConvHeight, 1,
2638				    border, internalFormat);
2639
2640	 ASSERT(ctx->Driver.TexImage2D);
2641
2642	 /* Give the texture to the driver!  <pixels> may be null! */
2643	 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
2644				   width, height, border, format, type, pixels,
2645				   &ctx->Unpack, texObj, texImage);
2646
2647	 ASSERT(texImage->TexFormat);
2648
2649	 update_fbo_texture(ctx, texObj, face, level);
2650
2651	 /* state update */
2652	 texObj->_Complete = GL_FALSE;
2653	 ctx->NewState |= _NEW_TEXTURE;
2654      }
2655   out:
2656      _mesa_unlock_texture(ctx, texObj);
2657   }
2658   else if (target == GL_PROXY_TEXTURE_2D ||
2659            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2660             ctx->Extensions.ARB_texture_cube_map) ||
2661            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2662             ctx->Extensions.NV_texture_rectangle) ||
2663            (ctx->Extensions.MESA_texture_array &&
2664             target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
2665      /* Proxy texture: check for errors and update proxy state */
2666      struct gl_texture_image *texImage;
2667      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2668      if (texture_error_check(ctx, target, level, internalFormat,
2669                              format, type, 2, postConvWidth, postConvHeight,
2670                              1, border)) {
2671         /* when error, clear all proxy texture image parameters */
2672         if (texImage)
2673            clear_teximage_fields(texImage);
2674      }
2675      else {
2676         /* no error, set the tex image parameters */
2677         _mesa_init_teximage_fields(ctx, target, texImage,
2678                                    postConvWidth, postConvHeight, 1,
2679                                    border, internalFormat);
2680         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2681                                          internalFormat, format, type);
2682      }
2683   }
2684   else {
2685      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2686      return;
2687   }
2688}
2689
2690
2691/*
2692 * Called by the API or display list executor.
2693 * Note that width and height include the border.
2694 */
2695void GLAPIENTRY
2696_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2697                  GLsizei width, GLsizei height, GLsizei depth,
2698                  GLint border, GLenum format, GLenum type,
2699                  const GLvoid *pixels )
2700{
2701   GET_CURRENT_CONTEXT(ctx);
2702   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2703
2704   internalFormat = override_internal_format(internalFormat, width, height);
2705
2706   if (target == GL_TEXTURE_3D ||
2707       (ctx->Extensions.MESA_texture_array &&
2708        target == GL_TEXTURE_2D_ARRAY_EXT)) {
2709      /* non-proxy target */
2710      struct gl_texture_unit *texUnit;
2711      struct gl_texture_object *texObj;
2712      struct gl_texture_image *texImage;
2713      const GLuint face = _mesa_tex_target_to_face(target);
2714
2715      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2716                              format, type, 3, width, height, depth, border)) {
2717         return;   /* error was recorded */
2718      }
2719
2720      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2721	 _mesa_update_state(ctx);
2722
2723      texUnit = get_current_tex_unit(ctx);
2724      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2725      _mesa_lock_texture(ctx, texObj);
2726      {
2727	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2728	 if (!texImage) {
2729	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2730	    goto out;
2731	 }
2732
2733	 if (texImage->Data) {
2734	    ctx->Driver.FreeTexImageData( ctx, texImage );
2735	 }
2736
2737	 ASSERT(texImage->Data == NULL);
2738	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2739	 _mesa_init_teximage_fields(ctx, target, texImage,
2740				    width, height, depth,
2741				    border, internalFormat);
2742
2743	 ASSERT(ctx->Driver.TexImage3D);
2744
2745	 /* Give the texture to the driver!  <pixels> may be null! */
2746	 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
2747				   width, height, depth, border, format, type,
2748				   pixels, &ctx->Unpack, texObj, texImage);
2749
2750	 ASSERT(texImage->TexFormat);
2751
2752	 update_fbo_texture(ctx, texObj, face, level);
2753
2754	 /* state update */
2755	 texObj->_Complete = GL_FALSE;
2756	 ctx->NewState |= _NEW_TEXTURE;
2757      }
2758   out:
2759      _mesa_unlock_texture(ctx, texObj);
2760   }
2761   else if (target == GL_PROXY_TEXTURE_3D ||
2762       (ctx->Extensions.MESA_texture_array &&
2763        target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
2764      /* Proxy texture: check for errors and update proxy state */
2765      struct gl_texture_image *texImage;
2766      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2767      if (texture_error_check(ctx, target, level, internalFormat,
2768                              format, type, 3, width, height, depth, border)) {
2769         /* when error, clear all proxy texture image parameters */
2770         if (texImage)
2771            clear_teximage_fields(texImage);
2772      }
2773      else {
2774         /* no error, set the tex image parameters */
2775         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2776                                    depth, border, internalFormat);
2777         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2778                                          internalFormat, format, type);
2779      }
2780   }
2781   else {
2782      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2783      return;
2784   }
2785}
2786
2787
2788void GLAPIENTRY
2789_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2790                     GLsizei width, GLsizei height, GLsizei depth,
2791                     GLint border, GLenum format, GLenum type,
2792                     const GLvoid *pixels )
2793{
2794   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2795                    depth, border, format, type, pixels);
2796}
2797
2798
2799
2800void GLAPIENTRY
2801_mesa_TexSubImage1D( GLenum target, GLint level,
2802                     GLint xoffset, GLsizei width,
2803                     GLenum format, GLenum type,
2804                     const GLvoid *pixels )
2805{
2806   GLsizei postConvWidth = width;
2807   struct gl_texture_unit *texUnit;
2808   struct gl_texture_object *texObj;
2809   struct gl_texture_image *texImage = NULL;
2810   GET_CURRENT_CONTEXT(ctx);
2811   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2812
2813   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2814      _mesa_update_state(ctx);
2815
2816#if FEATURE_convolve
2817   /* XXX should test internal format */
2818   if (_mesa_is_color_format(format)) {
2819      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2820   }
2821#endif
2822
2823   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2824			       postConvWidth, 1, 1, format, type)) {
2825      return;   /* error was detected */
2826   }
2827
2828
2829   texUnit = get_current_tex_unit(ctx);
2830   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2831   assert(texObj);
2832
2833   _mesa_lock_texture(ctx, texObj);
2834   {
2835      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2836
2837      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2838				  postConvWidth, 1, 1, format, type, texImage)) {
2839	 goto out;   /* error was detected */
2840      }
2841
2842      if (width == 0)
2843	 goto out;  /* no-op, not an error */
2844
2845      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2846      xoffset += texImage->Border;
2847
2848      ASSERT(ctx->Driver.TexSubImage1D);
2849      (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
2850				   format, type, pixels, &ctx->Unpack,
2851				   texObj, texImage);
2852      ctx->NewState |= _NEW_TEXTURE;
2853   }
2854 out:
2855   _mesa_unlock_texture(ctx, texObj);
2856}
2857
2858
2859void GLAPIENTRY
2860_mesa_TexSubImage2D( GLenum target, GLint level,
2861                     GLint xoffset, GLint yoffset,
2862                     GLsizei width, GLsizei height,
2863                     GLenum format, GLenum type,
2864                     const GLvoid *pixels )
2865{
2866   GLsizei postConvWidth = width, postConvHeight = height;
2867   struct gl_texture_unit *texUnit;
2868   struct gl_texture_object *texObj;
2869   struct gl_texture_image *texImage;
2870   GET_CURRENT_CONTEXT(ctx);
2871   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2872
2873   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2874      _mesa_update_state(ctx);
2875
2876#if FEATURE_convolve
2877   /* XXX should test internal format */
2878   if (_mesa_is_color_format(format)) {
2879      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2880                                         &postConvHeight);
2881   }
2882#endif
2883
2884   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2885			      postConvWidth, postConvHeight, 1, format, type)) {
2886      return;   /* error was detected */
2887   }
2888
2889   texUnit = get_current_tex_unit(ctx);
2890   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2891   _mesa_lock_texture(ctx, texObj);
2892   {
2893      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2894
2895      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2896				  postConvWidth, postConvHeight, 1, format, type,
2897				  texImage)) {
2898	 goto out;   /* error was detected */
2899      }
2900
2901      if (width == 0 || height == 0)
2902	 goto out;  /* no-op, not an error */
2903
2904      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2905      xoffset += texImage->Border;
2906      yoffset += texImage->Border;
2907
2908      ASSERT(ctx->Driver.TexSubImage2D);
2909      (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2910				   width, height, format, type, pixels,
2911				   &ctx->Unpack, texObj, texImage);
2912      ctx->NewState |= _NEW_TEXTURE;
2913   }
2914 out:
2915   _mesa_unlock_texture(ctx, texObj);
2916}
2917
2918
2919
2920void GLAPIENTRY
2921_mesa_TexSubImage3D( GLenum target, GLint level,
2922                     GLint xoffset, GLint yoffset, GLint zoffset,
2923                     GLsizei width, GLsizei height, GLsizei depth,
2924                     GLenum format, GLenum type,
2925                     const GLvoid *pixels )
2926{
2927   struct gl_texture_unit *texUnit;
2928   struct gl_texture_object *texObj;
2929   struct gl_texture_image *texImage;
2930   GET_CURRENT_CONTEXT(ctx);
2931   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2932
2933   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2934      _mesa_update_state(ctx);
2935
2936   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2937                              width, height, depth, format, type)) {
2938      return;   /* error was detected */
2939   }
2940
2941   texUnit = get_current_tex_unit(ctx);
2942   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2943
2944   _mesa_lock_texture(ctx, texObj);
2945   {
2946      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2947
2948      if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
2949				  width, height, depth, format, type, texImage)) {
2950	 goto out;   /* error was detected */
2951      }
2952
2953      if (width == 0 || height == 0 || height == 0)
2954	 goto out;  /* no-op, not an error */
2955
2956      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2957      xoffset += texImage->Border;
2958      yoffset += texImage->Border;
2959      zoffset += texImage->Border;
2960
2961      ASSERT(ctx->Driver.TexSubImage3D);
2962      (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2963				   xoffset, yoffset, zoffset,
2964				   width, height, depth,
2965				   format, type, pixels,
2966				   &ctx->Unpack, texObj, texImage );
2967      ctx->NewState |= _NEW_TEXTURE;
2968   }
2969 out:
2970   _mesa_unlock_texture(ctx, texObj);
2971}
2972
2973
2974
2975void GLAPIENTRY
2976_mesa_CopyTexImage1D( GLenum target, GLint level,
2977                      GLenum internalFormat,
2978                      GLint x, GLint y,
2979                      GLsizei width, GLint border )
2980{
2981   struct gl_texture_unit *texUnit;
2982   struct gl_texture_object *texObj;
2983   struct gl_texture_image *texImage;
2984   GLsizei postConvWidth = width;
2985   const GLuint face = _mesa_tex_target_to_face(target);
2986   GET_CURRENT_CONTEXT(ctx);
2987   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2988
2989   if (ctx->NewState & NEW_COPY_TEX_STATE)
2990      _mesa_update_state(ctx);
2991
2992#if FEATURE_convolve
2993   if (_mesa_is_color_format(internalFormat)) {
2994      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2995   }
2996#endif
2997
2998   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2999                               postConvWidth, 1, border))
3000      return;
3001
3002   texUnit = get_current_tex_unit(ctx);
3003   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3004   _mesa_lock_texture(ctx, texObj);
3005   {
3006      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3007      if (!texImage) {
3008	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
3009	 goto out;
3010      }
3011
3012      if (texImage->Data) {
3013	 ctx->Driver.FreeTexImageData( ctx, texImage );
3014      }
3015
3016      ASSERT(texImage->Data == NULL);
3017
3018      clear_teximage_fields(texImage); /* not really needed, but helpful */
3019      _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
3020				 border, internalFormat);
3021
3022
3023      ASSERT(ctx->Driver.CopyTexImage1D);
3024      (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
3025				    x, y, width, border);
3026
3027      ASSERT(texImage->TexFormat);
3028
3029      update_fbo_texture(ctx, texObj, face, level);
3030
3031      /* state update */
3032      texObj->_Complete = GL_FALSE;
3033      ctx->NewState |= _NEW_TEXTURE;
3034   }
3035 out:
3036   _mesa_unlock_texture(ctx, texObj);
3037}
3038
3039
3040
3041void GLAPIENTRY
3042_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
3043                      GLint x, GLint y, GLsizei width, GLsizei height,
3044                      GLint border )
3045{
3046   struct gl_texture_unit *texUnit;
3047   struct gl_texture_object *texObj;
3048   struct gl_texture_image *texImage;
3049   GLsizei postConvWidth = width, postConvHeight = height;
3050   const GLuint face = _mesa_tex_target_to_face(target);
3051   GET_CURRENT_CONTEXT(ctx);
3052   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3053
3054   if (ctx->NewState & NEW_COPY_TEX_STATE)
3055      _mesa_update_state(ctx);
3056
3057#if FEATURE_convolve
3058   if (_mesa_is_color_format(internalFormat)) {
3059      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
3060                                         &postConvHeight);
3061   }
3062#endif
3063
3064   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
3065                               postConvWidth, postConvHeight, border))
3066      return;
3067
3068   texUnit = get_current_tex_unit(ctx);
3069   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3070
3071   _mesa_lock_texture(ctx, texObj);
3072   {
3073      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3074
3075      if (!texImage) {
3076	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
3077	 goto out;
3078      }
3079
3080      if (texImage->Data) {
3081	 ctx->Driver.FreeTexImageData( ctx, texImage );
3082      }
3083
3084      ASSERT(texImage->Data == NULL);
3085
3086      clear_teximage_fields(texImage); /* not really needed, but helpful */
3087      _mesa_init_teximage_fields(ctx, target, texImage,
3088				 postConvWidth, postConvHeight, 1,
3089				 border, internalFormat);
3090
3091      ASSERT(ctx->Driver.CopyTexImage2D);
3092      (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
3093				    x, y, width, height, border);
3094
3095      ASSERT(texImage->TexFormat);
3096
3097      update_fbo_texture(ctx, texObj, face, level);
3098
3099      /* state update */
3100      texObj->_Complete = GL_FALSE;
3101      ctx->NewState |= _NEW_TEXTURE;
3102   }
3103 out:
3104   _mesa_unlock_texture(ctx, texObj);
3105}
3106
3107
3108void GLAPIENTRY
3109_mesa_CopyTexSubImage1D( GLenum target, GLint level,
3110                         GLint xoffset, GLint x, GLint y, GLsizei width )
3111{
3112   struct gl_texture_unit *texUnit;
3113   struct gl_texture_object *texObj;
3114   struct gl_texture_image *texImage;
3115   GLsizei postConvWidth = width;
3116   GLint yoffset = 0;
3117   GLsizei height = 1;
3118
3119   GET_CURRENT_CONTEXT(ctx);
3120   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3121
3122   if (ctx->NewState & NEW_COPY_TEX_STATE)
3123      _mesa_update_state(ctx);
3124
3125   if (copytexsubimage_error_check1(ctx, 1, target, level))
3126      return;
3127
3128   texUnit = get_current_tex_unit(ctx);
3129   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3130
3131   _mesa_lock_texture(ctx, texObj);
3132   {
3133      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3134
3135#if FEATURE_convolve
3136      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3137         _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
3138      }
3139#endif
3140
3141      if (copytexsubimage_error_check2(ctx, 1, target, level,
3142				       xoffset, 0, 0, postConvWidth, 1,
3143				       texImage))
3144	 goto out;
3145
3146
3147      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3148      xoffset += texImage->Border;
3149
3150      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3151                                     &width, &height)) {
3152         ASSERT(ctx->Driver.CopyTexSubImage1D);
3153         ctx->Driver.CopyTexSubImage1D(ctx, target, level,
3154                                       xoffset, x, y, width);
3155      }
3156
3157      ctx->NewState |= _NEW_TEXTURE;
3158   }
3159 out:
3160   _mesa_unlock_texture(ctx, texObj);
3161}
3162
3163
3164
3165void GLAPIENTRY
3166_mesa_CopyTexSubImage2D( GLenum target, GLint level,
3167                         GLint xoffset, GLint yoffset,
3168                         GLint x, GLint y, GLsizei width, GLsizei height )
3169{
3170   struct gl_texture_unit *texUnit;
3171   struct gl_texture_object *texObj;
3172   struct gl_texture_image *texImage;
3173   GLsizei postConvWidth = width, postConvHeight = height;
3174   GET_CURRENT_CONTEXT(ctx);
3175   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3176
3177   if (ctx->NewState & NEW_COPY_TEX_STATE)
3178      _mesa_update_state(ctx);
3179
3180   if (copytexsubimage_error_check1(ctx, 2, target, level))
3181      return;
3182
3183   texUnit = get_current_tex_unit(ctx);
3184   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3185
3186   _mesa_lock_texture(ctx, texObj);
3187   {
3188      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3189
3190#if FEATURE_convolve
3191      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3192         _mesa_adjust_image_for_convolution(ctx, 2,
3193                                            &postConvWidth, &postConvHeight);
3194      }
3195#endif
3196
3197      if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
3198				       postConvWidth, postConvHeight, texImage))
3199	 goto out;
3200
3201      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3202      xoffset += texImage->Border;
3203      yoffset += texImage->Border;
3204
3205      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3206                                     &width, &height)) {
3207         ASSERT(ctx->Driver.CopyTexSubImage2D);
3208         ctx->Driver.CopyTexSubImage2D(ctx, target, level,
3209				       xoffset, yoffset, x, y, width, height);
3210      }
3211
3212      ctx->NewState |= _NEW_TEXTURE;
3213   }
3214 out:
3215   _mesa_unlock_texture(ctx, texObj);
3216}
3217
3218
3219
3220void GLAPIENTRY
3221_mesa_CopyTexSubImage3D( GLenum target, GLint level,
3222                         GLint xoffset, GLint yoffset, GLint zoffset,
3223                         GLint x, GLint y, GLsizei width, GLsizei height )
3224{
3225   struct gl_texture_unit *texUnit;
3226   struct gl_texture_object *texObj;
3227   struct gl_texture_image *texImage;
3228   GLsizei postConvWidth = width, postConvHeight = height;
3229   GET_CURRENT_CONTEXT(ctx);
3230   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3231
3232   if (ctx->NewState & NEW_COPY_TEX_STATE)
3233      _mesa_update_state(ctx);
3234
3235   if (copytexsubimage_error_check1(ctx, 3, target, level))
3236      return;
3237
3238   texUnit = get_current_tex_unit(ctx);
3239   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3240
3241   _mesa_lock_texture(ctx, texObj);
3242   {
3243      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3244
3245#if FEATURE_convolve
3246      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3247         _mesa_adjust_image_for_convolution(ctx, 2,
3248                                            &postConvWidth, &postConvHeight);
3249      }
3250#endif
3251
3252      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
3253				       zoffset, postConvWidth, postConvHeight,
3254				       texImage))
3255	 goto out;
3256
3257      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3258      xoffset += texImage->Border;
3259      yoffset += texImage->Border;
3260      zoffset += texImage->Border;
3261
3262      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3263                                     &width, &height)) {
3264         ASSERT(ctx->Driver.CopyTexSubImage3D);
3265         ctx->Driver.CopyTexSubImage3D(ctx, target, level,
3266				       xoffset, yoffset, zoffset,
3267				       x, y, width, height);
3268      }
3269
3270      ctx->NewState |= _NEW_TEXTURE;
3271   }
3272 out:
3273   _mesa_unlock_texture(ctx, texObj);
3274}
3275
3276
3277
3278
3279/**********************************************************************/
3280/******                   Compressed Textures                    ******/
3281/**********************************************************************/
3282
3283
3284/**
3285 * Error checking for glCompressedTexImage[123]D().
3286 * \return error code or GL_NO_ERROR.
3287 */
3288static GLenum
3289compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3290                               GLenum target, GLint level,
3291                               GLenum internalFormat, GLsizei width,
3292                               GLsizei height, GLsizei depth, GLint border,
3293                               GLsizei imageSize)
3294{
3295   GLint expectedSize, maxLevels = 0, maxTextureSize;
3296
3297   if (dimensions == 1) {
3298      /* 1D compressed textures not allowed */
3299      return GL_INVALID_ENUM;
3300   }
3301   else if (dimensions == 2) {
3302      if (target == GL_PROXY_TEXTURE_2D) {
3303         maxLevels = ctx->Const.MaxTextureLevels;
3304      }
3305      else if (target == GL_TEXTURE_2D) {
3306         maxLevels = ctx->Const.MaxTextureLevels;
3307      }
3308      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3309         if (!ctx->Extensions.ARB_texture_cube_map)
3310            return GL_INVALID_ENUM; /*target*/
3311         maxLevels = ctx->Const.MaxCubeTextureLevels;
3312      }
3313      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3314               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3315         if (!ctx->Extensions.ARB_texture_cube_map)
3316            return GL_INVALID_ENUM; /*target*/
3317         maxLevels = ctx->Const.MaxCubeTextureLevels;
3318      }
3319      else {
3320         return GL_INVALID_ENUM; /*target*/
3321      }
3322   }
3323   else if (dimensions == 3) {
3324      /* 3D compressed textures not allowed */
3325      return GL_INVALID_ENUM;
3326   }
3327
3328   maxTextureSize = 1 << (maxLevels - 1);
3329
3330   /* This will detect any invalid internalFormat value */
3331   if (!is_compressed_format(ctx, internalFormat))
3332      return GL_INVALID_ENUM;
3333
3334   /* This should really never fail */
3335   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3336      return GL_INVALID_ENUM;
3337
3338   if (border != 0)
3339      return GL_INVALID_VALUE;
3340
3341   /*
3342    * XXX We should probably use the proxy texture error check function here.
3343    */
3344   if (width < 1 || width > maxTextureSize ||
3345       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
3346      return GL_INVALID_VALUE;
3347
3348   if ((height < 1 || height > maxTextureSize ||
3349       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
3350       && dimensions > 1)
3351      return GL_INVALID_VALUE;
3352
3353   if ((depth < 1 || depth > maxTextureSize ||
3354       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
3355       && dimensions > 2)
3356      return GL_INVALID_VALUE;
3357
3358   /* For cube map, width must equal height */
3359   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3360       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3361      return GL_INVALID_VALUE;
3362
3363   if (level < 0 || level >= maxLevels)
3364      return GL_INVALID_VALUE;
3365
3366   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3367                                                       depth, internalFormat);
3368   if (expectedSize != imageSize)
3369      return GL_INVALID_VALUE;
3370
3371#if FEATURE_EXT_texture_sRGB
3372   if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3373        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3374        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3375        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3376       && border != 0) {
3377      return GL_INVALID_OPERATION;
3378   }
3379#endif
3380
3381   return GL_NO_ERROR;
3382}
3383
3384
3385/**
3386 * Error checking for glCompressedTexSubImage[123]D().
3387 * \warning  There are some bad assumptions here about the size of compressed
3388 *           texture tiles (multiple of 4) used to test the validity of the
3389 *           offset and size parameters.
3390 * \return error code or GL_NO_ERROR.
3391 */
3392static GLenum
3393compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3394                                  GLenum target, GLint level,
3395                                  GLint xoffset, GLint yoffset, GLint zoffset,
3396                                  GLsizei width, GLsizei height, GLsizei depth,
3397                                  GLenum format, GLsizei imageSize)
3398{
3399   GLint expectedSize, maxLevels = 0, maxTextureSize;
3400   (void) zoffset;
3401
3402   if (dimensions == 1) {
3403      /* 1D compressed textures not allowed */
3404      return GL_INVALID_ENUM;
3405   }
3406   else if (dimensions == 2) {
3407      if (target == GL_PROXY_TEXTURE_2D) {
3408         maxLevels = ctx->Const.MaxTextureLevels;
3409      }
3410      else if (target == GL_TEXTURE_2D) {
3411         maxLevels = ctx->Const.MaxTextureLevels;
3412      }
3413      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3414         if (!ctx->Extensions.ARB_texture_cube_map)
3415            return GL_INVALID_ENUM; /*target*/
3416         maxLevels = ctx->Const.MaxCubeTextureLevels;
3417      }
3418      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3419               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3420         if (!ctx->Extensions.ARB_texture_cube_map)
3421            return GL_INVALID_ENUM; /*target*/
3422         maxLevels = ctx->Const.MaxCubeTextureLevels;
3423      }
3424      else {
3425         return GL_INVALID_ENUM; /*target*/
3426      }
3427   }
3428   else if (dimensions == 3) {
3429      /* 3D compressed textures not allowed */
3430      return GL_INVALID_ENUM;
3431   }
3432
3433   maxTextureSize = 1 << (maxLevels - 1);
3434
3435   /* this will catch any invalid compressed format token */
3436   if (!is_compressed_format(ctx, format))
3437      return GL_INVALID_ENUM;
3438
3439   if (width < 1 || width > maxTextureSize)
3440      return GL_INVALID_VALUE;
3441
3442   if ((height < 1 || height > maxTextureSize)
3443       && dimensions > 1)
3444      return GL_INVALID_VALUE;
3445
3446   if (level < 0 || level >= maxLevels)
3447      return GL_INVALID_VALUE;
3448
3449   /* XXX these tests are specific to the compressed format.
3450    * this code should be generalized in some way.
3451    */
3452   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3453      return GL_INVALID_VALUE;
3454
3455   if ((width & 3) != 0 && width != 2 && width != 1)
3456      return GL_INVALID_VALUE;
3457
3458   if ((height & 3) != 0 && height != 2 && height != 1)
3459      return GL_INVALID_VALUE;
3460
3461   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3462                                                       depth, format);
3463   if (expectedSize != imageSize)
3464      return GL_INVALID_VALUE;
3465
3466   return GL_NO_ERROR;
3467}
3468
3469
3470
3471void GLAPIENTRY
3472_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3473                              GLenum internalFormat, GLsizei width,
3474                              GLint border, GLsizei imageSize,
3475                              const GLvoid *data)
3476{
3477   GET_CURRENT_CONTEXT(ctx);
3478   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3479
3480   if (target == GL_TEXTURE_1D) {
3481      /* non-proxy target */
3482      struct gl_texture_unit *texUnit;
3483      struct gl_texture_object *texObj;
3484      struct gl_texture_image *texImage;
3485      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3486                               internalFormat, width, 1, 1, border, imageSize);
3487      if (error) {
3488         _mesa_error(ctx, error, "glCompressedTexImage1D");
3489         return;
3490      }
3491
3492      texUnit = get_current_tex_unit(ctx);
3493      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3494
3495      _mesa_lock_texture(ctx, texObj);
3496      {
3497	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3498	 if (!texImage) {
3499	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3500	    goto out;
3501	 }
3502
3503	 if (texImage->Data) {
3504	    ctx->Driver.FreeTexImageData( ctx, texImage );
3505	 }
3506	 ASSERT(texImage->Data == NULL);
3507
3508	 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3509				    border, internalFormat);
3510
3511	 ASSERT(ctx->Driver.CompressedTexImage1D);
3512	 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
3513					     internalFormat, width, border,
3514					     imageSize, data,
3515					     texObj, texImage);
3516
3517	 /* state update */
3518	 texObj->_Complete = GL_FALSE;
3519	 ctx->NewState |= _NEW_TEXTURE;
3520      }
3521   out:
3522      _mesa_unlock_texture(ctx, texObj);
3523   }
3524   else if (target == GL_PROXY_TEXTURE_1D) {
3525      /* Proxy texture: check for errors and update proxy state */
3526      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3527                               internalFormat, width, 1, 1, border, imageSize);
3528      if (!error) {
3529         ASSERT(ctx->Driver.TestProxyTexImage);
3530         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3531                                             internalFormat, GL_NONE, GL_NONE,
3532                                             width, 1, 1, border);
3533      }
3534      if (error) {
3535         /* if error, clear all proxy texture image parameters */
3536         struct gl_texture_image *texImage;
3537         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3538         if (texImage)
3539            clear_teximage_fields(texImage);
3540      }
3541      else {
3542         /* store the teximage parameters */
3543         struct gl_texture_unit *texUnit;
3544         struct gl_texture_object *texObj;
3545         struct gl_texture_image *texImage;
3546         texUnit = get_current_tex_unit(ctx);
3547	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3548
3549	 _mesa_lock_texture(ctx, texObj);
3550	 {
3551	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3552	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3553				       border, internalFormat);
3554	 }
3555	 _mesa_unlock_texture(ctx, texObj);
3556      }
3557   }
3558   else {
3559      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3560      return;
3561   }
3562}
3563
3564
3565void GLAPIENTRY
3566_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3567                              GLenum internalFormat, GLsizei width,
3568                              GLsizei height, GLint border, GLsizei imageSize,
3569                              const GLvoid *data)
3570{
3571   GET_CURRENT_CONTEXT(ctx);
3572   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3573
3574   if (target == GL_TEXTURE_2D ||
3575       (ctx->Extensions.ARB_texture_cube_map &&
3576        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3577        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3578      /* non-proxy target */
3579      struct gl_texture_unit *texUnit;
3580      struct gl_texture_object *texObj;
3581      struct gl_texture_image *texImage;
3582      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3583                          internalFormat, width, height, 1, border, imageSize);
3584      if (error) {
3585         _mesa_error(ctx, error, "glCompressedTexImage2D");
3586         return;
3587      }
3588
3589      texUnit = get_current_tex_unit(ctx);
3590      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3591
3592      _mesa_lock_texture(ctx, texObj);
3593      {
3594	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3595	 if (!texImage) {
3596	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3597	    goto out;
3598	 }
3599
3600	 if (texImage->Data) {
3601	    ctx->Driver.FreeTexImageData( ctx, texImage );
3602	 }
3603	 ASSERT(texImage->Data == NULL);
3604
3605	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3606				    border, internalFormat);
3607
3608	 ASSERT(ctx->Driver.CompressedTexImage2D);
3609	 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
3610					     internalFormat, width, height,
3611					     border, imageSize, data,
3612					     texObj, texImage);
3613
3614	 /* state update */
3615	 texObj->_Complete = GL_FALSE;
3616	 ctx->NewState |= _NEW_TEXTURE;
3617      }
3618   out:
3619      _mesa_unlock_texture(ctx, texObj);
3620   }
3621   else if (target == GL_PROXY_TEXTURE_2D ||
3622            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3623             ctx->Extensions.ARB_texture_cube_map)) {
3624      /* Proxy texture: check for errors and update proxy state */
3625      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3626                          internalFormat, width, height, 1, border, imageSize);
3627      if (!error) {
3628         ASSERT(ctx->Driver.TestProxyTexImage);
3629         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3630                                              internalFormat, GL_NONE, GL_NONE,
3631                                              width, height, 1, border);
3632      }
3633      if (error) {
3634         /* if error, clear all proxy texture image parameters */
3635         struct gl_texture_image *texImage;
3636         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3637         if (texImage)
3638            clear_teximage_fields(texImage);
3639      }
3640      else {
3641         /* store the teximage parameters */
3642         struct gl_texture_unit *texUnit;
3643         struct gl_texture_object *texObj;
3644         struct gl_texture_image *texImage;
3645         texUnit = get_current_tex_unit(ctx);
3646	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3647
3648	 _mesa_lock_texture(ctx, texObj);
3649	 {
3650	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3651	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3652				       border, internalFormat);
3653	 }
3654	 _mesa_unlock_texture(ctx, texObj);
3655      }
3656   }
3657   else {
3658      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3659      return;
3660   }
3661}
3662
3663
3664void GLAPIENTRY
3665_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3666                              GLenum internalFormat, GLsizei width,
3667                              GLsizei height, GLsizei depth, GLint border,
3668                              GLsizei imageSize, const GLvoid *data)
3669{
3670   GET_CURRENT_CONTEXT(ctx);
3671   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3672
3673   if (target == GL_TEXTURE_3D) {
3674      /* non-proxy target */
3675      struct gl_texture_unit *texUnit;
3676      struct gl_texture_object *texObj;
3677      struct gl_texture_image *texImage;
3678      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3679                      internalFormat, width, height, depth, border, imageSize);
3680      if (error) {
3681         _mesa_error(ctx, error, "glCompressedTexImage3D");
3682         return;
3683      }
3684
3685      texUnit = get_current_tex_unit(ctx);
3686      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3687      _mesa_lock_texture(ctx, texObj);
3688      {
3689	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3690	 if (!texImage) {
3691	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3692	    goto out;
3693	 }
3694
3695	 if (texImage->Data) {
3696	    ctx->Driver.FreeTexImageData( ctx, texImage );
3697	 }
3698	 ASSERT(texImage->Data == NULL);
3699
3700	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
3701				    border, internalFormat);
3702
3703	 ASSERT(ctx->Driver.CompressedTexImage3D);
3704	 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3705					     internalFormat,
3706					     width, height, depth,
3707					     border, imageSize, data,
3708					     texObj, texImage);
3709
3710	 /* state update */
3711	 texObj->_Complete = GL_FALSE;
3712	 ctx->NewState |= _NEW_TEXTURE;
3713      }
3714   out:
3715      _mesa_unlock_texture(ctx, texObj);
3716   }
3717   else if (target == GL_PROXY_TEXTURE_3D) {
3718      /* Proxy texture: check for errors and update proxy state */
3719      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3720                      internalFormat, width, height, depth, border, imageSize);
3721      if (!error) {
3722         ASSERT(ctx->Driver.TestProxyTexImage);
3723         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3724                                             internalFormat, GL_NONE, GL_NONE,
3725                                             width, height, depth, border);
3726      }
3727      if (error) {
3728         /* if error, clear all proxy texture image parameters */
3729         struct gl_texture_image *texImage;
3730         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3731         if (texImage)
3732            clear_teximage_fields(texImage);
3733      }
3734      else {
3735         /* store the teximage parameters */
3736         struct gl_texture_unit *texUnit;
3737         struct gl_texture_object *texObj;
3738         struct gl_texture_image *texImage;
3739         texUnit = get_current_tex_unit(ctx);
3740	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3741	 _mesa_lock_texture(ctx, texObj);
3742	 {
3743	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3744	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3745				       depth, border, internalFormat);
3746	 }
3747	 _mesa_unlock_texture(ctx, texObj);
3748      }
3749   }
3750   else {
3751      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3752      return;
3753   }
3754}
3755
3756
3757void GLAPIENTRY
3758_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3759                                 GLsizei width, GLenum format,
3760                                 GLsizei imageSize, const GLvoid *data)
3761{
3762   struct gl_texture_unit *texUnit;
3763   struct gl_texture_object *texObj;
3764   struct gl_texture_image *texImage;
3765   GLenum error;
3766   GET_CURRENT_CONTEXT(ctx);
3767   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3768
3769   error = compressed_subtexture_error_check(ctx, 1, target, level,
3770                                             xoffset, 0, 0, /* pos */
3771                                             width, 1, 1,   /* size */
3772                                             format, imageSize);
3773   if (error) {
3774      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3775      return;
3776   }
3777
3778   texUnit = get_current_tex_unit(ctx);
3779   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3780   _mesa_lock_texture(ctx, texObj);
3781   {
3782      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3783      assert(texImage);
3784
3785      if ((GLint) format != texImage->InternalFormat) {
3786	 _mesa_error(ctx, GL_INVALID_OPERATION,
3787		     "glCompressedTexSubImage1D(format)");
3788	 goto out;
3789      }
3790
3791      if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
3792	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
3793	 goto out;
3794      }
3795
3796      if (width == 0)
3797	 goto out;  /* no-op, not an error */
3798
3799      if (ctx->Driver.CompressedTexSubImage1D) {
3800	 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3801						xoffset, width,
3802						format, imageSize, data,
3803						texObj, texImage);
3804      }
3805      ctx->NewState |= _NEW_TEXTURE;
3806   }
3807 out:
3808   _mesa_unlock_texture(ctx, texObj);
3809}
3810
3811
3812void GLAPIENTRY
3813_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3814                                 GLint yoffset, GLsizei width, GLsizei height,
3815                                 GLenum format, GLsizei imageSize,
3816                                 const GLvoid *data)
3817{
3818   struct gl_texture_unit *texUnit;
3819   struct gl_texture_object *texObj;
3820   struct gl_texture_image *texImage;
3821   GLenum error;
3822   GET_CURRENT_CONTEXT(ctx);
3823   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3824
3825   error = compressed_subtexture_error_check(ctx, 2, target, level,
3826                                             xoffset, yoffset, 0, /* pos */
3827                                             width, height, 1,    /* size */
3828                                             format, imageSize);
3829   if (error) {
3830      /* XXX proxy target? */
3831      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3832      return;
3833   }
3834
3835   texUnit = get_current_tex_unit(ctx);
3836   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3837   _mesa_lock_texture(ctx, texObj);
3838   {
3839      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3840      assert(texImage);
3841
3842      if ((GLint) format != texImage->InternalFormat) {
3843	 _mesa_error(ctx, GL_INVALID_OPERATION,
3844		     "glCompressedTexSubImage2D(format)");
3845	 goto out;
3846      }
3847
3848      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3849	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
3850	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3851	 goto out;
3852      }
3853
3854      if (width == 0 || height == 0)
3855	 goto out;  /* no-op, not an error */
3856
3857      if (ctx->Driver.CompressedTexSubImage2D) {
3858	 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3859						xoffset, yoffset, width, height,
3860						format, imageSize, data,
3861						texObj, texImage);
3862      }
3863      ctx->NewState |= _NEW_TEXTURE;
3864   }
3865 out:
3866   _mesa_unlock_texture(ctx, texObj);
3867}
3868
3869
3870void GLAPIENTRY
3871_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3872                                 GLint yoffset, GLint zoffset, GLsizei width,
3873                                 GLsizei height, GLsizei depth, GLenum format,
3874                                 GLsizei imageSize, const GLvoid *data)
3875{
3876   struct gl_texture_unit *texUnit;
3877   struct gl_texture_object *texObj;
3878   struct gl_texture_image *texImage;
3879   GLenum error;
3880   GET_CURRENT_CONTEXT(ctx);
3881   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3882
3883   error = compressed_subtexture_error_check(ctx, 3, target, level,
3884                                             xoffset, yoffset, zoffset,/*pos*/
3885                                             width, height, depth, /*size*/
3886                                             format, imageSize);
3887   if (error) {
3888      _mesa_error(ctx, error, "glCompressedTexSubImage3D");
3889      return;
3890   }
3891
3892   texUnit = get_current_tex_unit(ctx);
3893   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3894   _mesa_lock_texture(ctx, texObj);
3895   {
3896      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3897      assert(texImage);
3898
3899      if ((GLint) format != texImage->InternalFormat) {
3900	 _mesa_error(ctx, GL_INVALID_OPERATION,
3901		     "glCompressedTexSubImage3D(format)");
3902	 goto out;
3903      }
3904
3905      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3906	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
3907	  ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
3908	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3909	 goto out;
3910      }
3911
3912      if (width == 0 || height == 0 || depth == 0)
3913	 goto out;  /* no-op, not an error */
3914
3915      if (ctx->Driver.CompressedTexSubImage3D) {
3916	 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3917						xoffset, yoffset, zoffset,
3918						width, height, depth,
3919						format, imageSize, data,
3920						texObj, texImage);
3921      }
3922      ctx->NewState |= _NEW_TEXTURE;
3923   }
3924 out:
3925   _mesa_unlock_texture(ctx, texObj);
3926}
3927
3928
3929void GLAPIENTRY
3930_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3931{
3932   const struct gl_texture_unit *texUnit;
3933   struct gl_texture_object *texObj;
3934   struct gl_texture_image *texImage;
3935   GLint maxLevels;
3936   GET_CURRENT_CONTEXT(ctx);
3937   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3938
3939   texUnit = get_current_tex_unit(ctx);
3940   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3941   if (!texObj) {
3942      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
3943      return;
3944   }
3945
3946   maxLevels = _mesa_max_texture_levels(ctx, target);
3947   ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
3948
3949   if (level < 0 || level >= maxLevels) {
3950      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3951      return;
3952   }
3953
3954   if (_mesa_is_proxy_texture(target)) {
3955      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3956      return;
3957   }
3958
3959   _mesa_lock_texture(ctx, texObj);
3960   {
3961      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3962      if (texImage) {
3963         if (texImage->IsCompressed) {
3964            /* this typically calls _mesa_get_compressed_teximage() */
3965            ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
3966                                              texObj, texImage);
3967         }
3968         else {
3969            _mesa_error(ctx, GL_INVALID_OPERATION,
3970                        "glGetCompressedTexImageARB");
3971         }
3972      }
3973      else {
3974         /* probably invalid mipmap level */
3975         _mesa_error(ctx, GL_INVALID_VALUE,
3976                     "glGetCompressedTexImageARB(level)");
3977      }
3978   }
3979   _mesa_unlock_texture(ctx, texObj);
3980}
3981