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