teximage.c revision 77ee31930a1b0cc7766939415f4f04ed6a1fa4ac
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/**
27 * \file teximage.c
28 * Texture image-related functions.
29 */
30
31
32#include "glheader.h"
33#include "bufferobj.h"
34#include "context.h"
35#include "convolve.h"
36#include "image.h"
37#include "imports.h"
38#include "macros.h"
39#include "state.h"
40#include "texcompress.h"
41#include "texformat.h"
42#include "teximage.h"
43#include "texstate.h"
44#include "texstore.h"
45#include "mtypes.h"
46
47
48/**
49 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
50 * elsewhere.
51 */
52void *
53_mesa_alloc_texmemory(GLsizei bytes)
54{
55   return _mesa_align_malloc(bytes, 512);
56}
57
58
59/**
60 * Free texture memory allocated with _mesa_alloc_texmemory()
61 */
62void
63_mesa_free_texmemory(void *m)
64{
65   _mesa_align_free(m);
66}
67
68
69
70
71#if 0
72static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
73{
74#if CHAN_TYPE == GL_FLOAT
75   _mesa_problem(NULL, "PrintTexture doesn't support float channels");
76#else
77   GLuint i, j, c;
78   const GLchan *data = (const GLchan *) img->Data;
79
80   if (!data) {
81      _mesa_printf("No texture data\n");
82      return;
83   }
84
85   switch (img->Format) {
86      case GL_ALPHA:
87      case GL_LUMINANCE:
88      case GL_INTENSITY:
89      case GL_COLOR_INDEX:
90         c = 1;
91         break;
92      case GL_LUMINANCE_ALPHA:
93         c = 2;
94         break;
95      case GL_RGB:
96         c = 3;
97         break;
98      case GL_RGBA:
99         c = 4;
100         break;
101      default:
102         _mesa_problem(NULL, "error in PrintTexture\n");
103         return;
104   }
105
106   for (i = 0; i < img->Height; i++) {
107      for (j = 0; j < img->Width; j++) {
108         if (c==1)
109            _mesa_printf("%02x  ", data[0]);
110         else if (c==2)
111            _mesa_printf("%02x%02x  ", data[0], data[1]);
112         else if (c==3)
113            _mesa_printf("%02x%02x%02x  ", data[0], data[1], data[2]);
114         else if (c==4)
115            _mesa_printf("%02x%02x%02x%02x  ", data[0], data[1], data[2], data[3]);
116         data += (img->RowStride - img->Width) * c;
117      }
118      _mesa_printf("\n");
119   }
120#endif
121}
122#endif
123
124
125/*
126 * Compute floor(log_base_2(n)).
127 * If n < 0 return -1.
128 */
129static int
130logbase2( int n )
131{
132   GLint i = 1;
133   GLint log2 = 0;
134
135   if (n < 0)
136      return -1;
137
138   if (n == 0)
139      return 0;
140
141   while ( n > i ) {
142      i *= 2;
143      log2++;
144   }
145   if (i != n) {
146      return log2 - 1;
147   }
148   else {
149      return log2;
150   }
151}
152
153
154
155/**
156 * Return the simple base format for a given internal texture format.
157 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
158 *
159 * \param ctx GL context.
160 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
161 *
162 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
163 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
164 *
165 * This is the format which is used during texture application (i.e. the
166 * texture format and env mode determine the arithmetic used.
167 */
168GLint
169_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
170{
171   switch (internalFormat) {
172      case GL_ALPHA:
173      case GL_ALPHA4:
174      case GL_ALPHA8:
175      case GL_ALPHA12:
176      case GL_ALPHA16:
177         return GL_ALPHA;
178      case 1:
179      case GL_LUMINANCE:
180      case GL_LUMINANCE4:
181      case GL_LUMINANCE8:
182      case GL_LUMINANCE12:
183      case GL_LUMINANCE16:
184         return GL_LUMINANCE;
185      case 2:
186      case GL_LUMINANCE_ALPHA:
187      case GL_LUMINANCE4_ALPHA4:
188      case GL_LUMINANCE6_ALPHA2:
189      case GL_LUMINANCE8_ALPHA8:
190      case GL_LUMINANCE12_ALPHA4:
191      case GL_LUMINANCE12_ALPHA12:
192      case GL_LUMINANCE16_ALPHA16:
193         return GL_LUMINANCE_ALPHA;
194      case GL_INTENSITY:
195      case GL_INTENSITY4:
196      case GL_INTENSITY8:
197      case GL_INTENSITY12:
198      case GL_INTENSITY16:
199         return GL_INTENSITY;
200      case 3:
201      case GL_RGB:
202      case GL_R3_G3_B2:
203      case GL_RGB4:
204      case GL_RGB5:
205      case GL_RGB8:
206      case GL_RGB10:
207      case GL_RGB12:
208      case GL_RGB16:
209         return GL_RGB;
210      case 4:
211      case GL_RGBA:
212      case GL_RGBA2:
213      case GL_RGBA4:
214      case GL_RGB5_A1:
215      case GL_RGBA8:
216      case GL_RGB10_A2:
217      case GL_RGBA12:
218      case GL_RGBA16:
219         return GL_RGBA;
220      default:
221         ; /* fallthrough */
222   }
223
224   if (ctx->Extensions.EXT_paletted_texture) {
225      switch (internalFormat) {
226         case GL_COLOR_INDEX:
227         case GL_COLOR_INDEX1_EXT:
228         case GL_COLOR_INDEX2_EXT:
229         case GL_COLOR_INDEX4_EXT:
230         case GL_COLOR_INDEX8_EXT:
231         case GL_COLOR_INDEX12_EXT:
232         case GL_COLOR_INDEX16_EXT:
233            return GL_COLOR_INDEX;
234         default:
235            ; /* fallthrough */
236      }
237   }
238
239   if (ctx->Extensions.SGIX_depth_texture ||
240       ctx->Extensions.ARB_depth_texture) {
241      switch (internalFormat) {
242         case GL_DEPTH_COMPONENT:
243         case GL_DEPTH_COMPONENT16_SGIX:
244         case GL_DEPTH_COMPONENT24_SGIX:
245         case GL_DEPTH_COMPONENT32_SGIX:
246            return GL_DEPTH_COMPONENT;
247         default:
248            ; /* fallthrough */
249      }
250   }
251
252   if (ctx->Extensions.ARB_texture_compression) {
253      switch (internalFormat) {
254         case GL_COMPRESSED_ALPHA:
255            return GL_ALPHA;
256         case GL_COMPRESSED_LUMINANCE:
257            return GL_LUMINANCE;
258         case GL_COMPRESSED_LUMINANCE_ALPHA:
259            return GL_LUMINANCE_ALPHA;
260         case GL_COMPRESSED_INTENSITY:
261            return GL_INTENSITY;
262         case GL_COMPRESSED_RGB:
263            return GL_RGB;
264         case GL_COMPRESSED_RGBA:
265            return GL_RGBA;
266         default:
267            ; /* fallthrough */
268      }
269   }
270
271   if (ctx->Extensions.TDFX_texture_compression_FXT1) {
272      switch (internalFormat) {
273         case GL_COMPRESSED_RGB_FXT1_3DFX:
274            return GL_RGB;
275         case GL_COMPRESSED_RGBA_FXT1_3DFX:
276            return GL_RGBA;
277         default:
278            ; /* fallthrough */
279      }
280   }
281
282   if (ctx->Extensions.EXT_texture_compression_s3tc) {
283      switch (internalFormat) {
284         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
285            return GL_RGB;
286         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
287         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
288         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
289            return GL_RGBA;
290         default:
291            ; /* fallthrough */
292      }
293   }
294
295   if (ctx->Extensions.S3_s3tc) {
296      switch (internalFormat) {
297         case GL_RGB_S3TC:
298         case GL_RGB4_S3TC:
299            return GL_RGB;
300         case GL_RGBA_S3TC:
301         case GL_RGBA4_S3TC:
302            return GL_RGBA;
303         default:
304            ; /* fallthrough */
305      }
306   }
307
308   if (ctx->Extensions.MESA_ycbcr_texture) {
309      if (internalFormat == GL_YCBCR_MESA)
310         return GL_YCBCR_MESA;
311   }
312
313   if (ctx->Extensions.ARB_texture_float) {
314      switch (internalFormat) {
315         case GL_ALPHA16F_ARB:
316         case GL_ALPHA32F_ARB:
317            return GL_ALPHA;
318         case GL_RGBA16F_ARB:
319         case GL_RGBA32F_ARB:
320            return GL_RGBA;
321         case GL_RGB16F_ARB:
322         case GL_RGB32F_ARB:
323            return GL_RGB;
324         case GL_INTENSITY16F_ARB:
325         case GL_INTENSITY32F_ARB:
326            return GL_INTENSITY;
327         case GL_LUMINANCE16F_ARB:
328         case GL_LUMINANCE32F_ARB:
329            return GL_LUMINANCE;
330         case GL_LUMINANCE_ALPHA16F_ARB:
331         case GL_LUMINANCE_ALPHA32F_ARB:
332            return GL_LUMINANCE_ALPHA;
333         default:
334            ; /* fallthrough */
335      }
336   }
337
338   if (ctx->Extensions.EXT_packed_depth_stencil) {
339      switch (internalFormat) {
340         case GL_DEPTH_STENCIL_EXT:
341         case GL_DEPTH24_STENCIL8_EXT:
342            return GL_DEPTH_STENCIL_EXT;
343         default:
344            ; /* fallthrough */
345      }
346   }
347
348   return -1; /* error */
349}
350
351
352/**
353 * Test if the given image format is a color/RGBA format (i.e., not color
354 * index, depth, stencil, etc).
355 * \param format  the image format value (may by an internal texture format)
356 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
357 */
358static GLboolean
359is_color_format(GLenum format)
360{
361   switch (format) {
362      case GL_RED:
363      case GL_GREEN:
364      case GL_BLUE:
365      case GL_ALPHA:
366      case GL_ALPHA4:
367      case GL_ALPHA8:
368      case GL_ALPHA12:
369      case GL_ALPHA16:
370      case 1:
371      case GL_LUMINANCE:
372      case GL_LUMINANCE4:
373      case GL_LUMINANCE8:
374      case GL_LUMINANCE12:
375      case GL_LUMINANCE16:
376      case 2:
377      case GL_LUMINANCE_ALPHA:
378      case GL_LUMINANCE4_ALPHA4:
379      case GL_LUMINANCE6_ALPHA2:
380      case GL_LUMINANCE8_ALPHA8:
381      case GL_LUMINANCE12_ALPHA4:
382      case GL_LUMINANCE12_ALPHA12:
383      case GL_LUMINANCE16_ALPHA16:
384      case GL_INTENSITY:
385      case GL_INTENSITY4:
386      case GL_INTENSITY8:
387      case GL_INTENSITY12:
388      case GL_INTENSITY16:
389      case 3:
390      case GL_RGB:
391      case GL_BGR:
392      case GL_R3_G3_B2:
393      case GL_RGB4:
394      case GL_RGB5:
395      case GL_RGB8:
396      case GL_RGB10:
397      case GL_RGB12:
398      case GL_RGB16:
399      case 4:
400      case GL_ABGR_EXT:
401      case GL_RGBA:
402      case GL_BGRA:
403      case GL_RGBA2:
404      case GL_RGBA4:
405      case GL_RGB5_A1:
406      case GL_RGBA8:
407      case GL_RGB10_A2:
408      case GL_RGBA12:
409      case GL_RGBA16:
410      /* float texture formats */
411      case GL_ALPHA16F_ARB:
412      case GL_ALPHA32F_ARB:
413      case GL_LUMINANCE16F_ARB:
414      case GL_LUMINANCE32F_ARB:
415      case GL_LUMINANCE_ALPHA16F_ARB:
416      case GL_LUMINANCE_ALPHA32F_ARB:
417      case GL_INTENSITY16F_ARB:
418      case GL_INTENSITY32F_ARB:
419      case GL_RGB16F_ARB:
420      case GL_RGB32F_ARB:
421      case GL_RGBA16F_ARB:
422      case GL_RGBA32F_ARB:
423      /* compressed formats */
424      case GL_COMPRESSED_ALPHA:
425      case GL_COMPRESSED_LUMINANCE:
426      case GL_COMPRESSED_LUMINANCE_ALPHA:
427      case GL_COMPRESSED_INTENSITY:
428      case GL_COMPRESSED_RGB:
429      case GL_COMPRESSED_RGBA:
430      case GL_RGB_S3TC:
431      case GL_RGB4_S3TC:
432      case GL_RGBA_S3TC:
433      case GL_RGBA4_S3TC:
434      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
435      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
436      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
437      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
438      case GL_COMPRESSED_RGB_FXT1_3DFX:
439      case GL_COMPRESSED_RGBA_FXT1_3DFX:
440         return GL_TRUE;
441      case GL_YCBCR_MESA:  /* not considered to be RGB */
442      default:
443         return GL_FALSE;
444   }
445}
446
447
448/**
449 * Test if the given image format is a color index format.
450 */
451static GLboolean
452is_index_format(GLenum format)
453{
454   switch (format) {
455      case GL_COLOR_INDEX:
456      case GL_COLOR_INDEX1_EXT:
457      case GL_COLOR_INDEX2_EXT:
458      case GL_COLOR_INDEX4_EXT:
459      case GL_COLOR_INDEX8_EXT:
460      case GL_COLOR_INDEX12_EXT:
461      case GL_COLOR_INDEX16_EXT:
462         return GL_TRUE;
463      default:
464         return GL_FALSE;
465   }
466}
467
468
469/**
470 * Test if the given image format is a depth component format.
471 */
472static GLboolean
473is_depth_format(GLenum format)
474{
475   switch (format) {
476      case GL_DEPTH_COMPONENT16_ARB:
477      case GL_DEPTH_COMPONENT24_ARB:
478      case GL_DEPTH_COMPONENT32_ARB:
479      case GL_DEPTH_COMPONENT:
480         return GL_TRUE;
481      default:
482         return GL_FALSE;
483   }
484}
485
486
487/**
488 * Test if the given image format is a YCbCr format.
489 */
490static GLboolean
491is_ycbcr_format(GLenum format)
492{
493   switch (format) {
494      case GL_YCBCR_MESA:
495         return GL_TRUE;
496      default:
497         return GL_FALSE;
498   }
499}
500
501
502/**
503 * Test if the given image format is a Depth/Stencil format.
504 */
505static GLboolean
506is_depthstencil_format(GLenum format)
507{
508   switch (format) {
509      case GL_DEPTH24_STENCIL8_EXT:
510      case GL_DEPTH_STENCIL_EXT:
511         return GL_TRUE;
512      default:
513         return GL_FALSE;
514   }
515}
516
517
518
519/**
520 * Test if it is a supported compressed format.
521 *
522 * \param internalFormat the internal format token provided by the user.
523 *
524 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
525 * GL_FALSE otherwise.
526 *
527 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
528 * are supported.
529 */
530static GLboolean
531is_compressed_format(GLcontext *ctx, GLenum internalFormat)
532{
533   (void) ctx;
534   switch (internalFormat) {
535      case GL_COMPRESSED_RGB_FXT1_3DFX:
536      case GL_COMPRESSED_RGBA_FXT1_3DFX:
537      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
538      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
539      case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
540      case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
541      case GL_RGB_S3TC:
542      case GL_RGB4_S3TC:
543      case GL_RGBA_S3TC:
544      case GL_RGBA4_S3TC:
545         return GL_TRUE;
546      default:
547         return GL_FALSE;
548   }
549}
550
551
552/**
553 * Store a gl_texture_image pointer in a gl_texture_object structure
554 * according to the target and level parameters.
555 *
556 * \param tObj texture object.
557 * \param target texture target.
558 * \param level image level.
559 * \param texImage texture image.
560 *
561 * This was basically prompted by the introduction of cube maps.
562 */
563void
564_mesa_set_tex_image(struct gl_texture_object *tObj,
565                    GLenum target, GLint level,
566                    struct gl_texture_image *texImage)
567{
568   ASSERT(tObj);
569   ASSERT(texImage);
570   switch (target) {
571      case GL_TEXTURE_1D:
572      case GL_TEXTURE_2D:
573      case GL_TEXTURE_3D:
574         tObj->Image[0][level] = texImage;
575         break;
576      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
577      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
578      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
579      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
580      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
581      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
582         {
583            GLuint face = ((GLuint) target -
584                           (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
585            tObj->Image[face][level] = texImage;
586         }
587         break;
588      case GL_TEXTURE_RECTANGLE_NV:
589         ASSERT(level == 0);
590         tObj->Image[0][level] = texImage;
591         break;
592      default:
593         _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
594         return;
595   }
596   /* Set the 'back' pointer */
597   texImage->TexObject = tObj;
598}
599
600
601/**
602 * Allocate a texture image structure.
603 *
604 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
605 * driver.
606 *
607 * \return a pointer to gl_texture_image struct with all fields initialized to
608 * zero.
609 */
610struct gl_texture_image *
611_mesa_new_texture_image( GLcontext *ctx )
612{
613   (void) ctx;
614   return CALLOC_STRUCT(gl_texture_image);
615}
616
617
618/**
619 * Free texture image data.
620 * This function is a fallback called via ctx->Driver.FreeTexImageData().
621 *
622 * \param teximage texture image.
623 *
624 * Free the texture image data if it's not marked as client data.
625 */
626void
627_mesa_free_texture_image_data(GLcontext *ctx,
628                              struct gl_texture_image *texImage)
629{
630   if (texImage->Data && !texImage->IsClientData) {
631      /* free the old texture data */
632      _mesa_free_texmemory(texImage->Data);
633   }
634
635   texImage->Data = NULL;
636}
637
638
639/**
640 * Free texture image.
641 *
642 * \param teximage texture image.
643 *
644 * Free the texture image structure and the associated image data.
645 */
646void
647_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
648{
649   if (texImage->Data) {
650      ctx->Driver.FreeTexImageData( ctx, texImage );
651   }
652   ASSERT(texImage->Data == NULL);
653   FREE( texImage );
654}
655
656
657/**
658 * Test if a target is a proxy target.
659 *
660 * \param target texture target.
661 *
662 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
663 */
664GLboolean
665_mesa_is_proxy_texture(GLenum target)
666{
667   return (target == GL_PROXY_TEXTURE_1D ||
668           target == GL_PROXY_TEXTURE_2D ||
669           target == GL_PROXY_TEXTURE_3D ||
670           target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
671           target == GL_PROXY_TEXTURE_RECTANGLE_NV);
672}
673
674
675/**
676 * Get the texture object that corresponds to the target of the given texture unit.
677 *
678 * \param ctx GL context.
679 * \param texUnit texture unit.
680 * \param target texture target.
681 *
682 * \return pointer to the texture object on success, or NULL on failure.
683 *
684 * \sa gl_texture_unit.
685 */
686struct gl_texture_object *
687_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
688                        GLenum target)
689{
690   switch (target) {
691      case GL_TEXTURE_1D:
692         return texUnit->Current1D;
693      case GL_PROXY_TEXTURE_1D:
694         return ctx->Texture.Proxy1D;
695      case GL_TEXTURE_2D:
696         return texUnit->Current2D;
697      case GL_PROXY_TEXTURE_2D:
698         return ctx->Texture.Proxy2D;
699      case GL_TEXTURE_3D:
700         return texUnit->Current3D;
701      case GL_PROXY_TEXTURE_3D:
702         return ctx->Texture.Proxy3D;
703      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
704      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
705      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
706      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
707      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
708      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
709      case GL_TEXTURE_CUBE_MAP_ARB:
710         return ctx->Extensions.ARB_texture_cube_map
711                ? texUnit->CurrentCubeMap : NULL;
712      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
713         return ctx->Extensions.ARB_texture_cube_map
714                ? ctx->Texture.ProxyCubeMap : NULL;
715      case GL_TEXTURE_RECTANGLE_NV:
716         return ctx->Extensions.NV_texture_rectangle
717                ? texUnit->CurrentRect : NULL;
718      case GL_PROXY_TEXTURE_RECTANGLE_NV:
719         return ctx->Extensions.NV_texture_rectangle
720                ? ctx->Texture.ProxyRect : NULL;
721      default:
722         _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
723         return NULL;
724   }
725}
726
727
728/**
729 * Get the texture image struct which corresponds to target and level
730 * of the given texture unit.
731 *
732 * \param ctx GL context.
733 * \param texUnit texture unit.
734 * \param target texture target.
735 * \param level image level.
736 *
737 * \return pointer to the texture image structure on success, or NULL on failure.
738 *
739 * \sa gl_texture_unit.
740 */
741struct gl_texture_image *
742_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
743                       GLenum target, GLint level)
744{
745   ASSERT(texUnit);
746   ASSERT(level < MAX_TEXTURE_LEVELS);
747   switch (target) {
748      case GL_TEXTURE_1D:
749         return texUnit->Current1D->Image[0][level];
750      case GL_PROXY_TEXTURE_1D:
751         return ctx->Texture.Proxy1D->Image[0][level];
752      case GL_TEXTURE_2D:
753         return texUnit->Current2D->Image[0][level];
754      case GL_PROXY_TEXTURE_2D:
755         return ctx->Texture.Proxy2D->Image[0][level];
756      case GL_TEXTURE_3D:
757         return texUnit->Current3D->Image[0][level];
758      case GL_PROXY_TEXTURE_3D:
759         return ctx->Texture.Proxy3D->Image[0][level];
760      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
761      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
762      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
763      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
764      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
765      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
766         if (ctx->Extensions.ARB_texture_cube_map) {
767	    GLuint face = ((GLuint) target -
768			   (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
769            return texUnit->CurrentCubeMap->Image[face][level];
770	 }
771         else
772            return NULL;
773      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
774         if (ctx->Extensions.ARB_texture_cube_map)
775            return ctx->Texture.ProxyCubeMap->Image[0][level];
776         else
777            return NULL;
778      case GL_TEXTURE_RECTANGLE_NV:
779         if (ctx->Extensions.NV_texture_rectangle) {
780            ASSERT(level == 0);
781            return texUnit->CurrentRect->Image[0][level];
782         }
783         else {
784            return NULL;
785         }
786      case GL_PROXY_TEXTURE_RECTANGLE_NV:
787         if (ctx->Extensions.NV_texture_rectangle) {
788            ASSERT(level == 0);
789            return ctx->Texture.ProxyRect->Image[0][level];
790         }
791         else {
792            return NULL;
793         }
794      default:
795         _mesa_problem(ctx, "bad target in _mesa_select_tex_image()");
796         return NULL;
797   }
798}
799
800
801/**
802 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
803 * it and install it.  Only return NULL if passed a bad parameter or run
804 * out of memory.
805 */
806struct gl_texture_image *
807_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
808                    GLenum target, GLint level)
809{
810   struct gl_texture_image *texImage;
811   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
812   if (!texImage) {
813      struct gl_texture_object *texObj;
814      texImage = ctx->Driver.NewTextureImage(ctx);
815      if (!texImage) {
816         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
817         return NULL;
818      }
819      texObj = _mesa_select_tex_object(ctx, texUnit, target);
820      ASSERT(texObj);
821      _mesa_set_tex_image(texObj, target, level, texImage);
822   }
823   return texImage;
824}
825
826
827/**
828 * Return pointer to the specified proxy texture image.
829 * Note that proxy textures are per-context, not per-texture unit.
830 * \return pointer to texture image or NULL if invalid target, invalid
831 *         level, or out of memory.
832 */
833struct gl_texture_image *
834_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
835{
836   struct gl_texture_image *texImage;
837
838   if (level < 0 )
839      return NULL;
840
841   switch (target) {
842   case GL_PROXY_TEXTURE_1D:
843      if (level >= ctx->Const.MaxTextureLevels)
844         return NULL;
845      texImage = ctx->Texture.Proxy1D->Image[0][level];
846      if (!texImage) {
847         texImage = ctx->Driver.NewTextureImage(ctx);
848         if (!texImage) {
849            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
850            return NULL;
851         }
852         ctx->Texture.Proxy1D->Image[0][level] = texImage;
853         /* Set the 'back' pointer */
854         texImage->TexObject = ctx->Texture.Proxy1D;
855      }
856      return texImage;
857   case GL_PROXY_TEXTURE_2D:
858      if (level >= ctx->Const.MaxTextureLevels)
859         return NULL;
860      texImage = ctx->Texture.Proxy2D->Image[0][level];
861      if (!texImage) {
862         texImage = ctx->Driver.NewTextureImage(ctx);
863         if (!texImage) {
864            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
865            return NULL;
866         }
867         ctx->Texture.Proxy2D->Image[0][level] = texImage;
868         /* Set the 'back' pointer */
869         texImage->TexObject = ctx->Texture.Proxy2D;
870      }
871      return texImage;
872   case GL_PROXY_TEXTURE_3D:
873      if (level >= ctx->Const.Max3DTextureLevels)
874         return NULL;
875      texImage = ctx->Texture.Proxy3D->Image[0][level];
876      if (!texImage) {
877         texImage = ctx->Driver.NewTextureImage(ctx);
878         if (!texImage) {
879            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
880            return NULL;
881         }
882         ctx->Texture.Proxy3D->Image[0][level] = texImage;
883         /* Set the 'back' pointer */
884         texImage->TexObject = ctx->Texture.Proxy3D;
885      }
886      return texImage;
887   case GL_PROXY_TEXTURE_CUBE_MAP:
888      if (level >= ctx->Const.MaxCubeTextureLevels)
889         return NULL;
890      texImage = ctx->Texture.ProxyCubeMap->Image[0][level];
891      if (!texImage) {
892         texImage = ctx->Driver.NewTextureImage(ctx);
893         if (!texImage) {
894            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
895            return NULL;
896         }
897         ctx->Texture.ProxyCubeMap->Image[0][level] = texImage;
898         /* Set the 'back' pointer */
899         texImage->TexObject = ctx->Texture.ProxyCubeMap;
900      }
901      return texImage;
902   case GL_PROXY_TEXTURE_RECTANGLE_NV:
903      if (level > 0)
904         return NULL;
905      texImage = ctx->Texture.ProxyRect->Image[0][level];
906      if (!texImage) {
907         texImage = ctx->Driver.NewTextureImage(ctx);
908         if (!texImage) {
909            _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
910            return NULL;
911         }
912         ctx->Texture.ProxyRect->Image[0][level] = texImage;
913         /* Set the 'back' pointer */
914         texImage->TexObject = ctx->Texture.ProxyRect;
915      }
916      return texImage;
917   default:
918      return NULL;
919   }
920}
921
922
923/**
924 * Get the maximum number of allowed mipmap levels.
925 *
926 * \param ctx GL context.
927 * \param target texture target.
928 *
929 * \return the maximum number of allowed mipmap levels for the given
930 * texture target, or zero if passed a bad target.
931 *
932 * \sa gl_constants.
933 */
934GLint
935_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
936{
937   switch (target) {
938   case GL_TEXTURE_1D:
939   case GL_PROXY_TEXTURE_1D:
940   case GL_TEXTURE_2D:
941   case GL_PROXY_TEXTURE_2D:
942      return ctx->Const.MaxTextureLevels;
943   case GL_TEXTURE_3D:
944   case GL_PROXY_TEXTURE_3D:
945      return ctx->Const.Max3DTextureLevels;
946   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
947   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
948   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
949   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
950   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
951   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
952   case GL_TEXTURE_CUBE_MAP_ARB:
953   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
954      return ctx->Const.MaxCubeTextureLevels;
955   case GL_TEXTURE_RECTANGLE_NV:
956   case GL_PROXY_TEXTURE_RECTANGLE_NV:
957      return 1;
958   default:
959      return 0; /* bad target */
960   }
961}
962
963
964
965#if 000 /* not used anymore */
966/*
967 * glTexImage[123]D can accept a NULL image pointer.  In this case we
968 * create a texture image with unspecified image contents per the OpenGL
969 * spec.
970 */
971static GLubyte *
972make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
973{
974   const GLint components = _mesa_components_in_format(format);
975   const GLint numPixels = width * height * depth;
976   GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
977
978#ifdef DEBUG
979   /*
980    * Let's see if anyone finds this.  If glTexImage2D() is called with
981    * a NULL image pointer then load the texture image with something
982    * interesting instead of leaving it indeterminate.
983    */
984   if (data) {
985      static const char message[8][32] = {
986         "   X   X  XXXXX   XXX     X    ",
987         "   XX XX  X      X   X   X X   ",
988         "   X X X  X      X      X   X  ",
989         "   X   X  XXXX    XXX   XXXXX  ",
990         "   X   X  X          X  X   X  ",
991         "   X   X  X      X   X  X   X  ",
992         "   X   X  XXXXX   XXX   X   X  ",
993         "                               "
994      };
995
996      GLubyte *imgPtr = data;
997      GLint h, i, j, k;
998      for (h = 0; h < depth; h++) {
999         for (i = 0; i < height; i++) {
1000            GLint srcRow = 7 - (i % 8);
1001            for (j = 0; j < width; j++) {
1002               GLint srcCol = j % 32;
1003               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
1004               for (k = 0; k < components; k++) {
1005                  *imgPtr++ = texel;
1006               }
1007            }
1008         }
1009      }
1010   }
1011#endif
1012
1013   return data;
1014}
1015#endif
1016
1017
1018
1019/**
1020 * Reset the fields of a gl_texture_image struct to zero.
1021 *
1022 * \param img texture image structure.
1023 *
1024 * This is called when a proxy texture test fails, we set all the
1025 * image members (except DriverData) to zero.
1026 * It's also used in glTexImage[123]D as a safeguard to be sure all
1027 * required fields get initialized properly by the Driver.TexImage[123]D
1028 * functions.
1029 */
1030static void
1031clear_teximage_fields(struct gl_texture_image *img)
1032{
1033   ASSERT(img);
1034   img->_BaseFormat = 0;
1035   img->InternalFormat = 0;
1036   img->Border = 0;
1037   img->Width = 0;
1038   img->Height = 0;
1039   img->Depth = 0;
1040   img->RowStride = 0;
1041   img->Width2 = 0;
1042   img->Height2 = 0;
1043   img->Depth2 = 0;
1044   img->WidthLog2 = 0;
1045   img->HeightLog2 = 0;
1046   img->DepthLog2 = 0;
1047   img->Data = NULL;
1048   img->TexFormat = &_mesa_null_texformat;
1049   img->FetchTexelc = NULL;
1050   img->FetchTexelf = NULL;
1051   img->IsCompressed = 0;
1052   img->CompressedSize = 0;
1053}
1054
1055
1056/**
1057 * Initialize basic fields of the gl_texture_image struct.
1058 *
1059 * \param ctx GL context.
1060 * \param target texture target.
1061 * \param img texture image structure to be initialized.
1062 * \param width image width.
1063 * \param height image height.
1064 * \param depth image depth.
1065 * \param border image border.
1066 * \param internalFormat internal format.
1067 *
1068 * Fills in the fields of \p img with the given information.
1069 * Note: width, height and depth include the border.
1070 */
1071void
1072_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
1073                           struct gl_texture_image *img,
1074                           GLsizei width, GLsizei height, GLsizei depth,
1075                           GLint border, GLenum internalFormat)
1076{
1077   ASSERT(img);
1078   img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
1079   ASSERT(img->_BaseFormat > 0);
1080   img->InternalFormat = internalFormat;
1081   img->Border = border;
1082   img->Width = width;
1083   img->Height = height;
1084   img->Depth = depth;
1085   img->RowStride = width;
1086   img->Width2 = width - 2 * border;   /* == 1 << img->WidthLog2; */
1087   img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
1088   img->Depth2 = depth - 2 * border;   /* == 1 << img->DepthLog2; */
1089   img->WidthLog2 = logbase2(img->Width2);
1090   if (height == 1)  /* 1-D texture */
1091      img->HeightLog2 = 0;
1092   else
1093      img->HeightLog2 = logbase2(img->Height2);
1094   if (depth == 1)   /* 2-D texture */
1095      img->DepthLog2 = 0;
1096   else
1097      img->DepthLog2 = logbase2(img->Depth2);
1098   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
1099   img->IsCompressed = is_compressed_format(ctx, internalFormat);
1100   if (img->IsCompressed)
1101      img->CompressedSize = ctx->Driver.CompressedTextureSize(ctx, width,
1102                                               height, depth, internalFormat);
1103   else
1104      img->CompressedSize = 0;
1105
1106   if ((width == 1 || _mesa_bitcount(img->Width2) == 1) &&
1107       (height == 1 || _mesa_bitcount(img->Height2) == 1) &&
1108       (depth == 1 || _mesa_bitcount(img->Depth2) == 1))
1109      img->_IsPowerOfTwo = GL_TRUE;
1110   else
1111      img->_IsPowerOfTwo = GL_FALSE;
1112
1113   /* Compute Width/Height/DepthScale for mipmap lod computation */
1114   if (target == GL_TEXTURE_RECTANGLE_NV) {
1115      /* scale = 1.0 since texture coords directly map to texels */
1116      img->WidthScale = 1.0;
1117      img->HeightScale = 1.0;
1118      img->DepthScale = 1.0;
1119   }
1120   else {
1121      img->WidthScale = (GLfloat) img->Width;
1122      img->HeightScale = (GLfloat) img->Height;
1123      img->DepthScale = (GLfloat) img->Depth;
1124   }
1125}
1126
1127
1128/**
1129 * This is the fallback for Driver.TestProxyTexImage().  Test the texture
1130 * level, width, height and depth against the ctx->Const limits for textures.
1131 *
1132 * A hardware driver might override this function if, for example, the
1133 * max 3D texture size is 512x512x64 (i.e. not a cube).
1134 *
1135 * \param target  one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1136 *                GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1137 *                GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1138 * \param level  as passed to glTexImage
1139 * \param internalFormat  as passed to glTexImage
1140 * \param format  as passed to glTexImage
1141 * \param type  as passed to glTexImage
1142 * \param width  as passed to glTexImage
1143 * \param height  as passed to glTexImage
1144 * \param depth  as passed to glTexImage
1145 * \param border  as passed to glTexImage
1146 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1147 */
1148GLboolean
1149_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1150                          GLint internalFormat, GLenum format, GLenum type,
1151                          GLint width, GLint height, GLint depth, GLint border)
1152{
1153   GLint maxSize;
1154
1155   (void) internalFormat;
1156   (void) format;
1157   (void) type;
1158
1159   switch (target) {
1160   case GL_PROXY_TEXTURE_1D:
1161      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1162      if (width < 2 * border || width > 2 + maxSize ||
1163          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1164           _mesa_bitcount(width - 2 * border) != 1) ||
1165          level >= ctx->Const.MaxTextureLevels) {
1166         /* bad width or level */
1167         return GL_FALSE;
1168      }
1169      return GL_TRUE;
1170   case GL_PROXY_TEXTURE_2D:
1171      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1172      if (width < 2 * border || width > 2 + maxSize ||
1173          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1174           _mesa_bitcount(width - 2 * border) != 1) ||
1175          height < 2 * border || height > 2 + maxSize ||
1176          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1177           _mesa_bitcount(height - 2 * border) != 1) ||
1178          level >= ctx->Const.MaxTextureLevels) {
1179         /* bad width or height or level */
1180         return GL_FALSE;
1181      }
1182      return GL_TRUE;
1183   case GL_PROXY_TEXTURE_3D:
1184      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1185      if (width < 2 * border || width > 2 + maxSize ||
1186          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1187           _mesa_bitcount(width - 2 * border) != 1) ||
1188          height < 2 * border || height > 2 + maxSize ||
1189          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1190           _mesa_bitcount(height - 2 * border) != 1) ||
1191          depth < 2 * border || depth > 2 + maxSize ||
1192          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1193           _mesa_bitcount(depth - 2 * border) != 1) ||
1194          level >= ctx->Const.Max3DTextureLevels) {
1195         /* bad width or height or depth or level */
1196         return GL_FALSE;
1197      }
1198      return GL_TRUE;
1199   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1200      if (width < 1 || width > ctx->Const.MaxTextureRectSize ||
1201          height < 1 || height > ctx->Const.MaxTextureRectSize ||
1202          level != 0) {
1203         /* bad width or height or level */
1204         return GL_FALSE;
1205      }
1206      return GL_TRUE;
1207   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1208      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1209      if (width < 2 * border || width > 2 + maxSize ||
1210          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1211           _mesa_bitcount(width - 2 * border) != 1) ||
1212          height < 2 * border || height > 2 + maxSize ||
1213          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1214           _mesa_bitcount(height - 2 * border) != 1) ||
1215          level >= ctx->Const.MaxCubeTextureLevels) {
1216         /* bad width or height */
1217         return GL_FALSE;
1218      }
1219      return GL_TRUE;
1220   default:
1221      _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1222      return GL_FALSE;
1223   }
1224}
1225
1226
1227/**
1228 * Test the glTexImage[123]D() parameters for errors.
1229 *
1230 * \param ctx GL context.
1231 * \param target texture target given by the user.
1232 * \param level image level given by the user.
1233 * \param internalFormat internal format given by the user.
1234 * \param format pixel data format given by the user.
1235 * \param type pixel data type given by the user.
1236 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1237 * \param width image width given by the user.
1238 * \param height image height given by the user.
1239 * \param depth image depth given by the user.
1240 * \param border image border given by the user.
1241 *
1242 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1243 *
1244 * Verifies each of the parameters against the constants specified in
1245 * __GLcontextRec::Const and the supported extensions, and according to the
1246 * OpenGL specification.
1247 */
1248static GLboolean
1249texture_error_check( GLcontext *ctx, GLenum target,
1250                     GLint level, GLint internalFormat,
1251                     GLenum format, GLenum type,
1252                     GLuint dimensions,
1253                     GLint width, GLint height,
1254                     GLint depth, GLint border )
1255{
1256   const GLboolean isProxy = _mesa_is_proxy_texture(target);
1257   GLboolean sizeOK;
1258   GLboolean colorFormat, indexFormat;
1259
1260   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1261   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1262      if (!isProxy) {
1263         _mesa_error(ctx, GL_INVALID_VALUE,
1264                     "glTexImage%dD(level=%d)", dimensions, level);
1265      }
1266      return GL_TRUE;
1267   }
1268
1269   /* Check border */
1270   if (border < 0 || border > 1 ||
1271       ((target == GL_TEXTURE_RECTANGLE_NV ||
1272         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1273      if (!isProxy) {
1274         _mesa_error(ctx, GL_INVALID_VALUE,
1275                     "glTexImage%dD(border=%d)", dimensions, border);
1276      }
1277      return GL_TRUE;
1278   }
1279
1280   if (width < 0 || height < 0 || depth < 0) {
1281      if (!isProxy) {
1282         _mesa_error(ctx, GL_INVALID_VALUE,
1283                     "glTexImage%dD(width, height or depth < 0)", dimensions);
1284      }
1285      return GL_TRUE;
1286   }
1287
1288   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1289    * level, width, height and depth.
1290    */
1291   if (dimensions == 1) {
1292      if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1293         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1294                                                level, internalFormat,
1295                                                format, type,
1296                                                width, 1, 1, border);
1297      }
1298      else {
1299         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1300         return GL_TRUE;
1301      }
1302   }
1303   else if (dimensions == 2) {
1304      if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1305         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1306                                                level, internalFormat,
1307                                                format, type,
1308                                                width, height, 1, border);
1309      }
1310      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1311               (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1312                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1313         if (!ctx->Extensions.ARB_texture_cube_map) {
1314            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1315            return GL_TRUE;
1316         }
1317         sizeOK = (width == height) &&
1318            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1319                                          level, internalFormat, format, type,
1320                                          width, height, 1, border);
1321      }
1322      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1323               target == GL_TEXTURE_RECTANGLE_NV) {
1324         if (!ctx->Extensions.NV_texture_rectangle) {
1325            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1326            return GL_TRUE;
1327         }
1328         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1329                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
1330                                                level, internalFormat,
1331                                                format, type,
1332                                                width, height, 1, border);
1333      }
1334      else {
1335         _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1336         return GL_TRUE;
1337      }
1338   }
1339   else if (dimensions == 3) {
1340      if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1341         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_3D,
1342                                                level, internalFormat,
1343                                                format, type,
1344                                                width, height, depth, border);
1345      }
1346      else {
1347         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1348         return GL_TRUE;
1349      }
1350   }
1351   else {
1352      _mesa_problem( ctx, "bad dims in texture_error_check" );
1353      return GL_TRUE;
1354   }
1355
1356   if (!sizeOK) {
1357      if (!isProxy) {
1358         _mesa_error(ctx, GL_INVALID_VALUE,
1359                     "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1360                     dimensions, level, width, height, depth);
1361      }
1362      return GL_TRUE;
1363   }
1364
1365   /* Check internalFormat */
1366   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1367      if (!isProxy) {
1368         _mesa_error(ctx, GL_INVALID_VALUE,
1369                     "glTexImage%dD(internalFormat=0x%x)",
1370                     dimensions, internalFormat);
1371      }
1372      return GL_TRUE;
1373   }
1374
1375   /* Check incoming image format and type */
1376   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1377      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1378       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
1379       */
1380      if (!isProxy) {
1381         _mesa_error(ctx, GL_INVALID_OPERATION,
1382                     "glTexImage%dD(format or type)", dimensions);
1383      }
1384      return GL_TRUE;
1385   }
1386
1387   /* make sure internal format and format basically agree */
1388   colorFormat = is_color_format(format);
1389   indexFormat = is_index_format(format);
1390   if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1391       (is_index_format(internalFormat) && !indexFormat) ||
1392       (is_depth_format(internalFormat) != is_depth_format(format)) ||
1393       (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
1394       (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
1395      if (!isProxy)
1396         _mesa_error(ctx, GL_INVALID_OPERATION,
1397                     "glTexImage(internalFormat/format)");
1398      return GL_TRUE;
1399   }
1400
1401   /* additional checks for ycbcr textures */
1402   if (internalFormat == GL_YCBCR_MESA) {
1403      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1404      if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1405          type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1406         char message[100];
1407         _mesa_sprintf(message,
1408                 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1409         _mesa_error(ctx, GL_INVALID_ENUM, message);
1410         return GL_TRUE; /* error */
1411      }
1412      if (target != GL_TEXTURE_2D &&
1413          target != GL_PROXY_TEXTURE_2D &&
1414          target != GL_TEXTURE_RECTANGLE_NV &&
1415          target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1416         if (!isProxy)
1417            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1418         return GL_TRUE;
1419      }
1420      if (border != 0) {
1421         if (!isProxy) {
1422            char message[100];
1423            _mesa_sprintf(message,
1424                    "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1425                    dimensions, border);
1426            _mesa_error(ctx, GL_INVALID_VALUE, message);
1427         }
1428         return GL_TRUE;
1429      }
1430   }
1431
1432   /* additional checks for depth textures */
1433   if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1434      /* Only 1D and 2D textures supported */
1435      if (target != GL_TEXTURE_1D &&
1436          target != GL_PROXY_TEXTURE_1D &&
1437          target != GL_TEXTURE_2D &&
1438          target != GL_PROXY_TEXTURE_2D) {
1439         if (!isProxy)
1440            _mesa_error(ctx, GL_INVALID_ENUM,
1441                        "glTexImage(target/internalFormat)");
1442         return GL_TRUE;
1443      }
1444   }
1445
1446   /* additional checks for compressed textures */
1447   if (is_compressed_format(ctx, internalFormat)) {
1448      if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
1449         /* OK */
1450      }
1451      else if (ctx->Extensions.ARB_texture_cube_map &&
1452               (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1453                (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1454                 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
1455         /* OK */
1456      }
1457      else {
1458         if (!isProxy) {
1459            _mesa_error(ctx, GL_INVALID_ENUM,
1460                        "glTexImage%d(target)", dimensions);
1461            return GL_TRUE;
1462         }
1463      }
1464      if (border != 0) {
1465         if (!isProxy) {
1466            _mesa_error(ctx, GL_INVALID_OPERATION,
1467                        "glTexImage%D(border!=0)", dimensions);
1468         }
1469         return GL_TRUE;
1470      }
1471   }
1472
1473   /* if we get here, the parameters are OK */
1474   return GL_FALSE;
1475}
1476
1477
1478/**
1479 * Test glTexSubImage[123]D() parameters for errors.
1480 *
1481 * \param ctx GL context.
1482 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1483 * \param target texture target given by the user.
1484 * \param level image level given by the user.
1485 * \param xoffset sub-image x offset given by the user.
1486 * \param yoffset sub-image y offset given by the user.
1487 * \param zoffset sub-image z offset given by the user.
1488 * \param format pixel data format given by the user.
1489 * \param type pixel data type given by the user.
1490 * \param width image width given by the user.
1491 * \param height image height given by the user.
1492 * \param depth image depth given by the user.
1493 *
1494 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1495 *
1496 * Verifies each of the parameters against the constants specified in
1497 * __GLcontextRec::Const and the supported extensions, and according to the
1498 * OpenGL specification.
1499 */
1500static GLboolean
1501subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1502                        GLenum target, GLint level,
1503                        GLint xoffset, GLint yoffset, GLint zoffset,
1504                        GLint width, GLint height, GLint depth,
1505                        GLenum format, GLenum type )
1506{
1507   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1508   struct gl_texture_image *destTex;
1509
1510   /* Check target */
1511   if (dimensions == 1) {
1512      if (target != GL_TEXTURE_1D) {
1513         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1514         return GL_TRUE;
1515      }
1516   }
1517   else if (dimensions == 2) {
1518      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1519          target <=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1520         if (!ctx->Extensions.ARB_texture_cube_map) {
1521            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1522            return GL_TRUE;
1523         }
1524      }
1525      else if (ctx->Extensions.NV_texture_rectangle &&
1526               target == GL_TEXTURE_RECTANGLE_NV) {
1527         if (!ctx->Extensions.NV_texture_rectangle) {
1528            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1529            return GL_TRUE;
1530         }
1531      }
1532      else if (target != GL_TEXTURE_2D) {
1533         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1534         return GL_TRUE;
1535      }
1536   }
1537   else if (dimensions == 3) {
1538      if (target != GL_TEXTURE_3D) {
1539         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1540         return GL_TRUE;
1541      }
1542   }
1543   else {
1544      _mesa_problem( ctx, "invalid dims in texture_error_check" );
1545      return GL_TRUE;
1546   }
1547
1548   /* Basic level check */
1549   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1550      _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1551      return GL_TRUE;
1552   }
1553
1554   if (width < 0) {
1555      _mesa_error(ctx, GL_INVALID_VALUE,
1556                  "glTexSubImage%dD(width=%d)", dimensions, width);
1557      return GL_TRUE;
1558   }
1559   if (height < 0 && dimensions > 1) {
1560      _mesa_error(ctx, GL_INVALID_VALUE,
1561                  "glTexSubImage%dD(height=%d)", dimensions, height);
1562      return GL_TRUE;
1563   }
1564   if (depth < 0 && dimensions > 2) {
1565      _mesa_error(ctx, GL_INVALID_VALUE,
1566                  "glTexSubImage%dD(depth=%d)", dimensions, depth);
1567      return GL_TRUE;
1568   }
1569
1570   destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
1571
1572   if (!destTex) {
1573      /* undefined image level */
1574      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
1575      return GL_TRUE;
1576   }
1577
1578   if (xoffset < -((GLint)destTex->Border)) {
1579      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
1580                  dimensions);
1581      return GL_TRUE;
1582   }
1583   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1584      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
1585                  dimensions);
1586      return GL_TRUE;
1587   }
1588   if (dimensions > 1) {
1589      if (yoffset < -((GLint)destTex->Border)) {
1590         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
1591                     dimensions);
1592         return GL_TRUE;
1593      }
1594      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1595         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
1596                     dimensions);
1597         return GL_TRUE;
1598      }
1599   }
1600   if (dimensions > 2) {
1601      if (zoffset < -((GLint)destTex->Border)) {
1602         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1603         return GL_TRUE;
1604      }
1605      if (zoffset + depth  > (GLint) (destTex->Depth + destTex->Border)) {
1606         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1607         return GL_TRUE;
1608      }
1609   }
1610
1611   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1612      _mesa_error(ctx, GL_INVALID_ENUM,
1613                  "glTexSubImage%dD(format or type)", dimensions);
1614      return GL_TRUE;
1615   }
1616
1617   if (destTex->IsCompressed) {
1618      const struct gl_texture_unit *texUnit;
1619      const struct gl_texture_image *texImage;
1620      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1621      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1622
1623      if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
1624         /* OK */
1625      }
1626      else if (ctx->Extensions.ARB_texture_cube_map &&
1627               (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1628                (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1629                 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
1630         /* OK */
1631      }
1632      else {
1633         _mesa_error(ctx, GL_INVALID_ENUM,
1634                     "glTexSubImage%D(target)", dimensions);
1635         return GL_TRUE;
1636      }
1637      /* offset must be multiple of 4 */
1638      if ((xoffset & 3) || (yoffset & 3)) {
1639         _mesa_error(ctx, GL_INVALID_OPERATION,
1640                     "glTexSubImage%D(xoffset or yoffset)", dimensions);
1641         return GL_TRUE;
1642      }
1643      /* size must be multiple of 4 or equal to whole texture size */
1644      if ((width & 3) && (GLuint) width != texImage->Width) {
1645         _mesa_error(ctx, GL_INVALID_OPERATION,
1646                     "glTexSubImage%D(width)", dimensions);
1647         return GL_TRUE;
1648      }
1649      if ((height & 3) && (GLuint) height != texImage->Height) {
1650         _mesa_error(ctx, GL_INVALID_OPERATION,
1651                     "glTexSubImage%D(width)", dimensions);
1652         return GL_TRUE;
1653      }
1654   }
1655
1656   return GL_FALSE;
1657}
1658
1659
1660/**
1661 * Test glCopyTexImage[12]D() parameters for errors.
1662 *
1663 * \param ctx GL context.
1664 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1665 * \param target texture target given by the user.
1666 * \param level image level given by the user.
1667 * \param internalFormat internal format given by the user.
1668 * \param width image width given by the user.
1669 * \param height image height given by the user.
1670 * \param depth image depth given by the user.
1671 * \param border texture border.
1672 *
1673 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1674 *
1675 * Verifies each of the parameters against the constants specified in
1676 * __GLcontextRec::Const and the supported extensions, and according to the
1677 * OpenGL specification.
1678 */
1679static GLboolean
1680copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1681                         GLenum target, GLint level, GLint internalFormat,
1682                         GLint width, GLint height, GLint border )
1683{
1684   GLenum type;
1685   GLboolean sizeOK;
1686   GLint format;
1687
1688   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1689   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1690      _mesa_error(ctx, GL_INVALID_VALUE,
1691                  "glCopyTexImage%dD(level=%d)", dimensions, level);
1692      return GL_TRUE;
1693   }
1694
1695   /* Check border */
1696   if (border < 0 || border > 1 ||
1697       ((target == GL_TEXTURE_RECTANGLE_NV ||
1698         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1699      return GL_TRUE;
1700   }
1701
1702   format = _mesa_base_tex_format(ctx, internalFormat);
1703   if (format < 0) {
1704      _mesa_error(ctx, GL_INVALID_VALUE,
1705                  "glCopyTexImage%dD(internalFormat)", dimensions);
1706      return GL_TRUE;
1707   }
1708
1709   /* NOTE: the format and type aren't really significant for
1710    * TestProxyTexImage().  Only the internalformat really matters.
1711    */
1712   type = GL_FLOAT;
1713
1714   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1715    * level, width, height and depth.
1716    */
1717   if (dimensions == 1) {
1718      if (target == GL_TEXTURE_1D) {
1719         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1720                                                level, internalFormat,
1721                                                format, type,
1722                                                width, 1, 1, border);
1723      }
1724      else {
1725         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1726         return GL_TRUE;
1727      }
1728   }
1729   else if (dimensions == 2) {
1730      if (target == GL_TEXTURE_2D) {
1731         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1732                                                level, internalFormat,
1733                                                format, type,
1734                                                width, height, 1, border);
1735      }
1736      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1737               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1738         if (!ctx->Extensions.ARB_texture_cube_map) {
1739            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1740            return GL_TRUE;
1741         }
1742         sizeOK = (width == height) &&
1743            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1744                                          level, internalFormat, format, type,
1745                                          width, height, 1, border);
1746      }
1747      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1748         if (!ctx->Extensions.NV_texture_rectangle) {
1749            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1750            return GL_TRUE;
1751         }
1752         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1753                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
1754                                                level, internalFormat,
1755                                                format, type,
1756                                                width, height, 1, border);
1757      }
1758      else {
1759         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1760         return GL_TRUE;
1761      }
1762   }
1763   else {
1764      _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1765      return GL_TRUE;
1766   }
1767
1768   if (!sizeOK) {
1769      if (dimensions == 1) {
1770         _mesa_error(ctx, GL_INVALID_VALUE,
1771                     "glCopyTexImage1D(width=%d)", width);
1772      }
1773      else {
1774         ASSERT(dimensions == 2);
1775         _mesa_error(ctx, GL_INVALID_VALUE,
1776                     "glCopyTexImage2D(width=%d, height=%d)", width, height);
1777      }
1778      return GL_TRUE;
1779   }
1780
1781   if (is_compressed_format(ctx, internalFormat)) {
1782      if (target != GL_TEXTURE_2D) {
1783         _mesa_error(ctx, GL_INVALID_ENUM,
1784                     "glCopyTexImage%d(target)", dimensions);
1785         return GL_TRUE;
1786      }
1787      if (border != 0) {
1788         _mesa_error(ctx, GL_INVALID_OPERATION,
1789                     "glCopyTexImage%D(border!=0)", dimensions);
1790         return GL_TRUE;
1791      }
1792   }
1793   else if (is_depth_format(internalFormat)) {
1794      /* make sure we have depth/stencil buffers */
1795      if (!ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) {
1796         _mesa_error(ctx, GL_INVALID_OPERATION,
1797                     "glCopyTexImage%D(no depth)", dimensions);
1798         return GL_TRUE;
1799      }
1800   }
1801   else if (is_depthstencil_format(internalFormat)) {
1802      /* make sure we have depth/stencil buffers */
1803      if (!ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer ||
1804          !ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) {
1805         _mesa_error(ctx, GL_INVALID_OPERATION,
1806                     "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
1807         return GL_TRUE;
1808      }
1809   }
1810
1811   /* if we get here, the parameters are OK */
1812   return GL_FALSE;
1813}
1814
1815
1816/**
1817 * Test glCopyTexImage[12]D() parameters for errors.
1818 *
1819 * \param ctx GL context.
1820 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1821 * \param target texture target given by the user.
1822 * \param level image level given by the user.
1823 * \param xoffset sub-image x offset given by the user.
1824 * \param yoffset sub-image y offset given by the user.
1825 * \param zoffset sub-image z offset given by the user.
1826 * \param width image width given by the user.
1827 * \param height image height given by the user.
1828 *
1829 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1830 *
1831 * Verifies each of the parameters against the constants specified in
1832 * __GLcontextRec::Const and the supported extensions, and according to the
1833 * OpenGL specification.
1834 */
1835static GLboolean
1836copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1837                             GLenum target, GLint level,
1838                             GLint xoffset, GLint yoffset, GLint zoffset,
1839                             GLsizei width, GLsizei height )
1840{
1841   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1842   struct gl_texture_image *teximage;
1843
1844   /* Check target */
1845   if (dimensions == 1) {
1846      if (target != GL_TEXTURE_1D) {
1847         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1848         return GL_TRUE;
1849      }
1850   }
1851   else if (dimensions == 2) {
1852      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1853          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1854         if (!ctx->Extensions.ARB_texture_cube_map) {
1855            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1856            return GL_TRUE;
1857         }
1858      }
1859      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1860         if (!ctx->Extensions.NV_texture_rectangle) {
1861            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1862            return GL_TRUE;
1863         }
1864      }
1865      else if (target != GL_TEXTURE_2D) {
1866         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1867         return GL_TRUE;
1868      }
1869   }
1870   else if (dimensions == 3) {
1871      if (target != GL_TEXTURE_3D) {
1872         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1873         return GL_TRUE;
1874      }
1875   }
1876
1877   /* Check level */
1878   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1879      _mesa_error(ctx, GL_INVALID_VALUE,
1880                  "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1881      return GL_TRUE;
1882   }
1883
1884   /* Check size */
1885   if (width < 0) {
1886      _mesa_error(ctx, GL_INVALID_VALUE,
1887                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1888      return GL_TRUE;
1889   }
1890   if (dimensions > 1 && height < 0) {
1891      _mesa_error(ctx, GL_INVALID_VALUE,
1892                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1893      return GL_TRUE;
1894   }
1895
1896   teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
1897   if (!teximage) {
1898      _mesa_error(ctx, GL_INVALID_OPERATION,
1899                  "glCopyTexSubImage%dD(undefined texture level: %d)",
1900                  dimensions, level);
1901      return GL_TRUE;
1902   }
1903
1904   if (xoffset < -((GLint)teximage->Border)) {
1905      _mesa_error(ctx, GL_INVALID_VALUE,
1906                  "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1907      return GL_TRUE;
1908   }
1909   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1910      _mesa_error(ctx, GL_INVALID_VALUE,
1911                  "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1912      return GL_TRUE;
1913   }
1914   if (dimensions > 1) {
1915      if (yoffset < -((GLint)teximage->Border)) {
1916         _mesa_error(ctx, GL_INVALID_VALUE,
1917                     "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1918         return GL_TRUE;
1919      }
1920      /* NOTE: we're adding the border here, not subtracting! */
1921      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1922         _mesa_error(ctx, GL_INVALID_VALUE,
1923                     "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1924         return GL_TRUE;
1925      }
1926   }
1927
1928   if (dimensions > 2) {
1929      if (zoffset < -((GLint)teximage->Border)) {
1930         _mesa_error(ctx, GL_INVALID_VALUE,
1931                     "glCopyTexSubImage%dD(zoffset)", dimensions);
1932         return GL_TRUE;
1933      }
1934      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1935         _mesa_error(ctx, GL_INVALID_VALUE,
1936                     "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1937         return GL_TRUE;
1938      }
1939   }
1940
1941   if (teximage->IsCompressed) {
1942      if (target != GL_TEXTURE_2D) {
1943         _mesa_error(ctx, GL_INVALID_ENUM,
1944                     "glCopyTexSubImage%d(target)", dimensions);
1945         return GL_TRUE;
1946      }
1947      /* offset must be multiple of 4 */
1948      if ((xoffset & 3) || (yoffset & 3)) {
1949         _mesa_error(ctx, GL_INVALID_VALUE,
1950                     "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
1951         return GL_TRUE;
1952      }
1953      /* size must be multiple of 4 */
1954      if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
1955         _mesa_error(ctx, GL_INVALID_VALUE,
1956                     "glCopyTexSubImage%D(width)", dimensions);
1957         return GL_TRUE;
1958      }
1959      if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
1960         _mesa_error(ctx, GL_INVALID_VALUE,
1961                     "glCopyTexSubImage%D(height)", dimensions);
1962         return GL_TRUE;
1963      }
1964   }
1965
1966   if (teximage->InternalFormat == GL_YCBCR_MESA) {
1967      _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
1968      return GL_TRUE;
1969   }
1970
1971   if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
1972      if (!ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer) {
1973         _mesa_error(ctx, GL_INVALID_OPERATION,
1974                     "glCopyTexSubImage%D(no depth buffer)",
1975                     dimensions);
1976         return GL_TRUE;
1977      }
1978   }
1979   else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
1980      if (!ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer ||
1981          !ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) {
1982         _mesa_error(ctx, GL_INVALID_OPERATION,
1983                     "glCopyTexSubImage%D(no depth/stencil buffer)",
1984                     dimensions);
1985         return GL_TRUE;
1986      }
1987   }
1988
1989   /* if we get here, the parameters are OK */
1990   return GL_FALSE;
1991}
1992
1993
1994/**
1995 * Get texture image.  Called by glGetTexImage.
1996 *
1997 * \param target texture target.
1998 * \param level image level.
1999 * \param format pixel data format for returned image.
2000 * \param type pixel data type for returned image.
2001 * \param pixels returned pixel data.
2002 */
2003void GLAPIENTRY
2004_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2005                   GLenum type, GLvoid *pixels )
2006{
2007   const struct gl_texture_unit *texUnit;
2008   const struct gl_texture_object *texObj;
2009   const struct gl_texture_image *texImage;
2010   GLint maxLevels = 0;
2011   GET_CURRENT_CONTEXT(ctx);
2012   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2013
2014   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2015   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2016   if (!texObj || _mesa_is_proxy_texture(target)) {
2017      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2018      return;
2019   }
2020
2021   maxLevels = _mesa_max_texture_levels(ctx, target);
2022   ASSERT(maxLevels > 0);  /* 0 indicates bad target, caught above */
2023
2024   if (level < 0 || level >= maxLevels) {
2025      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2026      return;
2027   }
2028
2029   if (_mesa_sizeof_packed_type(type) <= 0) {
2030      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2031      return;
2032   }
2033
2034   if (_mesa_components_in_format(format) <= 0 ||
2035       format == GL_STENCIL_INDEX) {
2036      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2037      return;
2038   }
2039
2040   if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
2041      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2042   }
2043
2044   if (!ctx->Extensions.SGIX_depth_texture &&
2045       !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
2046      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2047   }
2048
2049   if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
2050      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2051   }
2052
2053   if (!ctx->Extensions.EXT_packed_depth_stencil
2054       && is_depthstencil_format(format)) {
2055      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2056   }
2057
2058   if (!pixels)
2059      return;
2060
2061   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2062   if (!texImage) {
2063      /* invalid mipmap level, not an error */
2064      return;
2065   }
2066
2067   /* Make sure the requested image format is compatible with the
2068    * texture's format.  Note that a color index texture can be converted
2069    * to RGBA so that combo is allowed.
2070    */
2071   if (is_color_format(format)
2072       && !is_color_format(texImage->TexFormat->BaseFormat)
2073       && !is_index_format(texImage->TexFormat->BaseFormat)) {
2074      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2075      return;
2076   }
2077   else if (is_index_format(format)
2078       && !is_index_format(texImage->TexFormat->BaseFormat)) {
2079      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2080      return;
2081   }
2082   else if (is_depth_format(format)
2083       && !is_depth_format(texImage->TexFormat->BaseFormat)
2084       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2085      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2086      return;
2087   }
2088   else if (is_ycbcr_format(format)
2089       && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
2090      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2091      return;
2092   }
2093   else if (is_depthstencil_format(format)
2094       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2095      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2096      return;
2097   }
2098
2099   /* typically, this will call _mesa_get_teximage() */
2100   ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
2101                           texObj, texImage);
2102}
2103
2104
2105
2106/*
2107 * Called from the API.  Note that width includes the border.
2108 */
2109void GLAPIENTRY
2110_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2111                  GLsizei width, GLint border, GLenum format,
2112                  GLenum type, const GLvoid *pixels )
2113{
2114   GLsizei postConvWidth = width;
2115   GET_CURRENT_CONTEXT(ctx);
2116   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2117
2118   if (is_color_format(internalFormat)) {
2119      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2120   }
2121
2122   if (target == GL_TEXTURE_1D) {
2123      /* non-proxy target */
2124      struct gl_texture_unit *texUnit;
2125      struct gl_texture_object *texObj;
2126      struct gl_texture_image *texImage;
2127
2128      if (texture_error_check(ctx, target, level, internalFormat,
2129                              format, type, 1, postConvWidth, 1, 1, border)) {
2130         return;   /* error was recorded */
2131      }
2132
2133      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2134      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2135      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2136
2137      if (!texImage) {
2138         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2139         return;
2140      }
2141      else if (texImage->Data) {
2142	 ctx->Driver.FreeTexImageData( ctx, texImage );
2143      }
2144      ASSERT(texImage->Data == NULL);
2145      clear_teximage_fields(texImage); /* not really needed, but helpful */
2146      _mesa_init_teximage_fields(ctx, target, texImage,
2147                                 postConvWidth, 1, 1,
2148                                 border, internalFormat);
2149
2150      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2151         _mesa_update_state(ctx);
2152
2153      ASSERT(ctx->Driver.TexImage1D);
2154
2155      /* Give the texture to the driver!  <pixels> may be null! */
2156      (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
2157                                width, border, format, type, pixels,
2158                                &ctx->Unpack, texObj, texImage);
2159
2160      ASSERT(texImage->TexFormat);
2161
2162      /* state update */
2163      texObj->Complete = GL_FALSE;
2164      ctx->NewState |= _NEW_TEXTURE;
2165   }
2166   else if (target == GL_PROXY_TEXTURE_1D) {
2167      /* Proxy texture: check for errors and update proxy state */
2168      struct gl_texture_image *texImage;
2169      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2170      if (texture_error_check(ctx, target, level, internalFormat,
2171                              format, type, 1, postConvWidth, 1, 1, border)) {
2172         /* when error, clear all proxy texture image parameters */
2173         if (texImage)
2174            clear_teximage_fields(texImage);
2175      }
2176      else {
2177         /* no error, set the tex image parameters */
2178         ASSERT(texImage);
2179         _mesa_init_teximage_fields(ctx, target, texImage,
2180                                    postConvWidth, 1, 1,
2181                                    border, internalFormat);
2182         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2183                                          internalFormat, format, type);
2184      }
2185   }
2186   else {
2187      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2188      return;
2189   }
2190}
2191
2192
2193void GLAPIENTRY
2194_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2195                  GLsizei width, GLsizei height, GLint border,
2196                  GLenum format, GLenum type,
2197                  const GLvoid *pixels )
2198{
2199   GLsizei postConvWidth = width, postConvHeight = height;
2200   GET_CURRENT_CONTEXT(ctx);
2201   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2202
2203   if (is_color_format(internalFormat)) {
2204      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2205					 &postConvHeight);
2206   }
2207
2208   if (target == GL_TEXTURE_2D ||
2209       (ctx->Extensions.ARB_texture_cube_map &&
2210        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2211        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2212       (ctx->Extensions.NV_texture_rectangle &&
2213        target == GL_TEXTURE_RECTANGLE_NV)) {
2214      /* non-proxy target */
2215      struct gl_texture_unit *texUnit;
2216      struct gl_texture_object *texObj;
2217      struct gl_texture_image *texImage;
2218
2219      if (texture_error_check(ctx, target, level, internalFormat,
2220                              format, type, 2, postConvWidth, postConvHeight,
2221                              1, border)) {
2222         return;   /* error was recorded */
2223      }
2224
2225      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2226      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2227      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2228      if (!texImage) {
2229         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2230         return;
2231      }
2232      else if (texImage->Data) {
2233	 ctx->Driver.FreeTexImageData( ctx, texImage );
2234      }
2235      ASSERT(texImage->Data == NULL);
2236      clear_teximage_fields(texImage); /* not really needed, but helpful */
2237      _mesa_init_teximage_fields(ctx, target, texImage,
2238                                 postConvWidth, postConvHeight, 1,
2239                                 border, internalFormat);
2240
2241      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2242         _mesa_update_state(ctx);
2243
2244      ASSERT(ctx->Driver.TexImage2D);
2245
2246      /* Give the texture to the driver!  <pixels> may be null! */
2247      (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
2248                                width, height, border, format, type, pixels,
2249                                &ctx->Unpack, texObj, texImage);
2250
2251      ASSERT(texImage->TexFormat);
2252
2253      /* state update */
2254      texObj->Complete = GL_FALSE;
2255      ctx->NewState |= _NEW_TEXTURE;
2256   }
2257   else if (target == GL_PROXY_TEXTURE_2D ||
2258            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2259             ctx->Extensions.ARB_texture_cube_map) ||
2260            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2261             ctx->Extensions.NV_texture_rectangle)) {
2262      /* Proxy texture: check for errors and update proxy state */
2263      struct gl_texture_image *texImage;
2264      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2265      if (texture_error_check(ctx, target, level, internalFormat,
2266                              format, type, 2, postConvWidth, postConvHeight,
2267                              1, border)) {
2268         /* when error, clear all proxy texture image parameters */
2269         if (texImage)
2270            clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]);
2271      }
2272      else {
2273         /* no error, set the tex image parameters */
2274         _mesa_init_teximage_fields(ctx, target, texImage,
2275                                    postConvWidth, postConvHeight, 1,
2276                                    border, internalFormat);
2277         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2278                                          internalFormat, format, type);
2279      }
2280   }
2281   else {
2282      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2283      return;
2284   }
2285}
2286
2287
2288/*
2289 * Called by the API or display list executor.
2290 * Note that width and height include the border.
2291 */
2292void GLAPIENTRY
2293_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2294                  GLsizei width, GLsizei height, GLsizei depth,
2295                  GLint border, GLenum format, GLenum type,
2296                  const GLvoid *pixels )
2297{
2298   GET_CURRENT_CONTEXT(ctx);
2299   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2300
2301   if (target == GL_TEXTURE_3D) {
2302      struct gl_texture_unit *texUnit;
2303      struct gl_texture_object *texObj;
2304      struct gl_texture_image *texImage;
2305      /* non-proxy target */
2306
2307      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2308                              format, type, 3, width, height, depth, border)) {
2309         return;   /* error was recorded */
2310      }
2311
2312      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2313      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2314      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2315      if (!texImage) {
2316         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2317         return;
2318      }
2319      else if (texImage->Data) {
2320	 ctx->Driver.FreeTexImageData( ctx, texImage );
2321      }
2322      ASSERT(texImage->Data == NULL);
2323      clear_teximage_fields(texImage); /* not really needed, but helpful */
2324      _mesa_init_teximage_fields(ctx, target, texImage,
2325                                 width, height, depth,
2326                                 border, internalFormat);
2327
2328      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2329         _mesa_update_state(ctx);
2330
2331      ASSERT(ctx->Driver.TexImage3D);
2332
2333      /* Give the texture to the driver!  <pixels> may be null! */
2334      (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
2335                                width, height, depth, border, format, type,
2336                                pixels, &ctx->Unpack, texObj, texImage);
2337
2338      ASSERT(texImage->TexFormat);
2339
2340      /* state update */
2341      texObj->Complete = GL_FALSE;
2342      ctx->NewState |= _NEW_TEXTURE;
2343   }
2344   else if (target == GL_PROXY_TEXTURE_3D) {
2345      /* Proxy texture: check for errors and update proxy state */
2346      struct gl_texture_image *texImage;
2347      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2348      if (texture_error_check(ctx, target, level, internalFormat,
2349                              format, type, 3, width, height, depth, border)) {
2350         /* when error, clear all proxy texture image parameters */
2351         if (texImage)
2352            clear_teximage_fields(texImage);
2353      }
2354      else {
2355         /* no error, set the tex image parameters */
2356         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
2357                                    border, internalFormat);
2358         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2359                                          internalFormat, format, type);
2360      }
2361   }
2362   else {
2363      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2364      return;
2365   }
2366}
2367
2368
2369void GLAPIENTRY
2370_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2371                     GLsizei width, GLsizei height, GLsizei depth,
2372                     GLint border, GLenum format, GLenum type,
2373                     const GLvoid *pixels )
2374{
2375   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2376                    depth, border, format, type, pixels);
2377}
2378
2379
2380
2381void GLAPIENTRY
2382_mesa_TexSubImage1D( GLenum target, GLint level,
2383                     GLint xoffset, GLsizei width,
2384                     GLenum format, GLenum type,
2385                     const GLvoid *pixels )
2386{
2387   GLsizei postConvWidth = width;
2388   struct gl_texture_unit *texUnit;
2389   struct gl_texture_object *texObj;
2390   struct gl_texture_image *texImage;
2391   GET_CURRENT_CONTEXT(ctx);
2392   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2393
2394   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2395      _mesa_update_state(ctx);
2396
2397   /* XXX should test internal format */
2398   if (is_color_format(format)) {
2399      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2400   }
2401
2402   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2403                              postConvWidth, 1, 1, format, type)) {
2404      return;   /* error was detected */
2405   }
2406
2407   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2408   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2409   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2410   assert(texImage);
2411
2412   if (width == 0)
2413      return;  /* no-op, not an error */
2414
2415   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2416   xoffset += texImage->Border;
2417
2418   ASSERT(ctx->Driver.TexSubImage1D);
2419   (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
2420                                format, type, pixels, &ctx->Unpack,
2421                                texObj, texImage);
2422   ctx->NewState |= _NEW_TEXTURE;
2423}
2424
2425
2426void GLAPIENTRY
2427_mesa_TexSubImage2D( GLenum target, GLint level,
2428                     GLint xoffset, GLint yoffset,
2429                     GLsizei width, GLsizei height,
2430                     GLenum format, GLenum type,
2431                     const GLvoid *pixels )
2432{
2433   GLsizei postConvWidth = width, postConvHeight = height;
2434   struct gl_texture_unit *texUnit;
2435   struct gl_texture_object *texObj;
2436   struct gl_texture_image *texImage;
2437   GET_CURRENT_CONTEXT(ctx);
2438   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2439
2440   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2441      _mesa_update_state(ctx);
2442
2443   /* XXX should test internal format */
2444   if (is_color_format(format)) {
2445      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2446                                         &postConvHeight);
2447   }
2448
2449   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2450                             postConvWidth, postConvHeight, 1, format, type)) {
2451      return;   /* error was detected */
2452   }
2453
2454   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2455   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2456   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2457   assert(texImage);
2458
2459   if (width == 0 || height == 0)
2460      return;  /* no-op, not an error */
2461
2462   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2463   xoffset += texImage->Border;
2464   yoffset += texImage->Border;
2465
2466   ASSERT(ctx->Driver.TexSubImage2D);
2467   (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2468                                width, height, format, type, pixels,
2469                                &ctx->Unpack, texObj, texImage);
2470   ctx->NewState |= _NEW_TEXTURE;
2471}
2472
2473
2474
2475void GLAPIENTRY
2476_mesa_TexSubImage3D( GLenum target, GLint level,
2477                     GLint xoffset, GLint yoffset, GLint zoffset,
2478                     GLsizei width, GLsizei height, GLsizei depth,
2479                     GLenum format, GLenum type,
2480                     const GLvoid *pixels )
2481{
2482   struct gl_texture_unit *texUnit;
2483   struct gl_texture_object *texObj;
2484   struct gl_texture_image *texImage;
2485   GET_CURRENT_CONTEXT(ctx);
2486   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2487
2488   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2489      _mesa_update_state(ctx);
2490
2491   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2492                              width, height, depth, format, type)) {
2493      return;   /* error was detected */
2494   }
2495
2496   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2497   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2498   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2499   assert(texImage);
2500
2501   if (width == 0 || height == 0 || height == 0)
2502      return;  /* no-op, not an error */
2503
2504   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2505   xoffset += texImage->Border;
2506   yoffset += texImage->Border;
2507   zoffset += texImage->Border;
2508
2509   ASSERT(ctx->Driver.TexSubImage3D);
2510   (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2511                                xoffset, yoffset, zoffset,
2512                                width, height, depth,
2513                                format, type, pixels,
2514                                &ctx->Unpack, texObj, texImage );
2515   ctx->NewState |= _NEW_TEXTURE;
2516}
2517
2518
2519
2520void GLAPIENTRY
2521_mesa_CopyTexImage1D( GLenum target, GLint level,
2522                      GLenum internalFormat,
2523                      GLint x, GLint y,
2524                      GLsizei width, GLint border )
2525{
2526   struct gl_texture_unit *texUnit;
2527   struct gl_texture_object *texObj;
2528   struct gl_texture_image *texImage;
2529   GLsizei postConvWidth = width;
2530   GET_CURRENT_CONTEXT(ctx);
2531   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2532
2533   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2534      _mesa_update_state(ctx);
2535
2536   if (is_color_format(internalFormat)) {
2537      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2538   }
2539
2540   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2541                               postConvWidth, 1, border))
2542      return;
2543
2544   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2545   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2546   texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2547   if (!texImage) {
2548      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2549      return;
2550   }
2551   else if (texImage->Data) {
2552      ctx->Driver.FreeTexImageData( ctx, texImage );
2553   }
2554   ASSERT(texImage->Data == NULL);
2555
2556   clear_teximage_fields(texImage); /* not really needed, but helpful */
2557   _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2558                              border, internalFormat);
2559
2560
2561   ASSERT(ctx->Driver.CopyTexImage1D);
2562   (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
2563                                 x, y, width, border);
2564
2565   ASSERT(texImage->TexFormat);
2566
2567   /* state update */
2568   texObj->Complete = GL_FALSE;
2569   ctx->NewState |= _NEW_TEXTURE;
2570}
2571
2572
2573
2574void GLAPIENTRY
2575_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2576                      GLint x, GLint y, GLsizei width, GLsizei height,
2577                      GLint border )
2578{
2579   struct gl_texture_unit *texUnit;
2580   struct gl_texture_object *texObj;
2581   struct gl_texture_image *texImage;
2582   GLsizei postConvWidth = width, postConvHeight = height;
2583   GET_CURRENT_CONTEXT(ctx);
2584   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2585
2586   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2587      _mesa_update_state(ctx);
2588
2589   if (is_color_format(internalFormat)) {
2590      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2591                                         &postConvHeight);
2592   }
2593
2594   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2595                               postConvWidth, postConvHeight, border))
2596      return;
2597
2598   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2599   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2600   texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2601   if (!texImage) {
2602      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2603      return;
2604   }
2605   else if (texImage->Data) {
2606      ctx->Driver.FreeTexImageData( ctx, texImage );
2607   }
2608   ASSERT(texImage->Data == NULL);
2609
2610   clear_teximage_fields(texImage); /* not really needed, but helpful */
2611   _mesa_init_teximage_fields(ctx, target, texImage,
2612                              postConvWidth, postConvHeight, 1,
2613                              border, internalFormat);
2614
2615   ASSERT(ctx->Driver.CopyTexImage2D);
2616   (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
2617                                 x, y, width, height, border);
2618
2619   ASSERT(texImage->TexFormat);
2620
2621   /* state update */
2622   texObj->Complete = GL_FALSE;
2623   ctx->NewState |= _NEW_TEXTURE;
2624}
2625
2626
2627
2628void GLAPIENTRY
2629_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2630                         GLint xoffset, GLint x, GLint y, GLsizei width )
2631{
2632   struct gl_texture_unit *texUnit;
2633   struct gl_texture_image *texImage;
2634   GLsizei postConvWidth = width;
2635   GET_CURRENT_CONTEXT(ctx);
2636   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2637
2638   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2639      _mesa_update_state(ctx);
2640
2641   /* XXX should test internal format */
2642   _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2643
2644   if (copytexsubimage_error_check(ctx, 1, target, level,
2645                                   xoffset, 0, 0, postConvWidth, 1))
2646      return;
2647
2648   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2649   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2650   ASSERT(texImage);
2651
2652   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2653   xoffset += texImage->Border;
2654
2655   ASSERT(ctx->Driver.CopyTexSubImage1D);
2656   (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
2657   ctx->NewState |= _NEW_TEXTURE;
2658}
2659
2660
2661
2662void GLAPIENTRY
2663_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2664                         GLint xoffset, GLint yoffset,
2665                         GLint x, GLint y, GLsizei width, GLsizei height )
2666{
2667   struct gl_texture_unit *texUnit;
2668   struct gl_texture_image *texImage;
2669   GLsizei postConvWidth = width, postConvHeight = height;
2670   GET_CURRENT_CONTEXT(ctx);
2671   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2672
2673   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2674      _mesa_update_state(ctx);
2675
2676   /* XXX should test internal format */
2677   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2678
2679   if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2680                                   postConvWidth, postConvHeight))
2681      return;
2682
2683   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2684   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2685   ASSERT(texImage);
2686
2687   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2688   xoffset += texImage->Border;
2689   yoffset += texImage->Border;
2690
2691   ASSERT(ctx->Driver.CopyTexSubImage2D);
2692   (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2693                                    xoffset, yoffset, x, y, width, height);
2694   ctx->NewState |= _NEW_TEXTURE;
2695}
2696
2697
2698
2699void GLAPIENTRY
2700_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2701                         GLint xoffset, GLint yoffset, GLint zoffset,
2702                         GLint x, GLint y, GLsizei width, GLsizei height )
2703{
2704   struct gl_texture_unit *texUnit;
2705   struct gl_texture_image *texImage;
2706   GLsizei postConvWidth = width, postConvHeight = height;
2707   GET_CURRENT_CONTEXT(ctx);
2708   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2709
2710   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2711      _mesa_update_state(ctx);
2712
2713   /* XXX should test internal format */
2714   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2715
2716   if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2717                                   zoffset, postConvWidth, postConvHeight))
2718      return;
2719
2720   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2721   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2722   ASSERT(texImage);
2723
2724   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2725   xoffset += texImage->Border;
2726   yoffset += texImage->Border;
2727   zoffset += texImage->Border;
2728
2729   ASSERT(ctx->Driver.CopyTexSubImage3D);
2730   (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2731                                    xoffset, yoffset, zoffset,
2732                                    x, y, width, height);
2733   ctx->NewState |= _NEW_TEXTURE;
2734}
2735
2736
2737
2738
2739/**********************************************************************/
2740/******                   Compressed Textures                    ******/
2741/**********************************************************************/
2742
2743
2744/**
2745 * Error checking for glCompressedTexImage[123]D().
2746 * \return error code or GL_NO_ERROR.
2747 */
2748static GLenum
2749compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
2750                               GLenum target, GLint level,
2751                               GLenum internalFormat, GLsizei width,
2752                               GLsizei height, GLsizei depth, GLint border,
2753                               GLsizei imageSize)
2754{
2755   GLint expectedSize, maxLevels = 0, maxTextureSize;
2756
2757   if (dimensions == 1) {
2758      /* 1D compressed textures not allowed */
2759      return GL_INVALID_ENUM;
2760   }
2761   else if (dimensions == 2) {
2762      if (target == GL_PROXY_TEXTURE_2D) {
2763         maxLevels = ctx->Const.MaxTextureLevels;
2764      }
2765      else if (target == GL_TEXTURE_2D) {
2766         maxLevels = ctx->Const.MaxTextureLevels;
2767      }
2768      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
2769         if (!ctx->Extensions.ARB_texture_cube_map)
2770            return GL_INVALID_ENUM; /*target*/
2771         maxLevels = ctx->Const.MaxCubeTextureLevels;
2772      }
2773      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2774               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2775         if (!ctx->Extensions.ARB_texture_cube_map)
2776            return GL_INVALID_ENUM; /*target*/
2777         maxLevels = ctx->Const.MaxCubeTextureLevels;
2778      }
2779      else {
2780         return GL_INVALID_ENUM; /*target*/
2781      }
2782   }
2783   else if (dimensions == 3) {
2784      /* 3D compressed textures not allowed */
2785      return GL_INVALID_ENUM;
2786   }
2787
2788   maxTextureSize = 1 << (maxLevels - 1);
2789
2790   if (!is_compressed_format(ctx, internalFormat))
2791      return GL_INVALID_ENUM;
2792
2793   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
2794      return GL_INVALID_ENUM;
2795
2796   if (border != 0)
2797      return GL_INVALID_VALUE;
2798
2799   /*
2800    * XXX We should probably use the proxy texture error check function here.
2801    */
2802   if (width < 1 || width > maxTextureSize ||
2803       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1))
2804      return GL_INVALID_VALUE;
2805
2806   if ((height < 1 || height > maxTextureSize ||
2807       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1))
2808       && dimensions > 1)
2809      return GL_INVALID_VALUE;
2810
2811   if ((depth < 1 || depth > maxTextureSize ||
2812       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1))
2813       && dimensions > 2)
2814      return GL_INVALID_VALUE;
2815
2816   /* For cube map, width must equal height */
2817   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2818       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
2819      return GL_INVALID_VALUE;
2820
2821   if (level < 0 || level >= maxLevels)
2822      return GL_INVALID_VALUE;
2823
2824   expectedSize = ctx->Driver.CompressedTextureSize(ctx, width, height, depth,
2825                                                    internalFormat);
2826   if (expectedSize != imageSize)
2827      return GL_INVALID_VALUE;
2828
2829   return GL_NO_ERROR;
2830}
2831
2832
2833/**
2834 * Error checking for glCompressedTexSubImage[123]D().
2835 * \warning  There are some bad assumptions here about the size of compressed
2836 *           texture tiles (multiple of 4) used to test the validity of the
2837 *           offset and size parameters.
2838 * \return error code or GL_NO_ERROR.
2839 */
2840static GLenum
2841compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
2842                                  GLenum target, GLint level,
2843                                  GLint xoffset, GLint yoffset, GLint zoffset,
2844                                  GLsizei width, GLsizei height, GLsizei depth,
2845                                  GLenum format, GLsizei imageSize)
2846{
2847   GLint expectedSize, maxLevels = 0, maxTextureSize;
2848   (void) zoffset;
2849
2850   if (dimensions == 1) {
2851      /* 1D compressed textures not allowed */
2852      return GL_INVALID_ENUM;
2853   }
2854   else if (dimensions == 2) {
2855      if (target == GL_PROXY_TEXTURE_2D) {
2856         maxLevels = ctx->Const.MaxTextureLevels;
2857      }
2858      else if (target == GL_TEXTURE_2D) {
2859         maxLevels = ctx->Const.MaxTextureLevels;
2860      }
2861      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
2862         if (!ctx->Extensions.ARB_texture_cube_map)
2863            return GL_INVALID_ENUM; /*target*/
2864         maxLevels = ctx->Const.MaxCubeTextureLevels;
2865      }
2866      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2867               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2868         if (!ctx->Extensions.ARB_texture_cube_map)
2869            return GL_INVALID_ENUM; /*target*/
2870         maxLevels = ctx->Const.MaxCubeTextureLevels;
2871      }
2872      else {
2873         return GL_INVALID_ENUM; /*target*/
2874      }
2875   }
2876   else if (dimensions == 3) {
2877      /* 3D compressed textures not allowed */
2878      return GL_INVALID_ENUM;
2879   }
2880
2881   maxTextureSize = 1 << (maxLevels - 1);
2882
2883   if (!is_compressed_format(ctx, format))
2884      return GL_INVALID_ENUM;
2885
2886   if (width < 1 || width > maxTextureSize)
2887      return GL_INVALID_VALUE;
2888
2889   if ((height < 1 || height > maxTextureSize)
2890       && dimensions > 1)
2891      return GL_INVALID_VALUE;
2892
2893   if (level < 0 || level >= maxLevels)
2894      return GL_INVALID_VALUE;
2895
2896   /* XXX these tests are specific to the compressed format.
2897    * this code should be generalized in some way.
2898    */
2899   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
2900      return GL_INVALID_VALUE;
2901
2902   if ((width & 3) != 0 && width != 2 && width != 1)
2903      return GL_INVALID_VALUE;
2904
2905   if ((height & 3) != 0 && height != 2 && height != 1)
2906      return GL_INVALID_VALUE;
2907
2908   expectedSize = ctx->Driver.CompressedTextureSize(ctx, width, height, depth,
2909                                                    format);
2910   if (expectedSize != imageSize)
2911      return GL_INVALID_VALUE;
2912
2913   return GL_NO_ERROR;
2914}
2915
2916
2917
2918void GLAPIENTRY
2919_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2920                              GLenum internalFormat, GLsizei width,
2921                              GLint border, GLsizei imageSize,
2922                              const GLvoid *data)
2923{
2924   GET_CURRENT_CONTEXT(ctx);
2925   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2926
2927   if (target == GL_TEXTURE_1D) {
2928      /* non-proxy target */
2929      struct gl_texture_unit *texUnit;
2930      struct gl_texture_object *texObj;
2931      struct gl_texture_image *texImage;
2932      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
2933                               internalFormat, width, 1, 1, border, imageSize);
2934      if (error) {
2935         _mesa_error(ctx, error, "glCompressedTexImage1D");
2936         return;
2937      }
2938
2939      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2940      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2941      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2942      if (!texImage) {
2943         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
2944         return;
2945      }
2946      else if (texImage->Data) {
2947	 ctx->Driver.FreeTexImageData( ctx, texImage );
2948      }
2949      ASSERT(texImage->Data == NULL);
2950
2951      _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
2952                                 border, internalFormat);
2953
2954      ASSERT(ctx->Driver.CompressedTexImage1D);
2955      (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2956                                          internalFormat, width, border,
2957                                          imageSize, data,
2958                                          texObj, texImage);
2959
2960      /* state update */
2961      texObj->Complete = GL_FALSE;
2962      ctx->NewState |= _NEW_TEXTURE;
2963   }
2964   else if (target == GL_PROXY_TEXTURE_1D) {
2965      /* Proxy texture: check for errors and update proxy state */
2966      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
2967                               internalFormat, width, 1, 1, border, imageSize);
2968      if (!error) {
2969         ASSERT(ctx->Driver.TestProxyTexImage);
2970         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2971                                             internalFormat, GL_NONE, GL_NONE,
2972                                             width, 1, 1, border);
2973      }
2974      if (error) {
2975         /* if error, clear all proxy texture image parameters */
2976         struct gl_texture_image *texImage;
2977         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2978         if (texImage)
2979            clear_teximage_fields(texImage);
2980      }
2981      else {
2982         /* store the teximage parameters */
2983         struct gl_texture_unit *texUnit;
2984         struct gl_texture_image *texImage;
2985         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2986         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2987         _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
2988                                    border, internalFormat);
2989      }
2990   }
2991   else {
2992      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
2993      return;
2994   }
2995}
2996
2997
2998void GLAPIENTRY
2999_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3000                              GLenum internalFormat, GLsizei width,
3001                              GLsizei height, GLint border, GLsizei imageSize,
3002                              const GLvoid *data)
3003{
3004   GET_CURRENT_CONTEXT(ctx);
3005   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3006
3007   if (target == GL_TEXTURE_2D ||
3008       (ctx->Extensions.ARB_texture_cube_map &&
3009        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3010        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3011      /* non-proxy target */
3012      struct gl_texture_unit *texUnit;
3013      struct gl_texture_object *texObj;
3014      struct gl_texture_image *texImage;
3015      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3016                          internalFormat, width, height, 1, border, imageSize);
3017      if (error) {
3018         _mesa_error(ctx, error, "glCompressedTexImage2D");
3019         return;
3020      }
3021
3022      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3023      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3024      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
3025      if (!texImage) {
3026         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3027         return;
3028      }
3029      else if (texImage->Data) {
3030	 ctx->Driver.FreeTexImageData( ctx, texImage );
3031      }
3032      ASSERT(texImage->Data == NULL);
3033
3034      _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3035                                 border, internalFormat);
3036
3037      ASSERT(ctx->Driver.CompressedTexImage2D);
3038      (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
3039                                          internalFormat, width, height,
3040                                          border, imageSize, data,
3041                                          texObj, texImage);
3042
3043      /* state update */
3044      texObj->Complete = GL_FALSE;
3045      ctx->NewState |= _NEW_TEXTURE;
3046   }
3047   else if (target == GL_PROXY_TEXTURE_2D ||
3048            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3049             ctx->Extensions.ARB_texture_cube_map)) {
3050      /* Proxy texture: check for errors and update proxy state */
3051      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3052                          internalFormat, width, height, 1, border, imageSize);
3053      if (!error) {
3054         ASSERT(ctx->Driver.TestProxyTexImage);
3055         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3056                                              internalFormat, GL_NONE, GL_NONE,
3057                                              width, height, 1, border);
3058      }
3059      if (error) {
3060         /* if error, clear all proxy texture image parameters */
3061         struct gl_texture_image *texImage;
3062         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3063         if (texImage)
3064            clear_teximage_fields(texImage);
3065      }
3066      else {
3067         /* store the teximage parameters */
3068         struct gl_texture_unit *texUnit;
3069         struct gl_texture_image *texImage;
3070         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3071         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3072         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3073                                    border, internalFormat);
3074      }
3075   }
3076   else {
3077      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3078      return;
3079   }
3080}
3081
3082
3083void GLAPIENTRY
3084_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3085                              GLenum internalFormat, GLsizei width,
3086                              GLsizei height, GLsizei depth, GLint border,
3087                              GLsizei imageSize, const GLvoid *data)
3088{
3089   GET_CURRENT_CONTEXT(ctx);
3090   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3091
3092   if (target == GL_TEXTURE_3D) {
3093      /* non-proxy target */
3094      struct gl_texture_unit *texUnit;
3095      struct gl_texture_object *texObj;
3096      struct gl_texture_image *texImage;
3097      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3098                      internalFormat, width, height, depth, border, imageSize);
3099      if (error) {
3100         _mesa_error(ctx, error, "glCompressedTexImage3D");
3101         return;
3102      }
3103
3104      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3105      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3106      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
3107      if (!texImage) {
3108         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3109         return;
3110      }
3111      else if (texImage->Data) {
3112	 ctx->Driver.FreeTexImageData( ctx, texImage );
3113      }
3114      ASSERT(texImage->Data == NULL);
3115
3116      _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
3117                                 border, internalFormat);
3118
3119      ASSERT(ctx->Driver.CompressedTexImage3D);
3120      (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3121                                          internalFormat,
3122                                          width, height, depth,
3123                                          border, imageSize, data,
3124                                          texObj, texImage);
3125
3126      /* state update */
3127      texObj->Complete = GL_FALSE;
3128      ctx->NewState |= _NEW_TEXTURE;
3129   }
3130   else if (target == GL_PROXY_TEXTURE_3D) {
3131      /* Proxy texture: check for errors and update proxy state */
3132      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3133                      internalFormat, width, height, depth, border, imageSize);
3134      if (!error) {
3135         ASSERT(ctx->Driver.TestProxyTexImage);
3136         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3137                                             internalFormat, GL_NONE, GL_NONE,
3138                                             width, height, depth, border);
3139      }
3140      if (error) {
3141         /* if error, clear all proxy texture image parameters */
3142         struct gl_texture_image *texImage;
3143         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3144         if (texImage)
3145            clear_teximage_fields(texImage);
3146      }
3147      else {
3148         /* store the teximage parameters */
3149         struct gl_texture_unit *texUnit;
3150         struct gl_texture_image *texImage;
3151         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3152         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3153         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3154                                    depth, border, internalFormat);
3155      }
3156   }
3157   else {
3158      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3159      return;
3160   }
3161}
3162
3163
3164void GLAPIENTRY
3165_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3166                                 GLsizei width, GLenum format,
3167                                 GLsizei imageSize, const GLvoid *data)
3168{
3169   struct gl_texture_unit *texUnit;
3170   struct gl_texture_object *texObj;
3171   struct gl_texture_image *texImage;
3172   GLenum error;
3173   GET_CURRENT_CONTEXT(ctx);
3174   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3175
3176   error = compressed_subtexture_error_check(ctx, 1, target, level,
3177                                xoffset, 0, 0, width, 1, 1, format, imageSize);
3178   if (error) {
3179      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3180      return;
3181   }
3182
3183   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3184   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3185   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3186   assert(texImage);
3187
3188   if ((GLint) format != texImage->InternalFormat) {
3189      _mesa_error(ctx, GL_INVALID_OPERATION,
3190                  "glCompressedTexSubImage1D(format)");
3191      return;
3192   }
3193
3194   if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
3195      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
3196      return;
3197   }
3198
3199   if (width == 0)
3200      return;  /* no-op, not an error */
3201
3202   if (ctx->Driver.CompressedTexSubImage1D) {
3203      (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3204                                             xoffset, width,
3205                                             format, imageSize, data,
3206                                             texObj, texImage);
3207   }
3208   ctx->NewState |= _NEW_TEXTURE;
3209}
3210
3211
3212void GLAPIENTRY
3213_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3214                                 GLint yoffset, GLsizei width, GLsizei height,
3215                                 GLenum format, GLsizei imageSize,
3216                                 const GLvoid *data)
3217{
3218   struct gl_texture_unit *texUnit;
3219   struct gl_texture_object *texObj;
3220   struct gl_texture_image *texImage;
3221   GLenum error;
3222   GET_CURRENT_CONTEXT(ctx);
3223   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3224
3225   error = compressed_subtexture_error_check(ctx, 2, target, level,
3226                     xoffset, yoffset, 0, width, height, 1, format, imageSize);
3227   if (error) {
3228      /* XXX proxy target? */
3229      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3230      return;
3231   }
3232
3233   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3234   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3235   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3236   assert(texImage);
3237
3238   if ((GLint) format != texImage->InternalFormat) {
3239      _mesa_error(ctx, GL_INVALID_OPERATION,
3240                  "glCompressedTexSubImage2D(format)");
3241      return;
3242   }
3243
3244   if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3245       ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
3246      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3247      return;
3248   }
3249
3250   if (width == 0 || height == 0)
3251      return;  /* no-op, not an error */
3252
3253   if (ctx->Driver.CompressedTexSubImage2D) {
3254      (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3255                                             xoffset, yoffset, width, height,
3256                                             format, imageSize, data,
3257                                             texObj, texImage);
3258   }
3259   ctx->NewState |= _NEW_TEXTURE;
3260}
3261
3262
3263void GLAPIENTRY
3264_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3265                                 GLint yoffset, GLint zoffset, GLsizei width,
3266                                 GLsizei height, GLsizei depth, GLenum format,
3267                                 GLsizei imageSize, const GLvoid *data)
3268{
3269   struct gl_texture_unit *texUnit;
3270   struct gl_texture_object *texObj;
3271   struct gl_texture_image *texImage;
3272   GLenum error;
3273   GET_CURRENT_CONTEXT(ctx);
3274   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3275
3276   error = compressed_subtexture_error_check(ctx, 3, target, level,
3277           xoffset, yoffset, zoffset, width, height, depth, format, imageSize);
3278   if (error) {
3279      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3280      return;
3281   }
3282
3283   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3284   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3285   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3286   assert(texImage);
3287
3288   if ((GLint) format != texImage->InternalFormat) {
3289      _mesa_error(ctx, GL_INVALID_OPERATION,
3290                  "glCompressedTexSubImage3D(format)");
3291      return;
3292   }
3293
3294   if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3295       ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
3296       ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
3297      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3298      return;
3299   }
3300
3301   if (width == 0 || height == 0 || depth == 0)
3302      return;  /* no-op, not an error */
3303
3304   if (ctx->Driver.CompressedTexSubImage3D) {
3305      (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3306                                             xoffset, yoffset, zoffset,
3307                                             width, height, depth,
3308                                             format, imageSize, data,
3309                                             texObj, texImage);
3310   }
3311   ctx->NewState |= _NEW_TEXTURE;
3312}
3313
3314
3315void GLAPIENTRY
3316_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3317{
3318   const struct gl_texture_unit *texUnit;
3319   const struct gl_texture_object *texObj;
3320   struct gl_texture_image *texImage;
3321   GLint maxLevels;
3322   GET_CURRENT_CONTEXT(ctx);
3323   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3324
3325   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3326   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3327   if (!texObj) {
3328      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
3329      return;
3330   }
3331
3332   maxLevels = _mesa_max_texture_levels(ctx, target);
3333   ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
3334
3335   if (level < 0 || level >= maxLevels) {
3336      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3337      return;
3338   }
3339
3340   if (_mesa_is_proxy_texture(target)) {
3341      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3342      return;
3343   }
3344
3345   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3346   if (!texImage) {
3347      /* probably invalid mipmap level */
3348      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3349      return;
3350   }
3351
3352   if (!texImage->IsCompressed) {
3353      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3354      return;
3355   }
3356
3357   /* this typically calls _mesa_get_compressed_teximage() */
3358   ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
3359}
3360