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