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