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