teximage.c revision b23f5b5a5ccf5910f1d11d749c2e440e6a46259b
1/* $Id: teximage.c,v 1.99 2001/07/13 15:44:21 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "context.h"
33#include "convolve.h"
34#include "image.h"
35#include "macros.h"
36#include "mem.h"
37#include "mmath.h"
38#include "state.h"
39#include "texformat.h"
40#include "teximage.h"
41#include "texstate.h"
42#include "texstore.h"
43#include "mtypes.h"
44#include "swrast/s_span.h" /* XXX SWRAST hack */
45#endif
46
47
48/*
49 * NOTES:
50 *
51 * Mesa's native texture datatype is GLchan.  Native formats are
52 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
53 * and GL_COLOR_INDEX.
54 * Device drivers are free to implement any internal format they want.
55 */
56
57
58#ifdef DEBUG
59static void PrintTexture(const struct gl_texture_image *img)
60{
61   GLuint i, j, c;
62   const GLchan *data = (const GLchan *) img->Data;
63
64   if (!data) {
65      printf("No texture data\n");
66      return;
67   }
68
69   switch (img->Format) {
70      case GL_ALPHA:
71      case GL_LUMINANCE:
72      case GL_INTENSITY:
73      case GL_COLOR_INDEX:
74         c = 1;
75         break;
76      case GL_LUMINANCE_ALPHA:
77         c = 2;
78         break;
79      case GL_RGB:
80         c = 3;
81         break;
82      case GL_RGBA:
83         c = 4;
84         break;
85      default:
86         _mesa_problem(NULL, "error in PrintTexture\n");
87         return;
88   }
89
90   for (i = 0; i < img->Height; i++) {
91      for (j = 0; j < img->Width; j++) {
92         if (c==1)
93            printf("%02x  ", data[0]);
94         else if (c==2)
95            printf("%02x%02x  ", data[0], data[1]);
96         else if (c==3)
97            printf("%02x%02x%02x  ", data[0], data[1], data[2]);
98         else if (c==4)
99            printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
100         data += c;
101      }
102      printf("\n");
103   }
104}
105#endif
106
107
108
109/*
110 * Compute log base 2 of n.
111 * If n isn't an exact power of two return -1.
112 * If n < 0 return -1.
113 */
114static int
115logbase2( int n )
116{
117   GLint i = 1;
118   GLint log2 = 0;
119
120   if (n < 0) {
121      return -1;
122   }
123
124   while ( n > i ) {
125      i *= 2;
126      log2++;
127   }
128   if (i != n) {
129      return -1;
130   }
131   else {
132      return log2;
133   }
134}
135
136
137
138/*
139 * Given an internal texture format enum or 1, 2, 3, 4 return the
140 * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
141 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
142 * Return -1 if invalid enum.
143 */
144GLint
145_mesa_base_tex_format( GLcontext *ctx, GLint format )
146{
147   /*
148    * Ask the driver for the base format, if it doesn't
149    * know, it will return -1;
150    */
151   if (ctx->Driver.BaseCompressedTexFormat) {
152      GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
153      if (ifmt >= 0) {
154         return ifmt;
155      }
156   }
157   switch (format) {
158      case GL_ALPHA:
159      case GL_ALPHA4:
160      case GL_ALPHA8:
161      case GL_ALPHA12:
162      case GL_ALPHA16:
163         return GL_ALPHA;
164      case 1:
165      case GL_LUMINANCE:
166      case GL_LUMINANCE4:
167      case GL_LUMINANCE8:
168      case GL_LUMINANCE12:
169      case GL_LUMINANCE16:
170         return GL_LUMINANCE;
171      case 2:
172      case GL_LUMINANCE_ALPHA:
173      case GL_LUMINANCE4_ALPHA4:
174      case GL_LUMINANCE6_ALPHA2:
175      case GL_LUMINANCE8_ALPHA8:
176      case GL_LUMINANCE12_ALPHA4:
177      case GL_LUMINANCE12_ALPHA12:
178      case GL_LUMINANCE16_ALPHA16:
179         return GL_LUMINANCE_ALPHA;
180      case GL_INTENSITY:
181      case GL_INTENSITY4:
182      case GL_INTENSITY8:
183      case GL_INTENSITY12:
184      case GL_INTENSITY16:
185         return GL_INTENSITY;
186      case 3:
187      case GL_RGB:
188      case GL_R3_G3_B2:
189      case GL_RGB4:
190      case GL_RGB5:
191      case GL_RGB8:
192      case GL_RGB10:
193      case GL_RGB12:
194      case GL_RGB16:
195         return GL_RGB;
196      case 4:
197      case GL_RGBA:
198      case GL_RGBA2:
199      case GL_RGBA4:
200      case GL_RGB5_A1:
201      case GL_RGBA8:
202      case GL_RGB10_A2:
203      case GL_RGBA12:
204      case GL_RGBA16:
205         return GL_RGBA;
206      case GL_COLOR_INDEX:
207      case GL_COLOR_INDEX1_EXT:
208      case GL_COLOR_INDEX2_EXT:
209      case GL_COLOR_INDEX4_EXT:
210      case GL_COLOR_INDEX8_EXT:
211      case GL_COLOR_INDEX12_EXT:
212      case GL_COLOR_INDEX16_EXT:
213         return GL_COLOR_INDEX;
214      case GL_DEPTH_COMPONENT:
215      case GL_DEPTH_COMPONENT16_SGIX:
216      case GL_DEPTH_COMPONENT24_SGIX:
217      case GL_DEPTH_COMPONENT32_SGIX:
218         if (ctx->Extensions.SGIX_depth_texture)
219            return GL_DEPTH_COMPONENT;
220         else
221            return -1;
222      default:
223         return -1;  /* error */
224   }
225}
226
227
228/*
229 * Test if the given image format is a color/rgba format.  That is,
230 * not color index, depth, stencil, etc.
231 */
232static GLboolean
233is_color_format(GLenum format)
234{
235   switch (format) {
236      case GL_ALPHA:
237      case GL_ALPHA4:
238      case GL_ALPHA8:
239      case GL_ALPHA12:
240      case GL_ALPHA16:
241      case 1:
242      case GL_LUMINANCE:
243      case GL_LUMINANCE4:
244      case GL_LUMINANCE8:
245      case GL_LUMINANCE12:
246      case GL_LUMINANCE16:
247      case 2:
248      case GL_LUMINANCE_ALPHA:
249      case GL_LUMINANCE4_ALPHA4:
250      case GL_LUMINANCE6_ALPHA2:
251      case GL_LUMINANCE8_ALPHA8:
252      case GL_LUMINANCE12_ALPHA4:
253      case GL_LUMINANCE12_ALPHA12:
254      case GL_LUMINANCE16_ALPHA16:
255      case GL_INTENSITY:
256      case GL_INTENSITY4:
257      case GL_INTENSITY8:
258      case GL_INTENSITY12:
259      case GL_INTENSITY16:
260      case 3:
261      case GL_RGB:
262      case GL_R3_G3_B2:
263      case GL_RGB4:
264      case GL_RGB5:
265      case GL_RGB8:
266      case GL_RGB10:
267      case GL_RGB12:
268      case GL_RGB16:
269      case 4:
270      case GL_RGBA:
271      case GL_RGBA2:
272      case GL_RGBA4:
273      case GL_RGB5_A1:
274      case GL_RGBA8:
275      case GL_RGB10_A2:
276      case GL_RGBA12:
277      case GL_RGBA16:
278         return GL_TRUE;
279      default:
280         return GL_FALSE;
281   }
282}
283
284
285static GLboolean
286is_index_format(GLenum format)
287{
288   switch (format) {
289      case GL_COLOR_INDEX:
290      case GL_COLOR_INDEX1_EXT:
291      case GL_COLOR_INDEX2_EXT:
292      case GL_COLOR_INDEX4_EXT:
293      case GL_COLOR_INDEX8_EXT:
294      case GL_COLOR_INDEX12_EXT:
295      case GL_COLOR_INDEX16_EXT:
296         return GL_TRUE;
297      default:
298         return GL_FALSE;
299   }
300}
301
302
303/*
304 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
305 * otherwise.
306 */
307static GLboolean
308is_compressed_format(GLcontext *ctx, GLenum internalFormat)
309{
310   if (ctx->Driver.BaseCompressedTexFormat) {
311      GLint b = (*ctx->Driver.BaseCompressedTexFormat)(ctx, internalFormat);
312      if (b > 0)
313         return GL_TRUE;
314      else
315         return GL_FALSE;
316   }
317   return GL_FALSE;
318}
319
320
321
322/*
323 * Store a gl_texture_image pointer in a gl_texture_object structure
324 * according to the target and level parameters.
325 * This was basically prompted by the introduction of cube maps.
326 */
327void
328_mesa_set_tex_image(struct gl_texture_object *tObj,
329                    GLenum target, GLint level,
330                    struct gl_texture_image *texImage)
331{
332   ASSERT(tObj);
333   ASSERT(texImage);
334   switch (target) {
335      case GL_TEXTURE_1D:
336      case GL_TEXTURE_2D:
337      case GL_TEXTURE_3D:
338         tObj->Image[level] = texImage;
339         return;
340      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
341         tObj->Image[level] = texImage;
342         return;
343      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
344         tObj->NegX[level] = texImage;
345         return;
346      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
347         tObj->PosY[level] = texImage;
348         return;
349      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
350         tObj->NegY[level] = texImage;
351         return;
352      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
353         tObj->PosZ[level] = texImage;
354         return;
355      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
356         tObj->NegZ[level] = texImage;
357         return;
358      default:
359         _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
360         return;
361   }
362}
363
364
365
366/*
367 * Return new gl_texture_image struct with all fields initialized to zero.
368 */
369struct gl_texture_image *
370_mesa_alloc_texture_image( void )
371{
372   return CALLOC_STRUCT(gl_texture_image);
373}
374
375
376
377void
378_mesa_free_texture_image( struct gl_texture_image *teximage )
379{
380   if (teximage->Data) {
381      FREE( teximage->Data );
382      teximage->Data = NULL;
383   }
384   FREE( teximage );
385}
386
387
388/*
389 * Return GL_TRUE if the target is a proxy target.
390 */
391static GLboolean
392is_proxy_target(GLenum target)
393{
394   return (target == GL_PROXY_TEXTURE_1D ||
395           target == GL_PROXY_TEXTURE_2D ||
396           target == GL_PROXY_TEXTURE_3D ||
397           target == GL_PROXY_TEXTURE_CUBE_MAP_ARB);
398}
399
400
401/*
402 * Given a texture unit and a texture target, return the corresponding
403 * texture object.
404 */
405struct gl_texture_object *
406_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
407                        GLenum target)
408{
409   switch (target) {
410      case GL_TEXTURE_1D:
411         return texUnit->Current1D;
412      case GL_PROXY_TEXTURE_1D:
413         return ctx->Texture.Proxy1D;
414      case GL_TEXTURE_2D:
415         return texUnit->Current2D;
416      case GL_PROXY_TEXTURE_2D:
417         return ctx->Texture.Proxy2D;
418      case GL_TEXTURE_3D:
419         return texUnit->Current3D;
420      case GL_PROXY_TEXTURE_3D:
421         return ctx->Texture.Proxy3D;
422      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
423      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
424      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
425      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
426      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
427      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
428      case GL_TEXTURE_CUBE_MAP_ARB:
429         return ctx->Extensions.ARB_texture_cube_map
430                ? texUnit->CurrentCubeMap : NULL;
431      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
432         return ctx->Extensions.ARB_texture_cube_map
433                ? ctx->Texture.ProxyCubeMap : NULL;
434      default:
435         _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
436         return NULL;
437   }
438}
439
440
441/*
442 * Return the texture image struct which corresponds to target and level
443 * for the given texture unit.
444 */
445struct gl_texture_image *
446_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
447                       GLenum target, GLint level)
448{
449   ASSERT(texUnit);
450   ASSERT(level < MAX_TEXTURE_LEVELS);
451   switch (target) {
452      case GL_TEXTURE_1D:
453         return texUnit->Current1D->Image[level];
454      case GL_PROXY_TEXTURE_1D:
455         return ctx->Texture.Proxy1D->Image[level];
456      case GL_TEXTURE_2D:
457         return texUnit->Current2D->Image[level];
458      case GL_PROXY_TEXTURE_2D:
459         return ctx->Texture.Proxy2D->Image[level];
460      case GL_TEXTURE_3D:
461         return texUnit->Current3D->Image[level];
462      case GL_PROXY_TEXTURE_3D:
463         return ctx->Texture.Proxy3D->Image[level];
464      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
465         if (ctx->Extensions.ARB_texture_cube_map)
466            return texUnit->CurrentCubeMap->Image[level];
467         else
468            return NULL;
469      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
470         if (ctx->Extensions.ARB_texture_cube_map)
471            return texUnit->CurrentCubeMap->NegX[level];
472         else
473            return NULL;
474      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
475         if (ctx->Extensions.ARB_texture_cube_map)
476            return texUnit->CurrentCubeMap->PosY[level];
477         else
478            return NULL;
479      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
480         if (ctx->Extensions.ARB_texture_cube_map)
481            return texUnit->CurrentCubeMap->NegY[level];
482         else
483            return NULL;
484      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
485         if (ctx->Extensions.ARB_texture_cube_map)
486            return texUnit->CurrentCubeMap->PosZ[level];
487         else
488            return NULL;
489      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
490         if (ctx->Extensions.ARB_texture_cube_map)
491            return texUnit->CurrentCubeMap->NegZ[level];
492         else
493            return NULL;
494      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
495         if (ctx->Extensions.ARB_texture_cube_map)
496            return ctx->Texture.ProxyCubeMap->Image[level];
497         else
498            return NULL;
499      default:
500         _mesa_problem(ctx, "bad target in _mesa_select_tex_image()");
501         return NULL;
502   }
503}
504
505
506
507/*
508 * glTexImage[123]D can accept a NULL image pointer.  In this case we
509 * create a texture image with unspecified image contents per the OpenGL
510 * spec.
511 */
512static GLubyte *
513make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
514{
515   const GLint components = _mesa_components_in_format(format);
516   const GLint numPixels = width * height * depth;
517   GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
518
519   /*
520    * Let's see if anyone finds this.  If glTexImage2D() is called with
521    * a NULL image pointer then load the texture image with something
522    * interesting instead of leaving it indeterminate.
523    */
524   if (data) {
525      static const char message[8][32] = {
526         "   X   X  XXXXX   XXX     X    ",
527         "   XX XX  X      X   X   X X   ",
528         "   X X X  X      X      X   X  ",
529         "   X   X  XXXX    XXX   XXXXX  ",
530         "   X   X  X          X  X   X  ",
531         "   X   X  X      X   X  X   X  ",
532         "   X   X  XXXXX   XXX   X   X  ",
533         "                               "
534      };
535
536      GLubyte *imgPtr = data;
537      GLint h, i, j, k;
538      for (h = 0; h < depth; h++) {
539         for (i = 0; i < height; i++) {
540            GLint srcRow = 7 - (i % 8);
541            for (j = 0; j < width; j++) {
542               GLint srcCol = j % 32;
543               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
544               for (k = 0; k < components; k++) {
545                  *imgPtr++ = texel;
546               }
547            }
548         }
549      }
550   }
551
552   return data;
553}
554
555
556
557/*
558 * Reset the fields of a gl_texture_image struct to zero.
559 * This is called when a proxy texture test fails, we set all the
560 * image members (except DriverData) to zero.
561 * It's also used in glTexImage[123]D as a safeguard to be sure all
562 * required fields get initialized properly by the Driver.TexImage[123]D
563 * functions.
564 */
565static void
566clear_teximage_fields(struct gl_texture_image *img)
567{
568   ASSERT(img);
569   img->Format = 0;
570   img->IntFormat = 0;
571   img->Border = 0;
572   img->Width = 0;
573   img->Height = 0;
574   img->Depth = 0;
575   img->Width2 = 0;
576   img->Height2 = 0;
577   img->Depth2 = 0;
578   img->WidthLog2 = 0;
579   img->HeightLog2 = 0;
580   img->DepthLog2 = 0;
581   img->Data = NULL;
582   img->TexFormat = &_mesa_null_texformat;
583   img->FetchTexel = NULL;
584   img->IsCompressed = 0;
585   img->CompressedSize = 0;
586}
587
588
589/*
590 * Initialize basic fields of the gl_texture_image struct.
591 */
592void
593_mesa_init_teximage_fields(GLcontext *ctx,
594                           struct gl_texture_image *img,
595                           GLsizei width, GLsizei height, GLsizei depth,
596                           GLint border, GLenum internalFormat)
597{
598   ASSERT(img);
599   img->Format = _mesa_base_tex_format( ctx, internalFormat );
600   ASSERT(img->Format > 0);
601   img->IntFormat = internalFormat;
602   img->Border = border;
603   img->Width = width;
604   img->Height = height;
605   img->Depth = depth;
606   img->WidthLog2 = logbase2(width - 2 * border);
607   if (height == 1)  /* 1-D texture */
608      img->HeightLog2 = 0;
609   else
610      img->HeightLog2 = logbase2(height - 2 * border);
611   if (depth == 1)   /* 2-D texture */
612      img->DepthLog2 = 0;
613   else
614      img->DepthLog2 = logbase2(depth - 2 * border);
615   img->Width2 = 1 << img->WidthLog2;
616   img->Height2 = 1 << img->HeightLog2;
617   img->Depth2 = 1 << img->DepthLog2;
618   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
619   img->IsCompressed = is_compressed_format(ctx, internalFormat);
620}
621
622
623
624/*
625 * Test glTexImage[123]D() parameters for errors.
626 * Input:
627 *         dimensions - must be 1 or 2 or 3
628 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
629 */
630static GLboolean
631texture_error_check( GLcontext *ctx, GLenum target,
632                     GLint level, GLint internalFormat,
633                     GLenum format, GLenum type,
634                     GLuint dimensions,
635                     GLint width, GLint height,
636                     GLint depth, GLint border )
637{
638   GLboolean isProxy;
639   GLint iformat;
640   GLint maxLevels = 0, maxTextureSize;
641
642   if (dimensions == 1) {
643      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
644      if (target != GL_TEXTURE_1D && !isProxy) {
645         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
646         return GL_TRUE;
647      }
648      maxLevels = ctx->Const.MaxTextureLevels;
649   }
650   else if (dimensions == 2) {
651      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D ||
652                             target == GL_PROXY_TEXTURE_CUBE_MAP_ARB);
653      if (target != GL_TEXTURE_2D && !isProxy &&
654          !(ctx->Extensions.ARB_texture_cube_map &&
655            target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
656            target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
657          _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
658          return GL_TRUE;
659      }
660      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
661         maxLevels = ctx->Const.MaxTextureLevels;
662      else
663         maxLevels = ctx->Const.MaxCubeTextureLevels;
664   }
665   else if (dimensions == 3) {
666      isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
667      if (target != GL_TEXTURE_3D && !isProxy) {
668         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
669         return GL_TRUE;
670      }
671      maxLevels = ctx->Const.Max3DTextureLevels;
672   }
673   else {
674      _mesa_problem( ctx, "bad dims in texture_error_check" );
675      return GL_TRUE;
676   }
677
678   ASSERT(maxLevels > 0);
679   maxTextureSize = 1 << (maxLevels - 1);
680
681   /* Border */
682   if (border != 0 && border != 1) {
683      if (!isProxy) {
684         char message[100];
685         sprintf(message, "glTexImage%dD(border=%d)", dimensions, border);
686         _mesa_error(ctx, GL_INVALID_VALUE, message);
687      }
688      return GL_TRUE;
689   }
690
691   /* Width */
692   if (width < 2 * border || width > 2 + maxTextureSize
693       || logbase2( width - 2 * border ) < 0) {
694      if (!isProxy) {
695         char message[100];
696         sprintf(message, "glTexImage%dD(width=%d)", dimensions, width);
697         _mesa_error(ctx, GL_INVALID_VALUE, message);
698      }
699      return GL_TRUE;
700   }
701
702   /* Height */
703   if (dimensions >= 2) {
704      if (height < 2 * border || height > 2 + maxTextureSize
705          || logbase2( height - 2 * border ) < 0) {
706         if (!isProxy) {
707            char message[100];
708            sprintf(message, "glTexImage%dD(height=%d)", dimensions, height);
709            _mesa_error(ctx, GL_INVALID_VALUE, message);
710         }
711         return GL_TRUE;
712      }
713   }
714
715   /* For cube map, width must equal height */
716   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
717       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
718      if (width != height) {
719         if (!isProxy) {
720            _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
721         }
722         return GL_TRUE;
723      }
724   }
725
726   /* Depth */
727   if (dimensions >= 3) {
728      if (depth < 2 * border || depth > 2 + maxTextureSize
729          || logbase2( depth - 2 * border ) < 0) {
730         if (!isProxy) {
731            char message[100];
732            sprintf(message, "glTexImage3D(depth=%d)", depth );
733            _mesa_error( ctx, GL_INVALID_VALUE, message );
734         }
735         return GL_TRUE;
736      }
737   }
738
739   /* Level */
740   if (level < 0 || level >= maxLevels) {
741      if (!isProxy) {
742         char message[100];
743         sprintf(message, "glTexImage%dD(level=%d)", dimensions, level);
744         _mesa_error(ctx, GL_INVALID_VALUE, message);
745      }
746      return GL_TRUE;
747   }
748
749   /* For cube map, width must equal height */
750   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
751       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
752      if (width != height) {
753         _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
754         return GL_TRUE;
755      }
756   }
757
758   iformat = _mesa_base_tex_format( ctx, internalFormat );
759   if (iformat < 0) {
760      if (!isProxy) {
761         char message[100];
762         sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions,
763                 internalFormat);
764         _mesa_error(ctx, GL_INVALID_VALUE, message);
765      }
766      return GL_TRUE;
767   }
768
769   ASSERT(iformat > 0);
770
771   if (!is_compressed_format( ctx, internalFormat ) &&
772       !_mesa_is_legal_format_and_type( format, type )) {
773      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
774       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
775       */
776      if (!isProxy) {
777	 char message[100];
778	 sprintf(message, "glTexImage%dD(format or type)", dimensions);
779	 _mesa_error(ctx, GL_INVALID_OPERATION, message);
780      }
781      return GL_TRUE;
782   }
783
784   /* if we get here, the parameters are OK */
785   return GL_FALSE;
786}
787
788
789
790/*
791 * Test glTexSubImage[123]D() parameters for errors.
792 * Input:
793 *         dimensions - must be 1 or 2 or 3
794 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
795 */
796static GLboolean
797subtexture_error_check( GLcontext *ctx, GLuint dimensions,
798                        GLenum target, GLint level,
799                        GLint xoffset, GLint yoffset, GLint zoffset,
800                        GLint width, GLint height, GLint depth,
801                        GLenum format, GLenum type )
802{
803   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
804   struct gl_texture_image *destTex;
805   GLint maxLevels = 0;
806   GLboolean compressed;
807
808   if (dimensions == 1) {
809      if (target != GL_TEXTURE_1D) {
810         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
811         return GL_TRUE;
812      }
813      maxLevels = ctx->Const.MaxTextureLevels;
814   }
815   else if (dimensions == 2) {
816      if (ctx->Extensions.ARB_texture_cube_map) {
817         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
818              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
819             target != GL_TEXTURE_2D) {
820            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
821            return GL_TRUE;
822         }
823      }
824      else if (target != GL_TEXTURE_2D) {
825         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
826         return GL_TRUE;
827      }
828      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
829         maxLevels = ctx->Const.MaxTextureLevels;
830      else
831         maxLevels = ctx->Const.MaxCubeTextureLevels;
832   }
833   else if (dimensions == 3) {
834      if (target != GL_TEXTURE_3D) {
835         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
836         return GL_TRUE;
837      }
838      maxLevels = ctx->Const.Max3DTextureLevels;
839   }
840   else {
841      _mesa_problem( ctx, "bad dims in texture_error_check" );
842      return GL_TRUE;
843   }
844
845   ASSERT(maxLevels > 0);
846
847   if (level < 0 || level >= maxLevels) {
848      char message[100];
849      sprintf(message, "glTexSubImage2D(level=%d)", level);
850      _mesa_error(ctx, GL_INVALID_ENUM, message);
851      return GL_TRUE;
852   }
853
854   if (width < 0) {
855      char message[100];
856      sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width);
857      _mesa_error(ctx, GL_INVALID_VALUE, message);
858      return GL_TRUE;
859   }
860   if (height < 0 && dimensions > 1) {
861      char message[100];
862      sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height);
863      _mesa_error(ctx, GL_INVALID_VALUE, message);
864      return GL_TRUE;
865   }
866   if (depth < 0 && dimensions > 2) {
867      char message[100];
868      sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth);
869      _mesa_error(ctx, GL_INVALID_VALUE, message);
870      return GL_TRUE;
871   }
872
873   destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
874
875   if (!destTex) {
876      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
877      return GL_TRUE;
878   }
879
880   if (xoffset < -((GLint)destTex->Border)) {
881      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
882      return GL_TRUE;
883   }
884   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
885      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
886      return GL_TRUE;
887   }
888   if (dimensions > 1) {
889      if (yoffset < -((GLint)destTex->Border)) {
890         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
891         return GL_TRUE;
892      }
893      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
894         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
895         return GL_TRUE;
896      }
897   }
898   if (dimensions > 2) {
899      if (zoffset < -((GLint)destTex->Border)) {
900         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
901         return GL_TRUE;
902      }
903      if (zoffset + depth  > (GLint) (destTex->Depth + destTex->Border)) {
904         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
905         return GL_TRUE;
906      }
907   }
908
909   compressed = is_compressed_format(ctx, destTex->IntFormat);
910
911   if (!compressed && !_mesa_is_legal_format_and_type(format, type)) {
912      char message[100];
913      sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
914      _mesa_error(ctx, GL_INVALID_ENUM, message);
915      return GL_TRUE;
916   }
917
918   if (compressed) {
919      if (xoffset != -destTex->Border) {
920         _mesa_error(ctx, GL_INVALID_OPERATION,
921                     "glTexSubImage1/2/3D(xoffset != -border");
922         return GL_TRUE;
923      }
924      if (dimensions > 1 && yoffset != -destTex->Border) {
925         _mesa_error(ctx, GL_INVALID_OPERATION,
926                     "glTexSubImage2/3D(yoffset != -border");
927         return GL_TRUE;
928      }
929      if (dimensions > 2 && zoffset != -destTex->Border) {
930         _mesa_error(ctx, GL_INVALID_OPERATION,
931                     "glTexSubImage3D(zoffset != -border");
932         return GL_TRUE;
933      }
934   }
935
936   return GL_FALSE;
937}
938
939
940/*
941 * Test glCopyTexImage[12]D() parameters for errors.
942 * Input:  dimensions - must be 1 or 2 or 3
943 * Return:  GL_TRUE = an error was detected, GL_FALSE = no errors
944 */
945static GLboolean
946copytexture_error_check( GLcontext *ctx, GLuint dimensions,
947                         GLenum target, GLint level, GLint internalFormat,
948                         GLint width, GLint height, GLint border )
949{
950   GLint iformat;
951   GLint maxLevels = 0, maxTextureSize;
952
953   if (dimensions == 1) {
954      if (target != GL_TEXTURE_1D) {
955         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
956         return GL_TRUE;
957      }
958      maxLevels = ctx->Const.MaxTextureLevels;
959   }
960   else if (dimensions == 2) {
961      if (ctx->Extensions.ARB_texture_cube_map) {
962         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
963              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
964             target != GL_TEXTURE_2D) {
965            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
966            return GL_TRUE;
967         }
968      }
969      else if (target != GL_TEXTURE_2D) {
970         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
971         return GL_TRUE;
972      }
973      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
974         maxLevels = ctx->Const.MaxTextureLevels;
975      else
976         maxLevels = ctx->Const.MaxCubeTextureLevels;
977   }
978
979   ASSERT(maxLevels > 0);
980   maxTextureSize = 1 << (maxLevels - 1);
981
982   /* Border */
983   if (border != 0 && border != 1) {
984      char message[100];
985      sprintf(message, "glCopyTexImage%dD(border)", dimensions);
986      _mesa_error(ctx, GL_INVALID_VALUE, message);
987      return GL_TRUE;
988   }
989
990   /* Width */
991   if (width < 2 * border || width > 2 + maxTextureSize
992       || logbase2( width - 2 * border ) < 0) {
993      char message[100];
994      sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width);
995      _mesa_error(ctx, GL_INVALID_VALUE, message);
996      return GL_TRUE;
997   }
998
999   /* Height */
1000   if (dimensions >= 2) {
1001      if (height < 2 * border || height > 2 + maxTextureSize
1002          || logbase2( height - 2 * border ) < 0) {
1003         char message[100];
1004         sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height);
1005         _mesa_error(ctx, GL_INVALID_VALUE, message);
1006         return GL_TRUE;
1007      }
1008   }
1009
1010   /* For cube map, width must equal height */
1011   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1012       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1013      if (width != height) {
1014         _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1015         return GL_TRUE;
1016      }
1017   }
1018
1019   /* Level */
1020   if (level < 0 || level >= maxLevels) {
1021      char message[100];
1022      sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level);
1023      _mesa_error(ctx, GL_INVALID_VALUE, message);
1024      return GL_TRUE;
1025   }
1026
1027   iformat = _mesa_base_tex_format(ctx, internalFormat);
1028   if (iformat < 0) {
1029      char message[100];
1030      sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1031      _mesa_error(ctx, GL_INVALID_VALUE, message);
1032      return GL_TRUE;
1033   }
1034
1035   /* if we get here, the parameters are OK */
1036   return GL_FALSE;
1037}
1038
1039
1040static GLboolean
1041copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1042                             GLenum target, GLint level,
1043                             GLint xoffset, GLint yoffset, GLint zoffset,
1044                             GLsizei width, GLsizei height )
1045{
1046   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1047   struct gl_texture_image *teximage;
1048   GLint maxLevels = 0;
1049   GLboolean compressed;
1050
1051   if (dimensions == 1) {
1052      if (target != GL_TEXTURE_1D) {
1053         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1054         return GL_TRUE;
1055      }
1056      maxLevels = ctx->Const.MaxTextureLevels;
1057   }
1058   else if (dimensions == 2) {
1059      if (ctx->Extensions.ARB_texture_cube_map) {
1060         if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1061              target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1062             target != GL_TEXTURE_2D) {
1063            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1064            return GL_TRUE;
1065         }
1066      }
1067      else if (target != GL_TEXTURE_2D) {
1068         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1069         return GL_TRUE;
1070      }
1071      if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
1072         maxLevels = ctx->Const.MaxTextureLevels;
1073      else
1074         maxLevels = ctx->Const.MaxCubeTextureLevels;
1075   }
1076   else if (dimensions == 3) {
1077      if (target != GL_TEXTURE_3D) {
1078         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1079         return GL_TRUE;
1080      }
1081      maxLevels = ctx->Const.Max3DTextureLevels;
1082   }
1083
1084   ASSERT(maxLevels > 0);
1085
1086   if (level < 0 || level >= maxLevels) {
1087      char message[100];
1088      sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1089      _mesa_error(ctx, GL_INVALID_VALUE, message);
1090      return GL_TRUE;
1091   }
1092
1093   if (width < 0) {
1094      char message[100];
1095      sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1096      _mesa_error(ctx, GL_INVALID_VALUE, message);
1097      return GL_TRUE;
1098   }
1099   if (dimensions > 1 && height < 0) {
1100      char message[100];
1101      sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1102      _mesa_error(ctx, GL_INVALID_VALUE, message);
1103      return GL_TRUE;
1104   }
1105
1106   teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
1107   if (!teximage) {
1108      char message[100];
1109      sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1110      _mesa_error(ctx, GL_INVALID_OPERATION, message);
1111      return GL_TRUE;
1112   }
1113
1114   if (xoffset < -((GLint)teximage->Border)) {
1115      char message[100];
1116      sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1117      _mesa_error(ctx, GL_INVALID_VALUE, message);
1118      return GL_TRUE;
1119   }
1120   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1121      char message[100];
1122      sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1123      _mesa_error(ctx, GL_INVALID_VALUE, message);
1124      return GL_TRUE;
1125   }
1126   if (dimensions > 1) {
1127      if (yoffset < -((GLint)teximage->Border)) {
1128         char message[100];
1129         sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1130         _mesa_error(ctx, GL_INVALID_VALUE, message);
1131         return GL_TRUE;
1132      }
1133      /* NOTE: we're adding the border here, not subtracting! */
1134      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1135         char message[100];
1136         sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1137         _mesa_error(ctx, GL_INVALID_VALUE, message);
1138         return GL_TRUE;
1139      }
1140   }
1141
1142   if (dimensions > 2) {
1143      if (zoffset < -((GLint)teximage->Border)) {
1144         char message[100];
1145         sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1146         _mesa_error(ctx, GL_INVALID_VALUE, message);
1147         return GL_TRUE;
1148      }
1149      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1150         char message[100];
1151         sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1152         _mesa_error(ctx, GL_INVALID_VALUE, message);
1153         return GL_TRUE;
1154      }
1155   }
1156
1157   compressed = is_compressed_format(ctx, teximage->IntFormat);
1158   if (compressed) {
1159      if (xoffset != -teximage->Border) {
1160         _mesa_error(ctx, GL_INVALID_OPERATION,
1161                     "glCopyTexSubImage1/2/3D(xoffset != -border");
1162         return GL_TRUE;
1163      }
1164      if (dimensions > 1 && yoffset != -teximage->Border) {
1165         _mesa_error(ctx, GL_INVALID_OPERATION,
1166                     "glCopyTexSubImage2/3D(yoffset != -border");
1167         return GL_TRUE;
1168      }
1169      if (dimensions > 2 && zoffset != -teximage->Border) {
1170         _mesa_error(ctx, GL_INVALID_OPERATION,
1171                     "glCopyTexSubImage3D(zoffset != -border");
1172         return GL_TRUE;
1173      }
1174   }
1175
1176   /* if we get here, the parameters are OK */
1177   return GL_FALSE;
1178}
1179
1180
1181
1182void
1183_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1184                   GLenum type, GLvoid *pixels )
1185{
1186   const struct gl_texture_unit *texUnit;
1187   const struct gl_texture_object *texObj;
1188   struct gl_texture_image *texImage;
1189   GLint maxLevels = 0;
1190   GET_CURRENT_CONTEXT(ctx);
1191   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1192
1193   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
1194   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1195   if (!texObj || is_proxy_target(target)) {
1196      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
1197      return;
1198   }
1199
1200   if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
1201      maxLevels = ctx->Const.MaxTextureLevels;
1202   }
1203   else if (target == GL_TEXTURE_3D) {
1204      maxLevels = ctx->Const.Max3DTextureLevels;
1205   }
1206   else {
1207      maxLevels = ctx->Const.MaxCubeTextureLevels;
1208   }
1209
1210   ASSERT(maxLevels > 0);
1211
1212   if (level < 0 || level >= maxLevels) {
1213      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1214      return;
1215   }
1216
1217   if (_mesa_sizeof_type(type) <= 0) {
1218      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1219      return;
1220   }
1221
1222   if (_mesa_components_in_format(format) <= 0 ||
1223       format == GL_STENCIL_INDEX) {
1224      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1225      return;
1226   }
1227
1228   if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
1229      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1230   }
1231
1232   if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) {
1233      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1234   }
1235
1236   /* XXX what if format/type doesn't match texture format/type? */
1237
1238   if (!pixels)
1239      return;
1240
1241   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1242   if (!texImage) {
1243      /* invalid mipmap level, not an error */
1244      return;
1245   }
1246
1247   if (!texImage->Data) {
1248      /* no image data, not an error */
1249      return;
1250   }
1251
1252   {
1253      const GLint width = texImage->Width;
1254      const GLint height = texImage->Height;
1255      const GLint depth = texImage->Depth;
1256      GLint img, row;
1257      for (img = 0; img < depth; img++) {
1258         for (row = 0; row < height; row++) {
1259            /* compute destination address in client memory */
1260            GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1261                                                width, height, format, type,
1262                                                img, row, 0);
1263            assert(dest);
1264
1265            if (format == GL_COLOR_INDEX) {
1266               GLuint indexRow[MAX_WIDTH];
1267               GLint col;
1268               for (col = 0; col < width; col++) {
1269                  (*texImage->FetchTexel)(texImage, col, row, img,
1270                                          (GLvoid *) &indexRow[col]);
1271               }
1272               _mesa_pack_index_span(ctx, width, type, dest,
1273                                     indexRow, &ctx->Pack,
1274                                     0 /* no image transfer */);
1275            }
1276            else if (format == GL_DEPTH_COMPONENT) {
1277               GLfloat depthRow[MAX_WIDTH];
1278               GLint col;
1279               for (col = 0; col < width; col++) {
1280                  (*texImage->FetchTexel)(texImage, col, row, img,
1281                                          (GLvoid *) &depthRow[col]);
1282               }
1283               _mesa_pack_depth_span(ctx, width, dest, type,
1284                                     depthRow, &ctx->Pack);
1285            }
1286            else {
1287               /* general case:  convert row to RGBA format */
1288               GLchan rgba[MAX_WIDTH][4];
1289               GLint col;
1290               for (col = 0; col < width; col++) {
1291                  (*texImage->FetchTexel)(texImage, col, row, img,
1292                                          (GLvoid *) rgba[col]);
1293               }
1294               _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba,
1295                                    format, type, dest, &ctx->Pack,
1296                                    0 /* no image transfer */);
1297            } /* format */
1298         } /* row */
1299      } /* img */
1300   }
1301}
1302
1303
1304
1305/*
1306 * Called from the API.  Note that width includes the border.
1307 */
1308void
1309_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1310                  GLsizei width, GLint border, GLenum format,
1311                  GLenum type, const GLvoid *pixels )
1312{
1313   GLsizei postConvWidth = width;
1314   GET_CURRENT_CONTEXT(ctx);
1315   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1316
1317   if (is_color_format(internalFormat)) {
1318      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1319   }
1320
1321   if (target == GL_TEXTURE_1D) {
1322      struct gl_texture_unit *texUnit;
1323      struct gl_texture_object *texObj;
1324      struct gl_texture_image *texImage;
1325
1326      if (texture_error_check(ctx, target, level, internalFormat,
1327                              format, type, 1, postConvWidth, 1, 1, border)) {
1328         return;   /* error was recorded */
1329      }
1330
1331      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1332      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1333      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1334
1335      if (!texImage) {
1336         texImage = _mesa_alloc_texture_image();
1337         texObj->Image[level] = texImage;
1338         if (!texImage) {
1339            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1340            return;
1341         }
1342      }
1343      else if (texImage->Data) {
1344         /* free the old texture data */
1345         FREE(texImage->Data);
1346         texImage->Data = NULL;
1347      }
1348      clear_teximage_fields(texImage); /* not really needed, but helpful */
1349      _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1350                                 border, internalFormat);
1351
1352      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1353         _mesa_update_state(ctx);
1354
1355      ASSERT(ctx->Driver.TexImage1D);
1356      if (pixels) {
1357         (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1358                                   width, border, format, type, pixels,
1359                                   &ctx->Unpack, texObj, texImage);
1360      }
1361      else {
1362         GLubyte *dummy = make_null_texture(width, 1, 1, format);
1363         if (dummy) {
1364            (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1365                                      width, border,
1366                                      format, GL_UNSIGNED_BYTE, dummy,
1367                                      &_mesa_native_packing, texObj, texImage);
1368            FREE(dummy);
1369         }
1370      }
1371
1372      ASSERT(texImage->TexFormat);
1373      if (!texImage->FetchTexel) {
1374         /* If driver didn't explicitly set this, use the default */
1375         texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1376      }
1377      ASSERT(texImage->FetchTexel);
1378
1379      if (texImage->IsCompressed) {
1380         ASSERT(texImage->CompressedSize > 0);
1381      }
1382
1383      /* state update */
1384      texObj->Complete = GL_FALSE;
1385      ctx->NewState |= _NEW_TEXTURE;
1386   }
1387   else if (target == GL_PROXY_TEXTURE_1D) {
1388      /* Proxy texture: check for errors and update proxy state */
1389      GLenum error = texture_error_check(ctx, target, level, internalFormat,
1390                                         format, type, 1,
1391                                         postConvWidth, 1, 1, border);
1392      if (!error) {
1393         struct gl_texture_unit *texUnit;
1394         struct gl_texture_image *texImage;
1395         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1396         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1397         _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1398                                    border, internalFormat);
1399         ASSERT(ctx->Driver.TestProxyTexImage);
1400         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1401                                                  internalFormat, format, type,
1402                                                  postConvWidth, 1, 1, border);
1403      }
1404      if (error) {
1405         /* if error, clear all proxy texture image parameters */
1406         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
1407            clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
1408         }
1409      }
1410   }
1411   else {
1412      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1413      return;
1414   }
1415}
1416
1417
1418void
1419_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1420                  GLsizei width, GLsizei height, GLint border,
1421                  GLenum format, GLenum type,
1422                  const GLvoid *pixels )
1423{
1424   GLsizei postConvWidth = width, postConvHeight = height;
1425   GET_CURRENT_CONTEXT(ctx);
1426   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1427
1428   if (is_color_format(internalFormat)) {
1429      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1430					 &postConvHeight);
1431   }
1432
1433   if (target == GL_TEXTURE_2D ||
1434       (ctx->Extensions.ARB_texture_cube_map &&
1435        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1436        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1437      /* non-proxy target */
1438      struct gl_texture_unit *texUnit;
1439      struct gl_texture_object *texObj;
1440      struct gl_texture_image *texImage;
1441
1442      if (texture_error_check(ctx, target, level, internalFormat,
1443                              format, type, 2, postConvWidth, postConvHeight,
1444                              1, border)) {
1445         return;   /* error was recorded */
1446      }
1447
1448      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1449      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1450      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1451
1452      if (!texImage) {
1453         texImage = _mesa_alloc_texture_image();
1454         _mesa_set_tex_image(texObj, target, level, texImage);
1455         if (!texImage) {
1456            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1457            return;
1458         }
1459      }
1460      else if (texImage->Data) {
1461         /* free the old texture data */
1462         FREE(texImage->Data);
1463         texImage->Data = NULL;
1464      }
1465      clear_teximage_fields(texImage); /* not really needed, but helpful */
1466      _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight,
1467                                 1, border, internalFormat);
1468
1469      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1470         _mesa_update_state(ctx);
1471
1472      ASSERT(ctx->Driver.TexImage2D);
1473      if (pixels) {
1474         (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1475                                   width, height, border, format, type, pixels,
1476                                   &ctx->Unpack, texObj, texImage);
1477      }
1478      else {
1479         GLubyte *dummy = make_null_texture(width, height, 1, format);
1480         if (dummy) {
1481            (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1482                                      width, height, border,
1483                                      format, GL_UNSIGNED_BYTE, dummy,
1484                                      &_mesa_native_packing, texObj, texImage);
1485            FREE(dummy);
1486         }
1487      }
1488
1489      ASSERT(texImage->TexFormat);
1490      if (!texImage->FetchTexel) {
1491         /* If driver didn't explicitly set this, use the default */
1492         texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1493      }
1494      ASSERT(texImage->FetchTexel);
1495
1496      if (texImage->IsCompressed) {
1497         ASSERT(texImage->CompressedSize > 0);
1498      }
1499
1500      /* state update */
1501      texObj->Complete = GL_FALSE;
1502      ctx->NewState |= _NEW_TEXTURE;
1503   }
1504   else if (target == GL_PROXY_TEXTURE_2D) {
1505      /* Proxy texture: check for errors and update proxy state */
1506      GLenum error = texture_error_check(ctx, target, level, internalFormat,
1507				format, type, 2,
1508				postConvWidth, postConvHeight, 1, border);
1509      if (!error) {
1510         struct gl_texture_unit *texUnit;
1511         struct gl_texture_image *texImage;
1512         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1513         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1514         _mesa_init_teximage_fields(ctx, texImage, postConvWidth,
1515                                    postConvHeight, 1, border, internalFormat);
1516         ASSERT(ctx->Driver.TestProxyTexImage);
1517         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1518                                    internalFormat, format, type,
1519                                    postConvWidth, postConvHeight, 1, border);
1520      }
1521      if (error) {
1522         /* if error, clear all proxy texture image parameters */
1523         const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
1524            ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
1525         if (level >= 0 && level < maxLevels) {
1526            clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
1527         }
1528      }
1529   }
1530   else {
1531      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1532      return;
1533   }
1534}
1535
1536
1537/*
1538 * Called by the API or display list executor.
1539 * Note that width and height include the border.
1540 */
1541void
1542_mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
1543                  GLsizei width, GLsizei height, GLsizei depth,
1544                  GLint border, GLenum format, GLenum type,
1545                  const GLvoid *pixels )
1546{
1547   GET_CURRENT_CONTEXT(ctx);
1548   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1549
1550   if (target == GL_TEXTURE_3D) {
1551      struct gl_texture_unit *texUnit;
1552      struct gl_texture_object *texObj;
1553      struct gl_texture_image *texImage;
1554
1555      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
1556                              format, type, 3, width, height, depth, border)) {
1557         return;   /* error was recorded */
1558      }
1559
1560      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1561      texObj = _mesa_select_tex_object(ctx, texUnit, target);
1562      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1563
1564      if (!texImage) {
1565         texImage = _mesa_alloc_texture_image();
1566         texObj->Image[level] = texImage;
1567         if (!texImage) {
1568            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1569            return;
1570         }
1571      }
1572      else if (texImage->Data) {
1573         FREE(texImage->Data);
1574         texImage->Data = NULL;
1575      }
1576      clear_teximage_fields(texImage); /* not really needed, but helpful */
1577      _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
1578                                 internalFormat);
1579
1580      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1581         _mesa_update_state(ctx);
1582
1583      ASSERT(ctx->Driver.TexImage3D);
1584      if (pixels) {
1585         (*ctx->Driver.TexImage3D)(ctx, target, level, (GLint) internalFormat,
1586                                   width, height, depth, border,
1587                                   format, type, pixels,
1588                                   &ctx->Unpack, texObj, texImage);
1589      }
1590      else {
1591         GLubyte *dummy = make_null_texture(width, height, depth, format);
1592         if (dummy) {
1593            (*ctx->Driver.TexImage3D)(ctx, target, level,
1594                                      (GLint) internalFormat,
1595                                      width, height, depth, border,
1596                                      format, GL_UNSIGNED_BYTE, dummy,
1597                                      &_mesa_native_packing, texObj, texImage);
1598            FREE(dummy);
1599         }
1600      }
1601
1602      ASSERT(texImage->TexFormat);
1603      if (!texImage->FetchTexel) {
1604         /* If driver didn't explicitly set this, use the default */
1605         texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
1606      }
1607      ASSERT(texImage->FetchTexel);
1608
1609      if (texImage->IsCompressed) {
1610         ASSERT(texImage->CompressedSize > 0);
1611      }
1612
1613      /* state update */
1614      texObj->Complete = GL_FALSE;
1615      ctx->NewState |= _NEW_TEXTURE;
1616   }
1617   else if (target == GL_PROXY_TEXTURE_3D) {
1618      /* Proxy texture: check for errors and update proxy state */
1619      GLenum error = texture_error_check(ctx, target, level, internalFormat,
1620                                format, type, 3, width, height, depth, border);
1621      if (!error) {
1622         struct gl_texture_unit *texUnit;
1623         struct gl_texture_image *texImage;
1624         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1625         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1626         _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
1627                                    border, internalFormat);
1628         ASSERT(ctx->Driver.TestProxyTexImage);
1629         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1630                                                 internalFormat, format, type,
1631                                                 width, height, depth, border);
1632      }
1633      if (error) {
1634         /* if error, clear all proxy texture image parameters */
1635         if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
1636            clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
1637         }
1638      }
1639   }
1640   else {
1641      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1642      return;
1643   }
1644}
1645
1646
1647void
1648_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1649                     GLsizei width, GLsizei height, GLsizei depth,
1650                     GLint border, GLenum format, GLenum type,
1651                     const GLvoid *pixels )
1652{
1653   _mesa_TexImage3D(target, level, internalFormat, width, height,
1654                    depth, border, format, type, pixels);
1655}
1656
1657
1658
1659void
1660_mesa_TexSubImage1D( GLenum target, GLint level,
1661                     GLint xoffset, GLsizei width,
1662                     GLenum format, GLenum type,
1663                     const GLvoid *pixels )
1664{
1665   GLsizei postConvWidth = width;
1666   struct gl_texture_unit *texUnit;
1667   struct gl_texture_object *texObj;
1668   struct gl_texture_image *texImage;
1669   GET_CURRENT_CONTEXT(ctx);
1670   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1671
1672   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1673      _mesa_update_state(ctx);
1674
1675   /* XXX should test internal format */
1676   if (is_color_format(format)) {
1677      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1678   }
1679
1680   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1681                              postConvWidth, 1, 1, format, type)) {
1682      return;   /* error was detected */
1683   }
1684
1685   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1686   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1687   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1688   assert(texImage);
1689
1690   if (width == 0 || !pixels)
1691      return;  /* no-op, not an error */
1692
1693   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
1694   xoffset += texImage->Border;
1695
1696   ASSERT(ctx->Driver.TexSubImage1D);
1697   (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
1698                                format, type, pixels, &ctx->Unpack,
1699                                texObj, texImage);
1700   ctx->NewState |= _NEW_TEXTURE;
1701}
1702
1703
1704void
1705_mesa_TexSubImage2D( GLenum target, GLint level,
1706                     GLint xoffset, GLint yoffset,
1707                     GLsizei width, GLsizei height,
1708                     GLenum format, GLenum type,
1709                     const GLvoid *pixels )
1710{
1711   GLsizei postConvWidth = width, postConvHeight = height;
1712   struct gl_texture_unit *texUnit;
1713   struct gl_texture_object *texObj;
1714   struct gl_texture_image *texImage;
1715   GET_CURRENT_CONTEXT(ctx);
1716   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1717
1718   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1719      _mesa_update_state(ctx);
1720
1721   /* XXX should test internal format */
1722   if (is_color_format(format)) {
1723      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1724                                         &postConvHeight);
1725   }
1726
1727   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1728                             postConvWidth, postConvHeight, 1, format, type)) {
1729      return;   /* error was detected */
1730   }
1731
1732   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1733   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1734   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1735   assert(texImage);
1736
1737   if (width == 0 || height == 0 || !pixels)
1738      return;  /* no-op, not an error */
1739
1740   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
1741   xoffset += texImage->Border;
1742   yoffset += texImage->Border;
1743
1744   ASSERT(ctx->Driver.TexSubImage2D);
1745   (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
1746                                width, height, format, type, pixels,
1747                                &ctx->Unpack, texObj, texImage);
1748   ctx->NewState |= _NEW_TEXTURE;
1749}
1750
1751
1752
1753void
1754_mesa_TexSubImage3D( GLenum target, GLint level,
1755                     GLint xoffset, GLint yoffset, GLint zoffset,
1756                     GLsizei width, GLsizei height, GLsizei depth,
1757                     GLenum format, GLenum type,
1758                     const GLvoid *pixels )
1759{
1760   struct gl_texture_unit *texUnit;
1761   struct gl_texture_object *texObj;
1762   struct gl_texture_image *texImage;
1763   GET_CURRENT_CONTEXT(ctx);
1764   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1765
1766   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1767      _mesa_update_state(ctx);
1768
1769   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1770                              width, height, depth, format, type)) {
1771      return;   /* error was detected */
1772   }
1773
1774   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1775   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1776   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1777   assert(texImage);
1778
1779   if (width == 0 || height == 0 || height == 0 || !pixels)
1780      return;  /* no-op, not an error */
1781
1782   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
1783   xoffset += texImage->Border;
1784   yoffset += texImage->Border;
1785   zoffset += texImage->Border;
1786
1787   ASSERT(ctx->Driver.TexSubImage3D);
1788   (*ctx->Driver.TexSubImage3D)(ctx, target, level,
1789                                xoffset, yoffset, zoffset,
1790                                width, height, depth,
1791                                format, type, pixels,
1792                                &ctx->Unpack, texObj, texImage );
1793   ctx->NewState |= _NEW_TEXTURE;
1794}
1795
1796
1797
1798void
1799_mesa_CopyTexImage1D( GLenum target, GLint level,
1800                      GLenum internalFormat,
1801                      GLint x, GLint y,
1802                      GLsizei width, GLint border )
1803{
1804   struct gl_texture_unit *texUnit;
1805   struct gl_texture_object *texObj;
1806   struct gl_texture_image *texImage;
1807   GLsizei postConvWidth = width;
1808   GET_CURRENT_CONTEXT(ctx);
1809   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1810
1811   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1812      _mesa_update_state(ctx);
1813
1814   if (is_color_format(internalFormat)) {
1815      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1816   }
1817
1818   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1819                               postConvWidth, 1, border))
1820      return;
1821
1822   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1823   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1824   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1825   if (!texImage) {
1826      texImage = _mesa_alloc_texture_image();
1827      _mesa_set_tex_image(texObj, target, level, texImage);
1828      if (!texImage) {
1829         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
1830         return;
1831      }
1832   }
1833   else if (texImage->Data) {
1834      /* free the old texture data */
1835      FREE(texImage->Data);
1836      texImage->Data = NULL;
1837   }
1838
1839   clear_teximage_fields(texImage); /* not really needed, but helpful */
1840   _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1841                              border, internalFormat);
1842
1843
1844   ASSERT(ctx->Driver.CopyTexImage1D);
1845   (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
1846                                 x, y, width, border);
1847
1848   ASSERT(texImage->TexFormat);
1849   if (!texImage->FetchTexel) {
1850      /* If driver didn't explicitly set this, use the default */
1851      texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1852   }
1853   ASSERT(texImage->FetchTexel);
1854
1855   /* state update */
1856   texObj->Complete = GL_FALSE;
1857   ctx->NewState |= _NEW_TEXTURE;
1858}
1859
1860
1861
1862void
1863_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1864                      GLint x, GLint y, GLsizei width, GLsizei height,
1865                      GLint border )
1866{
1867   struct gl_texture_unit *texUnit;
1868   struct gl_texture_object *texObj;
1869   struct gl_texture_image *texImage;
1870   GLsizei postConvWidth = width, postConvHeight = height;
1871   GET_CURRENT_CONTEXT(ctx);
1872   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1873
1874   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1875      _mesa_update_state(ctx);
1876
1877   if (is_color_format(internalFormat)) {
1878      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1879                                         &postConvHeight);
1880   }
1881
1882   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1883                               postConvWidth, postConvHeight, border))
1884      return;
1885
1886   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1887   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1888   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1889   if (!texImage) {
1890      texImage = _mesa_alloc_texture_image();
1891      _mesa_set_tex_image(texObj, target, level, texImage);
1892      if (!texImage) {
1893         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
1894         return;
1895      }
1896   }
1897   else if (texImage->Data) {
1898      /* free the old texture data */
1899      FREE(texImage->Data);
1900      texImage->Data = NULL;
1901   }
1902
1903   clear_teximage_fields(texImage); /* not really needed, but helpful */
1904   _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
1905                              border, internalFormat);
1906
1907   ASSERT(ctx->Driver.CopyTexImage2D);
1908   (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
1909                                 x, y, width, height, border);
1910
1911   ASSERT(texImage->TexFormat);
1912   if (!texImage->FetchTexel) {
1913      /* If driver didn't explicitly set this, use the default */
1914      texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1915   }
1916   ASSERT(texImage->FetchTexel);
1917
1918   /* state update */
1919   texObj->Complete = GL_FALSE;
1920   ctx->NewState |= _NEW_TEXTURE;
1921}
1922
1923
1924
1925void
1926_mesa_CopyTexSubImage1D( GLenum target, GLint level,
1927                         GLint xoffset, GLint x, GLint y, GLsizei width )
1928{
1929   struct gl_texture_unit *texUnit;
1930   struct gl_texture_object *texObj;
1931   struct gl_texture_image *texImage;
1932   GLsizei postConvWidth = width;
1933   GET_CURRENT_CONTEXT(ctx);
1934   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1935
1936   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1937      _mesa_update_state(ctx);
1938
1939   /* XXX should test internal format */
1940   _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1941
1942   if (copytexsubimage_error_check(ctx, 1, target, level,
1943                                   xoffset, 0, 0, postConvWidth, 1))
1944      return;
1945
1946   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1947   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1948   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1949
1950   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
1951   xoffset += texImage->Border;
1952
1953   ASSERT(ctx->Driver.CopyTexSubImage1D);
1954   (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
1955   ctx->NewState |= _NEW_TEXTURE;
1956}
1957
1958
1959
1960void
1961_mesa_CopyTexSubImage2D( GLenum target, GLint level,
1962                         GLint xoffset, GLint yoffset,
1963                         GLint x, GLint y, GLsizei width, GLsizei height )
1964{
1965   struct gl_texture_unit *texUnit;
1966   struct gl_texture_object *texObj;
1967   struct gl_texture_image *texImage;
1968   GLsizei postConvWidth = width, postConvHeight = height;
1969   GET_CURRENT_CONTEXT(ctx);
1970   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1971
1972   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1973      _mesa_update_state(ctx);
1974
1975   /* XXX should test internal format */
1976   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
1977
1978   if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1979                                   postConvWidth, postConvHeight))
1980      return;
1981
1982   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1983   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1984   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1985
1986   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
1987   xoffset += texImage->Border;
1988   yoffset += texImage->Border;
1989
1990   ASSERT(ctx->Driver.CopyTexSubImage2D);
1991   (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
1992                                    xoffset, yoffset, x, y, width, height);
1993   ctx->NewState |= _NEW_TEXTURE;
1994}
1995
1996
1997
1998void
1999_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2000                         GLint xoffset, GLint yoffset, GLint zoffset,
2001                         GLint x, GLint y, GLsizei width, GLsizei height )
2002{
2003   struct gl_texture_unit *texUnit;
2004   struct gl_texture_object *texObj;
2005   struct gl_texture_image *texImage;
2006   GLsizei postConvWidth = width, postConvHeight = height;
2007   GET_CURRENT_CONTEXT(ctx);
2008   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2009
2010   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2011      _mesa_update_state(ctx);
2012
2013   /* XXX should test internal format */
2014   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2015
2016   if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2017                                   zoffset, postConvWidth, postConvHeight))
2018      return;
2019
2020   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2021   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2022   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2023
2024   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2025   xoffset += texImage->Border;
2026   yoffset += texImage->Border;
2027   zoffset += texImage->Border;
2028
2029   ASSERT(ctx->Driver.CopyTexSubImage3D);
2030   (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2031                                    xoffset, yoffset, zoffset,
2032                                    x, y, width, height);
2033   ctx->NewState |= _NEW_TEXTURE;
2034}
2035
2036
2037
2038void
2039_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2040                              GLenum internalFormat, GLsizei width,
2041                              GLint border, GLsizei imageSize,
2042                              const GLvoid *data)
2043{
2044   GET_CURRENT_CONTEXT(ctx);
2045   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2046
2047   switch (internalFormat) {
2048      case GL_COMPRESSED_ALPHA_ARB:
2049      case GL_COMPRESSED_LUMINANCE_ARB:
2050      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2051      case GL_COMPRESSED_INTENSITY_ARB:
2052      case GL_COMPRESSED_RGB_ARB:
2053      case GL_COMPRESSED_RGBA_ARB:
2054         _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2055         return;
2056      default:
2057         /* silence compiler warning */
2058         ;
2059   }
2060
2061   if (target == GL_TEXTURE_1D) {
2062      struct gl_texture_unit *texUnit;
2063      struct gl_texture_object *texObj;
2064      struct gl_texture_image *texImage;
2065
2066      if (texture_error_check(ctx, target, level, internalFormat,
2067                              GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2068         return;   /* error in texture image was detected */
2069      }
2070
2071      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2072      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2073      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2074
2075      if (!texImage) {
2076         texImage = _mesa_alloc_texture_image();
2077         texObj->Image[level] = texImage;
2078         if (!texImage) {
2079            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2080            return;
2081         }
2082      }
2083      else if (texImage->Data) {
2084         FREE(texImage->Data);
2085         texImage->Data = NULL;
2086      }
2087
2088      _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
2089                                 border, internalFormat);
2090
2091      if (ctx->Extensions.ARB_texture_compression) {
2092         ASSERT(ctx->Driver.CompressedTexImage1D);
2093         (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2094                                             internalFormat, width, border,
2095                                             imageSize, data,
2096                                             texObj, texImage);
2097         ASSERT(texImage->CompressedSize > 0); /* sanity */
2098      }
2099
2100      /* state update */
2101      texObj->Complete = GL_FALSE;
2102      ctx->NewState |= _NEW_TEXTURE;
2103   }
2104   else if (target == GL_PROXY_TEXTURE_1D) {
2105      /* Proxy texture: check for errors and update proxy state */
2106      GLenum error = texture_error_check(ctx, target, level, internalFormat,
2107                                    GL_NONE, GL_NONE, 1, width, 1, 1, border);
2108      if (!error) {
2109         struct gl_texture_unit *texUnit;
2110         struct gl_texture_image *texImage;
2111         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2112         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2113         _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
2114                                    border, internalFormat);
2115         ASSERT(ctx->Driver.TestProxyTexImage);
2116         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2117                                             internalFormat, GL_NONE, GL_NONE,
2118                                             width, 1, 1, border);
2119      }
2120      if (error) {
2121         /* if error, clear all proxy texture image parameters */
2122         if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2123            clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
2124         }
2125      }
2126   }
2127   else {
2128      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)");
2129      return;
2130   }
2131}
2132
2133
2134void
2135_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2136                              GLenum internalFormat, GLsizei width,
2137                              GLsizei height, GLint border, GLsizei imageSize,
2138                              const GLvoid *data)
2139{
2140   GET_CURRENT_CONTEXT(ctx);
2141   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2142
2143   switch (internalFormat) {
2144      case GL_COMPRESSED_ALPHA_ARB:
2145      case GL_COMPRESSED_LUMINANCE_ARB:
2146      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2147      case GL_COMPRESSED_INTENSITY_ARB:
2148      case GL_COMPRESSED_RGB_ARB:
2149      case GL_COMPRESSED_RGBA_ARB:
2150         _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2151         return;
2152      default:
2153         /* silence compiler warning */
2154         ;
2155   }
2156
2157   if (target == GL_TEXTURE_2D ||
2158       (ctx->Extensions.ARB_texture_cube_map &&
2159        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2160        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2161      struct gl_texture_unit *texUnit;
2162      struct gl_texture_object *texObj;
2163      struct gl_texture_image *texImage;
2164
2165      if (texture_error_check(ctx, target, level, internalFormat,
2166                              GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2167         return;   /* error in texture image was detected */
2168      }
2169
2170      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2171      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2172      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2173
2174      if (!texImage) {
2175         texImage = _mesa_alloc_texture_image();
2176         texObj->Image[level] = texImage;
2177         if (!texImage) {
2178            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2179            return;
2180         }
2181      }
2182      else if (texImage->Data) {
2183         FREE(texImage->Data);
2184         texImage->Data = NULL;
2185      }
2186
2187      _mesa_init_teximage_fields(ctx, texImage, width, height, 1, border,
2188                                 internalFormat);
2189
2190      if (ctx->Extensions.ARB_texture_compression) {
2191         ASSERT(ctx->Driver.CompressedTexImage2D);
2192         (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
2193                                             internalFormat, width, height,
2194                                             border, imageSize, data,
2195                                             texObj, texImage);
2196         ASSERT(texImage->CompressedSize > 0); /* sanity */
2197      }
2198
2199      /* state update */
2200      texObj->Complete = GL_FALSE;
2201      ctx->NewState |= _NEW_TEXTURE;
2202   }
2203   else if (target == GL_PROXY_TEXTURE_2D) {
2204      /* Proxy texture: check for errors and update proxy state */
2205      GLenum error = texture_error_check(ctx, target, level, internalFormat,
2206                                GL_NONE, GL_NONE, 2, width, height, 1, border);
2207      if (!error) {
2208         struct gl_texture_unit *texUnit;
2209         struct gl_texture_image *texImage;
2210         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2211         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2212         _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
2213                                    border, internalFormat);
2214         ASSERT(ctx->Driver.TestProxyTexImage);
2215         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2216                                              internalFormat, GL_NONE, GL_NONE,
2217                                              width, height, 1, border);
2218      }
2219      if (error) {
2220         /* if error, clear all proxy texture image parameters */
2221         const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
2222            ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
2223         if (level >= 0 && level < maxLevels) {
2224            clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
2225         }
2226      }
2227   }
2228   else {
2229      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)");
2230      return;
2231   }
2232}
2233
2234
2235void
2236_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2237                              GLenum internalFormat, GLsizei width,
2238                              GLsizei height, GLsizei depth, GLint border,
2239                              GLsizei imageSize, const GLvoid *data)
2240{
2241   GET_CURRENT_CONTEXT(ctx);
2242   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2243
2244   switch (internalFormat) {
2245      case GL_COMPRESSED_ALPHA_ARB:
2246      case GL_COMPRESSED_LUMINANCE_ARB:
2247      case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2248      case GL_COMPRESSED_INTENSITY_ARB:
2249      case GL_COMPRESSED_RGB_ARB:
2250      case GL_COMPRESSED_RGBA_ARB:
2251         _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
2252         return;
2253      default:
2254         /* silence compiler warning */
2255         ;
2256   }
2257
2258   if (target == GL_TEXTURE_3D) {
2259      struct gl_texture_unit *texUnit;
2260      struct gl_texture_object *texObj;
2261      struct gl_texture_image *texImage;
2262
2263      if (texture_error_check(ctx, target, level, internalFormat,
2264                          GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2265         return;   /* error in texture image was detected */
2266      }
2267
2268      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2269      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2270      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2271
2272      if (!texImage) {
2273         texImage = _mesa_alloc_texture_image();
2274         texObj->Image[level] = texImage;
2275         if (!texImage) {
2276            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2277            return;
2278         }
2279      }
2280      else if (texImage->Data) {
2281         FREE(texImage->Data);
2282         texImage->Data = NULL;
2283      }
2284
2285      _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
2286                                 internalFormat);
2287
2288      if (ctx->Extensions.ARB_texture_compression) {
2289         ASSERT(ctx->Driver.CompressedTexImage3D);
2290         (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
2291                                             internalFormat,
2292                                             width, height, depth,
2293                                             border, imageSize, data,
2294                                             texObj, texImage);
2295         ASSERT(texImage->CompressedSize > 0); /* sanity */
2296      }
2297
2298      /* state update */
2299      texObj->Complete = GL_FALSE;
2300      ctx->NewState |= _NEW_TEXTURE;
2301   }
2302   else if (target == GL_PROXY_TEXTURE_3D) {
2303      /* Proxy texture: check for errors and update proxy state */
2304      GLenum error = texture_error_check(ctx, target, level, internalFormat,
2305                            GL_NONE, GL_NONE, 1, width, height, depth, border);
2306      if (!error) {
2307         struct gl_texture_unit *texUnit;
2308         struct gl_texture_image *texImage;
2309         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2310         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2311         _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
2312                                    border, internalFormat);
2313         ASSERT(ctx->Driver.TestProxyTexImage);
2314         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2315                                             internalFormat, GL_NONE, GL_NONE,
2316                                             width, height, depth, border);
2317      }
2318      if (error) {
2319         /* if error, clear all proxy texture image parameters */
2320         if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
2321            clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
2322         }
2323      }
2324   }
2325   else {
2326      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)");
2327      return;
2328   }
2329}
2330
2331
2332void
2333_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2334                                 GLsizei width, GLenum format,
2335                                 GLsizei imageSize, const GLvoid *data)
2336{
2337   struct gl_texture_unit *texUnit;
2338   struct gl_texture_object *texObj;
2339   struct gl_texture_image *texImage;
2340   GET_CURRENT_CONTEXT(ctx);
2341   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2342
2343   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2344                              width, 1, 1, format, GL_NONE)) {
2345      return;   /* error was detected */
2346   }
2347
2348   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2349   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2350   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2351   assert(texImage);
2352
2353   if (width == 0 || !data)
2354      return;  /* no-op, not an error */
2355
2356   if (ctx->Driver.CompressedTexSubImage1D) {
2357      (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
2358                                             xoffset, width,
2359                                             format, imageSize, data,
2360                                             texObj, texImage);
2361   }
2362   ctx->NewState |= _NEW_TEXTURE;
2363}
2364
2365
2366void
2367_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2368                                 GLint yoffset, GLsizei width, GLsizei height,
2369                                 GLenum format, GLsizei imageSize,
2370                                 const GLvoid *data)
2371{
2372   struct gl_texture_unit *texUnit;
2373   struct gl_texture_object *texObj;
2374   struct gl_texture_image *texImage;
2375   GET_CURRENT_CONTEXT(ctx);
2376   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2377
2378   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2379                              width, height, 1, format, GL_NONE)) {
2380      return;   /* error was detected */
2381   }
2382
2383   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2384   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2385   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2386   assert(texImage);
2387
2388   if (width == 0 || height == 0 || !data)
2389      return;  /* no-op, not an error */
2390
2391   if (ctx->Driver.CompressedTexSubImage2D) {
2392      (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
2393                                             xoffset, yoffset, width, height,
2394                                             format, imageSize, data,
2395                                             texObj, texImage);
2396   }
2397   ctx->NewState |= _NEW_TEXTURE;
2398}
2399
2400
2401void
2402_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2403                                 GLint yoffset, GLint zoffset, GLsizei width,
2404                                 GLsizei height, GLsizei depth, GLenum format,
2405                                 GLsizei imageSize, const GLvoid *data)
2406{
2407   struct gl_texture_unit *texUnit;
2408   struct gl_texture_object *texObj;
2409   struct gl_texture_image *texImage;
2410   GET_CURRENT_CONTEXT(ctx);
2411   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2412
2413   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2414                              width, height, depth, format, GL_NONE)) {
2415      return;   /* error was detected */
2416   }
2417
2418   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2419   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2420   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2421   assert(texImage);
2422
2423   if (width == 0 || height == 0 || depth == 0 || !data)
2424      return;  /* no-op, not an error */
2425
2426   if (ctx->Driver.CompressedTexSubImage3D) {
2427      (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
2428                                             xoffset, yoffset, zoffset,
2429                                             width, height, depth,
2430                                             format, imageSize, data,
2431                                             texObj, texImage);
2432   }
2433   ctx->NewState |= _NEW_TEXTURE;
2434}
2435
2436
2437void
2438_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
2439{
2440   const struct gl_texture_unit *texUnit;
2441   const struct gl_texture_object *texObj;
2442   struct gl_texture_image *texImage;
2443   GLint maxLevels;
2444   GET_CURRENT_CONTEXT(ctx);
2445   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2446
2447   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2448   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2449   if (!texObj) {
2450      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
2451      return;
2452   }
2453
2454   if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
2455      maxLevels = ctx->Const.MaxTextureLevels;
2456   }
2457   else if (target == GL_TEXTURE_3D) {
2458      maxLevels = ctx->Const.Max3DTextureLevels;
2459   }
2460   else {
2461      maxLevels = ctx->Const.MaxCubeTextureLevels;
2462   }
2463
2464   ASSERT(maxLevels > 0);
2465
2466   if (level < 0 || level >= maxLevels) {
2467      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2468      return;
2469   }
2470
2471   if (is_proxy_target(target)) {
2472      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
2473      return;
2474   }
2475
2476   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2477   if (!texImage) {
2478      /* probably invalid mipmap level */
2479      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2480      return;
2481   }
2482
2483   if (!texImage->IsCompressed) {
2484      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
2485      return;
2486   }
2487
2488   if (!img)
2489      return;
2490
2491   if (ctx->Extensions.ARB_texture_compression) {
2492      ASSERT(ctx->Driver.GetCompressedTexImage);
2493      (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
2494                                           texImage);
2495   }
2496}
2497