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