teximage.c revision 1826ff3fb34e9fb19bc8d8dee2cce5280da5e069
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/** Debug helper: override the user-requested internal format */
2444static GLenum
2445override_internal_format(GLenum internalFormat, GLint width, GLint height)
2446{
2447#if 0
2448   if (internalFormat == GL_RGBA16F_ARB ||
2449       internalFormat == GL_RGBA32F_ARB) {
2450      printf("Convert rgba float tex to int %d x %d\n", width, height);
2451      return GL_RGBA;
2452   }
2453   else if (internalFormat == GL_RGB16F_ARB ||
2454            internalFormat == GL_RGB32F_ARB) {
2455      printf("Convert rgb float tex to int %d x %d\n", width, height);
2456      return GL_RGB;
2457   }
2458   else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
2459            internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
2460      printf("Convert luminance float tex to int %d x %d\n", width, height);
2461      return GL_LUMINANCE_ALPHA;
2462   }
2463   else if (internalFormat == GL_LUMINANCE16F_ARB ||
2464            internalFormat == GL_LUMINANCE32F_ARB) {
2465      printf("Convert luminance float tex to int %d x %d\n", width, height);
2466      return GL_LUMINANCE;
2467   }
2468   else if (internalFormat == GL_ALPHA16F_ARB ||
2469            internalFormat == GL_ALPHA32F_ARB) {
2470      printf("Convert luminance float tex to int %d x %d\n", width, height);
2471      return GL_ALPHA;
2472   }
2473   /*
2474   else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
2475      internalFormat = GL_RGBA;
2476   }
2477   */
2478   else {
2479      return internalFormat;
2480   }
2481#else
2482   return internalFormat;
2483#endif
2484}
2485
2486
2487/*
2488 * Called from the API.  Note that width includes the border.
2489 */
2490void GLAPIENTRY
2491_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2492                  GLsizei width, GLint border, GLenum format,
2493                  GLenum type, const GLvoid *pixels )
2494{
2495   GLsizei postConvWidth = width;
2496   GET_CURRENT_CONTEXT(ctx);
2497   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2498
2499   internalFormat = override_internal_format(internalFormat, width, 1);
2500
2501#if FEATURE_convolve
2502   if (_mesa_is_color_format(internalFormat)) {
2503      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2504   }
2505#endif
2506
2507   if (target == GL_TEXTURE_1D) {
2508      /* non-proxy target */
2509      struct gl_texture_unit *texUnit;
2510      struct gl_texture_object *texObj;
2511      struct gl_texture_image *texImage;
2512      const GLuint face = _mesa_tex_target_to_face(target);
2513
2514      if (texture_error_check(ctx, target, level, internalFormat,
2515                              format, type, 1, postConvWidth, 1, 1, border)) {
2516         return;   /* error was recorded */
2517      }
2518
2519      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2520	 _mesa_update_state(ctx);
2521
2522      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2523      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2524      _mesa_lock_texture(ctx, texObj);
2525      {
2526	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2527	 if (!texImage) {
2528	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2529	    goto out;
2530	 }
2531
2532	 if (texImage->Data) {
2533	    ctx->Driver.FreeTexImageData( ctx, texImage );
2534	 }
2535
2536	 ASSERT(texImage->Data == NULL);
2537
2538	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2539	 _mesa_init_teximage_fields(ctx, target, texImage,
2540				    postConvWidth, 1, 1,
2541				    border, internalFormat);
2542
2543	 ASSERT(ctx->Driver.TexImage1D);
2544
2545	 /* Give the texture to the driver!  <pixels> may be null! */
2546	 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
2547				   width, border, format, type, pixels,
2548				   &ctx->Unpack, texObj, texImage);
2549
2550	 ASSERT(texImage->TexFormat);
2551
2552	 update_fbo_texture(ctx, texObj, face, level);
2553
2554	 /* state update */
2555	 texObj->_Complete = GL_FALSE;
2556	 ctx->NewState |= _NEW_TEXTURE;
2557      }
2558   out:
2559      _mesa_unlock_texture(ctx, texObj);
2560   }
2561   else if (target == GL_PROXY_TEXTURE_1D) {
2562      /* Proxy texture: check for errors and update proxy state */
2563      struct gl_texture_image *texImage;
2564      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2565      if (texture_error_check(ctx, target, level, internalFormat,
2566                              format, type, 1, postConvWidth, 1, 1, border)) {
2567         /* when error, clear all proxy texture image parameters */
2568         if (texImage)
2569            clear_teximage_fields(texImage);
2570      }
2571      else {
2572         /* no error, set the tex image parameters */
2573         ASSERT(texImage);
2574         _mesa_init_teximage_fields(ctx, target, texImage,
2575                                    postConvWidth, 1, 1,
2576                                    border, internalFormat);
2577         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2578                                          internalFormat, format, type);
2579      }
2580   }
2581   else {
2582      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2583      return;
2584   }
2585}
2586
2587
2588void GLAPIENTRY
2589_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2590                  GLsizei width, GLsizei height, GLint border,
2591                  GLenum format, GLenum type,
2592                  const GLvoid *pixels )
2593{
2594   GLsizei postConvWidth = width, postConvHeight = height;
2595   GET_CURRENT_CONTEXT(ctx);
2596   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2597
2598   internalFormat = override_internal_format(internalFormat, width, height);
2599
2600#if FEATURE_convolve
2601   if (_mesa_is_color_format(internalFormat)) {
2602      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2603					 &postConvHeight);
2604   }
2605#endif
2606
2607   if (target == GL_TEXTURE_2D ||
2608       (ctx->Extensions.ARB_texture_cube_map &&
2609        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2610        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2611       (ctx->Extensions.NV_texture_rectangle &&
2612        target == GL_TEXTURE_RECTANGLE_NV) ||
2613       (ctx->Extensions.MESA_texture_array &&
2614        target == GL_TEXTURE_1D_ARRAY_EXT)) {
2615      /* non-proxy target */
2616      struct gl_texture_unit *texUnit;
2617      struct gl_texture_object *texObj;
2618      struct gl_texture_image *texImage;
2619      const GLuint face = _mesa_tex_target_to_face(target);
2620
2621      if (texture_error_check(ctx, target, level, internalFormat,
2622                              format, type, 2, postConvWidth, postConvHeight,
2623                              1, border)) {
2624         return;   /* error was recorded */
2625      }
2626
2627      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2628	 _mesa_update_state(ctx);
2629
2630      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2631      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2632      _mesa_lock_texture(ctx, texObj);
2633      {
2634	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2635	 if (!texImage) {
2636	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2637	    goto out;
2638	 }
2639
2640	 if (texImage->Data) {
2641	    ctx->Driver.FreeTexImageData( ctx, texImage );
2642	 }
2643
2644	 ASSERT(texImage->Data == NULL);
2645	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2646	 _mesa_init_teximage_fields(ctx, target, texImage,
2647				    postConvWidth, postConvHeight, 1,
2648				    border, internalFormat);
2649
2650	 ASSERT(ctx->Driver.TexImage2D);
2651
2652	 /* Give the texture to the driver!  <pixels> may be null! */
2653	 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
2654				   width, height, border, format, type, pixels,
2655				   &ctx->Unpack, texObj, texImage);
2656
2657	 ASSERT(texImage->TexFormat);
2658
2659	 update_fbo_texture(ctx, texObj, face, level);
2660
2661	 /* state update */
2662	 texObj->_Complete = GL_FALSE;
2663	 ctx->NewState |= _NEW_TEXTURE;
2664      }
2665   out:
2666      _mesa_unlock_texture(ctx, texObj);
2667   }
2668   else if (target == GL_PROXY_TEXTURE_2D ||
2669            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2670             ctx->Extensions.ARB_texture_cube_map) ||
2671            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2672             ctx->Extensions.NV_texture_rectangle) ||
2673            (ctx->Extensions.MESA_texture_array &&
2674             target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
2675      /* Proxy texture: check for errors and update proxy state */
2676      struct gl_texture_image *texImage;
2677      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2678      if (texture_error_check(ctx, target, level, internalFormat,
2679                              format, type, 2, postConvWidth, postConvHeight,
2680                              1, border)) {
2681         /* when error, clear all proxy texture image parameters */
2682         if (texImage)
2683            clear_teximage_fields(texImage);
2684      }
2685      else {
2686         /* no error, set the tex image parameters */
2687         _mesa_init_teximage_fields(ctx, target, texImage,
2688                                    postConvWidth, postConvHeight, 1,
2689                                    border, internalFormat);
2690         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2691                                          internalFormat, format, type);
2692      }
2693   }
2694   else {
2695      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2696      return;
2697   }
2698}
2699
2700
2701/*
2702 * Called by the API or display list executor.
2703 * Note that width and height include the border.
2704 */
2705void GLAPIENTRY
2706_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2707                  GLsizei width, GLsizei height, GLsizei depth,
2708                  GLint border, GLenum format, GLenum type,
2709                  const GLvoid *pixels )
2710{
2711   GET_CURRENT_CONTEXT(ctx);
2712   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2713
2714   internalFormat = override_internal_format(internalFormat, width, height);
2715
2716   if (target == GL_TEXTURE_3D ||
2717       (ctx->Extensions.MESA_texture_array &&
2718        target == GL_TEXTURE_2D_ARRAY_EXT)) {
2719      /* non-proxy target */
2720      struct gl_texture_unit *texUnit;
2721      struct gl_texture_object *texObj;
2722      struct gl_texture_image *texImage;
2723      const GLuint face = _mesa_tex_target_to_face(target);
2724
2725      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2726                              format, type, 3, width, height, depth, border)) {
2727         return;   /* error was recorded */
2728      }
2729
2730      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2731	 _mesa_update_state(ctx);
2732
2733      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2734      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2735      _mesa_lock_texture(ctx, texObj);
2736      {
2737	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2738	 if (!texImage) {
2739	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2740	    goto out;
2741	 }
2742
2743	 if (texImage->Data) {
2744	    ctx->Driver.FreeTexImageData( ctx, texImage );
2745	 }
2746
2747	 ASSERT(texImage->Data == NULL);
2748	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2749	 _mesa_init_teximage_fields(ctx, target, texImage,
2750				    width, height, depth,
2751				    border, internalFormat);
2752
2753	 ASSERT(ctx->Driver.TexImage3D);
2754
2755	 /* Give the texture to the driver!  <pixels> may be null! */
2756	 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
2757				   width, height, depth, border, format, type,
2758				   pixels, &ctx->Unpack, texObj, texImage);
2759
2760	 ASSERT(texImage->TexFormat);
2761
2762	 update_fbo_texture(ctx, texObj, face, level);
2763
2764	 /* state update */
2765	 texObj->_Complete = GL_FALSE;
2766	 ctx->NewState |= _NEW_TEXTURE;
2767      }
2768   out:
2769      _mesa_unlock_texture(ctx, texObj);
2770   }
2771   else if (target == GL_PROXY_TEXTURE_3D ||
2772       (ctx->Extensions.MESA_texture_array &&
2773        target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
2774      /* Proxy texture: check for errors and update proxy state */
2775      struct gl_texture_image *texImage;
2776      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2777      if (texture_error_check(ctx, target, level, internalFormat,
2778                              format, type, 3, width, height, depth, border)) {
2779         /* when error, clear all proxy texture image parameters */
2780         if (texImage)
2781            clear_teximage_fields(texImage);
2782      }
2783      else {
2784         /* no error, set the tex image parameters */
2785         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2786                                    depth, border, internalFormat);
2787         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2788                                          internalFormat, format, type);
2789      }
2790   }
2791   else {
2792      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2793      return;
2794   }
2795}
2796
2797
2798void GLAPIENTRY
2799_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2800                     GLsizei width, GLsizei height, GLsizei depth,
2801                     GLint border, GLenum format, GLenum type,
2802                     const GLvoid *pixels )
2803{
2804   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2805                    depth, border, format, type, pixels);
2806}
2807
2808
2809
2810void GLAPIENTRY
2811_mesa_TexSubImage1D( GLenum target, GLint level,
2812                     GLint xoffset, GLsizei width,
2813                     GLenum format, GLenum type,
2814                     const GLvoid *pixels )
2815{
2816   GLsizei postConvWidth = width;
2817   struct gl_texture_unit *texUnit;
2818   struct gl_texture_object *texObj;
2819   struct gl_texture_image *texImage = NULL;
2820   GET_CURRENT_CONTEXT(ctx);
2821   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2822
2823   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2824      _mesa_update_state(ctx);
2825
2826#if FEATURE_convolve
2827   /* XXX should test internal format */
2828   if (_mesa_is_color_format(format)) {
2829      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2830   }
2831#endif
2832
2833   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2834			       postConvWidth, 1, 1, format, type)) {
2835      return;   /* error was detected */
2836   }
2837
2838
2839   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2840   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2841   assert(texObj);
2842
2843   _mesa_lock_texture(ctx, texObj);
2844   {
2845      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2846
2847      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2848				  postConvWidth, 1, 1, format, type, texImage)) {
2849	 goto out;   /* error was detected */
2850      }
2851
2852      if (width == 0)
2853	 goto out;  /* no-op, not an error */
2854
2855      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2856      xoffset += texImage->Border;
2857
2858      ASSERT(ctx->Driver.TexSubImage1D);
2859      (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
2860				   format, type, pixels, &ctx->Unpack,
2861				   texObj, texImage);
2862      ctx->NewState |= _NEW_TEXTURE;
2863   }
2864 out:
2865   _mesa_unlock_texture(ctx, texObj);
2866}
2867
2868
2869void GLAPIENTRY
2870_mesa_TexSubImage2D( GLenum target, GLint level,
2871                     GLint xoffset, GLint yoffset,
2872                     GLsizei width, GLsizei height,
2873                     GLenum format, GLenum type,
2874                     const GLvoid *pixels )
2875{
2876   GLsizei postConvWidth = width, postConvHeight = height;
2877   struct gl_texture_unit *texUnit;
2878   struct gl_texture_object *texObj;
2879   struct gl_texture_image *texImage;
2880   GET_CURRENT_CONTEXT(ctx);
2881   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2882
2883   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2884      _mesa_update_state(ctx);
2885
2886#if FEATURE_convolve
2887   /* XXX should test internal format */
2888   if (_mesa_is_color_format(format)) {
2889      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2890                                         &postConvHeight);
2891   }
2892#endif
2893
2894   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2895			      postConvWidth, postConvHeight, 1, format, type)) {
2896      return;   /* error was detected */
2897   }
2898
2899   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2900   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2901   _mesa_lock_texture(ctx, texObj);
2902   {
2903      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2904
2905      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2906				  postConvWidth, postConvHeight, 1, format, type,
2907				  texImage)) {
2908	 goto out;   /* error was detected */
2909      }
2910
2911      if (width == 0 || height == 0)
2912	 goto out;  /* no-op, not an error */
2913
2914      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2915      xoffset += texImage->Border;
2916      yoffset += texImage->Border;
2917
2918      ASSERT(ctx->Driver.TexSubImage2D);
2919      (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2920				   width, height, format, type, pixels,
2921				   &ctx->Unpack, texObj, texImage);
2922      ctx->NewState |= _NEW_TEXTURE;
2923   }
2924 out:
2925   _mesa_unlock_texture(ctx, texObj);
2926}
2927
2928
2929
2930void GLAPIENTRY
2931_mesa_TexSubImage3D( GLenum target, GLint level,
2932                     GLint xoffset, GLint yoffset, GLint zoffset,
2933                     GLsizei width, GLsizei height, GLsizei depth,
2934                     GLenum format, GLenum type,
2935                     const GLvoid *pixels )
2936{
2937   struct gl_texture_unit *texUnit;
2938   struct gl_texture_object *texObj;
2939   struct gl_texture_image *texImage;
2940   GET_CURRENT_CONTEXT(ctx);
2941   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2942
2943   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2944      _mesa_update_state(ctx);
2945
2946   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2947                              width, height, depth, format, type)) {
2948      return;   /* error was detected */
2949   }
2950
2951   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2952   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2953
2954   _mesa_lock_texture(ctx, texObj);
2955   {
2956      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2957
2958      if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
2959				  width, height, depth, format, type, texImage)) {
2960	 goto out;   /* error was detected */
2961      }
2962
2963      if (width == 0 || height == 0 || height == 0)
2964	 goto out;  /* no-op, not an error */
2965
2966      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2967      xoffset += texImage->Border;
2968      yoffset += texImage->Border;
2969      zoffset += texImage->Border;
2970
2971      ASSERT(ctx->Driver.TexSubImage3D);
2972      (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2973				   xoffset, yoffset, zoffset,
2974				   width, height, depth,
2975				   format, type, pixels,
2976				   &ctx->Unpack, texObj, texImage );
2977      ctx->NewState |= _NEW_TEXTURE;
2978   }
2979 out:
2980   _mesa_unlock_texture(ctx, texObj);
2981}
2982
2983
2984
2985void GLAPIENTRY
2986_mesa_CopyTexImage1D( GLenum target, GLint level,
2987                      GLenum internalFormat,
2988                      GLint x, GLint y,
2989                      GLsizei width, GLint border )
2990{
2991   struct gl_texture_unit *texUnit;
2992   struct gl_texture_object *texObj;
2993   struct gl_texture_image *texImage;
2994   GLsizei postConvWidth = width;
2995   const GLuint face = _mesa_tex_target_to_face(target);
2996   GET_CURRENT_CONTEXT(ctx);
2997   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2998
2999   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
3000      _mesa_update_state(ctx);
3001
3002#if FEATURE_convolve
3003   if (_mesa_is_color_format(internalFormat)) {
3004      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
3005   }
3006#endif
3007
3008   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
3009                               postConvWidth, 1, border))
3010      return;
3011
3012   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3013   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3014   _mesa_lock_texture(ctx, texObj);
3015   {
3016      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3017      if (!texImage) {
3018	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
3019	 goto out;
3020      }
3021
3022      if (texImage->Data) {
3023	 ctx->Driver.FreeTexImageData( ctx, texImage );
3024      }
3025
3026      ASSERT(texImage->Data == NULL);
3027
3028      clear_teximage_fields(texImage); /* not really needed, but helpful */
3029      _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
3030				 border, internalFormat);
3031
3032
3033      ASSERT(ctx->Driver.CopyTexImage1D);
3034      (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
3035				    x, y, width, border);
3036
3037      ASSERT(texImage->TexFormat);
3038
3039      update_fbo_texture(ctx, texObj, face, level);
3040
3041      /* state update */
3042      texObj->_Complete = GL_FALSE;
3043      ctx->NewState |= _NEW_TEXTURE;
3044   }
3045 out:
3046   _mesa_unlock_texture(ctx, texObj);
3047}
3048
3049
3050
3051void GLAPIENTRY
3052_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
3053                      GLint x, GLint y, GLsizei width, GLsizei height,
3054                      GLint border )
3055{
3056   struct gl_texture_unit *texUnit;
3057   struct gl_texture_object *texObj;
3058   struct gl_texture_image *texImage;
3059   GLsizei postConvWidth = width, postConvHeight = height;
3060   const GLuint face = _mesa_tex_target_to_face(target);
3061   GET_CURRENT_CONTEXT(ctx);
3062   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3063
3064   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
3065      _mesa_update_state(ctx);
3066
3067#if FEATURE_convolve
3068   if (_mesa_is_color_format(internalFormat)) {
3069      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
3070                                         &postConvHeight);
3071   }
3072#endif
3073
3074   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
3075                               postConvWidth, postConvHeight, border))
3076      return;
3077
3078   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3079   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3080
3081   _mesa_lock_texture(ctx, texObj);
3082   {
3083      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3084
3085      if (!texImage) {
3086	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
3087	 goto out;
3088      }
3089
3090      if (texImage->Data) {
3091	 ctx->Driver.FreeTexImageData( ctx, texImage );
3092      }
3093
3094      ASSERT(texImage->Data == NULL);
3095
3096      clear_teximage_fields(texImage); /* not really needed, but helpful */
3097      _mesa_init_teximage_fields(ctx, target, texImage,
3098				 postConvWidth, postConvHeight, 1,
3099				 border, internalFormat);
3100
3101      ASSERT(ctx->Driver.CopyTexImage2D);
3102      (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
3103				    x, y, width, height, border);
3104
3105      ASSERT(texImage->TexFormat);
3106
3107      update_fbo_texture(ctx, texObj, face, level);
3108
3109      /* state update */
3110      texObj->_Complete = GL_FALSE;
3111      ctx->NewState |= _NEW_TEXTURE;
3112   }
3113 out:
3114   _mesa_unlock_texture(ctx, texObj);
3115}
3116
3117
3118void GLAPIENTRY
3119_mesa_CopyTexSubImage1D( GLenum target, GLint level,
3120                         GLint xoffset, GLint x, GLint y, GLsizei width )
3121{
3122   struct gl_texture_unit *texUnit;
3123   struct gl_texture_object *texObj;
3124   struct gl_texture_image *texImage;
3125   GLsizei postConvWidth = width;
3126   GLint yoffset = 0;
3127   GLsizei height = 1;
3128
3129   GET_CURRENT_CONTEXT(ctx);
3130   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3131
3132   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
3133      _mesa_update_state(ctx);
3134
3135   if (copytexsubimage_error_check1(ctx, 1, target, level))
3136      return;
3137
3138   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3139   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3140
3141   _mesa_lock_texture(ctx, texObj);
3142   {
3143      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3144
3145#if FEATURE_convolve
3146      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3147         _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
3148      }
3149#endif
3150
3151      if (copytexsubimage_error_check2(ctx, 1, target, level,
3152				       xoffset, 0, 0, postConvWidth, 1,
3153				       texImage))
3154	 goto out;
3155
3156
3157      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3158      xoffset += texImage->Border;
3159
3160      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3161                                     &width, &height)) {
3162         ASSERT(ctx->Driver.CopyTexSubImage1D);
3163         ctx->Driver.CopyTexSubImage1D(ctx, target, level,
3164                                       xoffset, x, y, width);
3165      }
3166
3167      ctx->NewState |= _NEW_TEXTURE;
3168   }
3169 out:
3170   _mesa_unlock_texture(ctx, texObj);
3171}
3172
3173
3174
3175void GLAPIENTRY
3176_mesa_CopyTexSubImage2D( GLenum target, GLint level,
3177                         GLint xoffset, GLint yoffset,
3178                         GLint x, GLint y, GLsizei width, GLsizei height )
3179{
3180   struct gl_texture_unit *texUnit;
3181   struct gl_texture_object *texObj;
3182   struct gl_texture_image *texImage;
3183   GLsizei postConvWidth = width, postConvHeight = height;
3184   GET_CURRENT_CONTEXT(ctx);
3185   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3186
3187   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
3188      _mesa_update_state(ctx);
3189
3190   if (copytexsubimage_error_check1(ctx, 2, target, level))
3191      return;
3192
3193   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3194   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3195
3196   _mesa_lock_texture(ctx, texObj);
3197   {
3198      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3199
3200#if FEATURE_convolve
3201      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3202         _mesa_adjust_image_for_convolution(ctx, 2,
3203                                            &postConvWidth, &postConvHeight);
3204      }
3205#endif
3206
3207      if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
3208				       postConvWidth, postConvHeight, texImage))
3209	 goto out;
3210
3211      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3212      xoffset += texImage->Border;
3213      yoffset += texImage->Border;
3214
3215      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3216                                     &width, &height)) {
3217         ASSERT(ctx->Driver.CopyTexSubImage2D);
3218         ctx->Driver.CopyTexSubImage2D(ctx, target, level,
3219				       xoffset, yoffset, x, y, width, height);
3220      }
3221
3222      ctx->NewState |= _NEW_TEXTURE;
3223   }
3224 out:
3225   _mesa_unlock_texture(ctx, texObj);
3226}
3227
3228
3229
3230void GLAPIENTRY
3231_mesa_CopyTexSubImage3D( GLenum target, GLint level,
3232                         GLint xoffset, GLint yoffset, GLint zoffset,
3233                         GLint x, GLint y, GLsizei width, GLsizei height )
3234{
3235   struct gl_texture_unit *texUnit;
3236   struct gl_texture_object *texObj;
3237   struct gl_texture_image *texImage;
3238   GLsizei postConvWidth = width, postConvHeight = height;
3239   GET_CURRENT_CONTEXT(ctx);
3240   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3241
3242   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
3243      _mesa_update_state(ctx);
3244
3245   if (copytexsubimage_error_check1(ctx, 3, target, level))
3246      return;
3247
3248   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3249   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3250
3251   _mesa_lock_texture(ctx, texObj);
3252   {
3253      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3254
3255#if FEATURE_convolve
3256      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
3257         _mesa_adjust_image_for_convolution(ctx, 2,
3258                                            &postConvWidth, &postConvHeight);
3259      }
3260#endif
3261
3262      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
3263				       zoffset, postConvWidth, postConvHeight,
3264				       texImage))
3265	 goto out;
3266
3267      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3268      xoffset += texImage->Border;
3269      yoffset += texImage->Border;
3270      zoffset += texImage->Border;
3271
3272      if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3273                                     &width, &height)) {
3274         ASSERT(ctx->Driver.CopyTexSubImage3D);
3275         ctx->Driver.CopyTexSubImage3D(ctx, target, level,
3276				       xoffset, yoffset, zoffset,
3277				       x, y, width, height);
3278      }
3279
3280      ctx->NewState |= _NEW_TEXTURE;
3281   }
3282 out:
3283   _mesa_unlock_texture(ctx, texObj);
3284}
3285
3286
3287
3288
3289/**********************************************************************/
3290/******                   Compressed Textures                    ******/
3291/**********************************************************************/
3292
3293
3294/**
3295 * Error checking for glCompressedTexImage[123]D().
3296 * \return error code or GL_NO_ERROR.
3297 */
3298static GLenum
3299compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3300                               GLenum target, GLint level,
3301                               GLenum internalFormat, GLsizei width,
3302                               GLsizei height, GLsizei depth, GLint border,
3303                               GLsizei imageSize)
3304{
3305   GLint expectedSize, maxLevels = 0, maxTextureSize;
3306
3307   if (dimensions == 1) {
3308      /* 1D compressed textures not allowed */
3309      return GL_INVALID_ENUM;
3310   }
3311   else if (dimensions == 2) {
3312      if (target == GL_PROXY_TEXTURE_2D) {
3313         maxLevels = ctx->Const.MaxTextureLevels;
3314      }
3315      else if (target == GL_TEXTURE_2D) {
3316         maxLevels = ctx->Const.MaxTextureLevels;
3317      }
3318      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3319         if (!ctx->Extensions.ARB_texture_cube_map)
3320            return GL_INVALID_ENUM; /*target*/
3321         maxLevels = ctx->Const.MaxCubeTextureLevels;
3322      }
3323      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3324               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3325         if (!ctx->Extensions.ARB_texture_cube_map)
3326            return GL_INVALID_ENUM; /*target*/
3327         maxLevels = ctx->Const.MaxCubeTextureLevels;
3328      }
3329      else {
3330         return GL_INVALID_ENUM; /*target*/
3331      }
3332   }
3333   else if (dimensions == 3) {
3334      /* 3D compressed textures not allowed */
3335      return GL_INVALID_ENUM;
3336   }
3337
3338   maxTextureSize = 1 << (maxLevels - 1);
3339
3340   /* This will detect any invalid internalFormat value */
3341   if (!is_compressed_format(ctx, internalFormat))
3342      return GL_INVALID_ENUM;
3343
3344   /* This should really never fail */
3345   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3346      return GL_INVALID_ENUM;
3347
3348   if (border != 0)
3349      return GL_INVALID_VALUE;
3350
3351   /*
3352    * XXX We should probably use the proxy texture error check function here.
3353    */
3354   if (width < 1 || width > maxTextureSize ||
3355       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
3356      return GL_INVALID_VALUE;
3357
3358   if ((height < 1 || height > maxTextureSize ||
3359       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
3360       && dimensions > 1)
3361      return GL_INVALID_VALUE;
3362
3363   if ((depth < 1 || depth > maxTextureSize ||
3364       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
3365       && dimensions > 2)
3366      return GL_INVALID_VALUE;
3367
3368   /* For cube map, width must equal height */
3369   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3370       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3371      return GL_INVALID_VALUE;
3372
3373   if (level < 0 || level >= maxLevels)
3374      return GL_INVALID_VALUE;
3375
3376   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3377                                                       depth, internalFormat);
3378   if (expectedSize != imageSize)
3379      return GL_INVALID_VALUE;
3380
3381#if FEATURE_EXT_texture_sRGB
3382   if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3383        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3384        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3385        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3386       && border != 0) {
3387      return GL_INVALID_OPERATION;
3388   }
3389#endif
3390
3391   return GL_NO_ERROR;
3392}
3393
3394
3395/**
3396 * Error checking for glCompressedTexSubImage[123]D().
3397 * \warning  There are some bad assumptions here about the size of compressed
3398 *           texture tiles (multiple of 4) used to test the validity of the
3399 *           offset and size parameters.
3400 * \return error code or GL_NO_ERROR.
3401 */
3402static GLenum
3403compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3404                                  GLenum target, GLint level,
3405                                  GLint xoffset, GLint yoffset, GLint zoffset,
3406                                  GLsizei width, GLsizei height, GLsizei depth,
3407                                  GLenum format, GLsizei imageSize)
3408{
3409   GLint expectedSize, maxLevels = 0, maxTextureSize;
3410   (void) zoffset;
3411
3412   if (dimensions == 1) {
3413      /* 1D compressed textures not allowed */
3414      return GL_INVALID_ENUM;
3415   }
3416   else if (dimensions == 2) {
3417      if (target == GL_PROXY_TEXTURE_2D) {
3418         maxLevels = ctx->Const.MaxTextureLevels;
3419      }
3420      else if (target == GL_TEXTURE_2D) {
3421         maxLevels = ctx->Const.MaxTextureLevels;
3422      }
3423      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3424         if (!ctx->Extensions.ARB_texture_cube_map)
3425            return GL_INVALID_ENUM; /*target*/
3426         maxLevels = ctx->Const.MaxCubeTextureLevels;
3427      }
3428      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3429               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3430         if (!ctx->Extensions.ARB_texture_cube_map)
3431            return GL_INVALID_ENUM; /*target*/
3432         maxLevels = ctx->Const.MaxCubeTextureLevels;
3433      }
3434      else {
3435         return GL_INVALID_ENUM; /*target*/
3436      }
3437   }
3438   else if (dimensions == 3) {
3439      /* 3D compressed textures not allowed */
3440      return GL_INVALID_ENUM;
3441   }
3442
3443   maxTextureSize = 1 << (maxLevels - 1);
3444
3445   /* this will catch any invalid compressed format token */
3446   if (!is_compressed_format(ctx, format))
3447      return GL_INVALID_ENUM;
3448
3449   if (width < 1 || width > maxTextureSize)
3450      return GL_INVALID_VALUE;
3451
3452   if ((height < 1 || height > maxTextureSize)
3453       && dimensions > 1)
3454      return GL_INVALID_VALUE;
3455
3456   if (level < 0 || level >= maxLevels)
3457      return GL_INVALID_VALUE;
3458
3459   /* XXX these tests are specific to the compressed format.
3460    * this code should be generalized in some way.
3461    */
3462   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3463      return GL_INVALID_VALUE;
3464
3465   if ((width & 3) != 0 && width != 2 && width != 1)
3466      return GL_INVALID_VALUE;
3467
3468   if ((height & 3) != 0 && height != 2 && height != 1)
3469      return GL_INVALID_VALUE;
3470
3471   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3472                                                       depth, format);
3473   if (expectedSize != imageSize)
3474      return GL_INVALID_VALUE;
3475
3476   return GL_NO_ERROR;
3477}
3478
3479
3480
3481void GLAPIENTRY
3482_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3483                              GLenum internalFormat, GLsizei width,
3484                              GLint border, GLsizei imageSize,
3485                              const GLvoid *data)
3486{
3487   GET_CURRENT_CONTEXT(ctx);
3488   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3489
3490   if (target == GL_TEXTURE_1D) {
3491      /* non-proxy target */
3492      struct gl_texture_unit *texUnit;
3493      struct gl_texture_object *texObj;
3494      struct gl_texture_image *texImage;
3495      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3496                               internalFormat, width, 1, 1, border, imageSize);
3497      if (error) {
3498         _mesa_error(ctx, error, "glCompressedTexImage1D");
3499         return;
3500      }
3501
3502      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3503      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3504
3505      _mesa_lock_texture(ctx, texObj);
3506      {
3507	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3508	 if (!texImage) {
3509	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3510	    goto out;
3511	 }
3512
3513	 if (texImage->Data) {
3514	    ctx->Driver.FreeTexImageData( ctx, texImage );
3515	 }
3516	 ASSERT(texImage->Data == NULL);
3517
3518	 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3519				    border, internalFormat);
3520
3521	 ASSERT(ctx->Driver.CompressedTexImage1D);
3522	 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
3523					     internalFormat, width, border,
3524					     imageSize, data,
3525					     texObj, texImage);
3526
3527	 /* state update */
3528	 texObj->_Complete = GL_FALSE;
3529	 ctx->NewState |= _NEW_TEXTURE;
3530      }
3531   out:
3532      _mesa_unlock_texture(ctx, texObj);
3533   }
3534   else if (target == GL_PROXY_TEXTURE_1D) {
3535      /* Proxy texture: check for errors and update proxy state */
3536      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3537                               internalFormat, width, 1, 1, border, imageSize);
3538      if (!error) {
3539         ASSERT(ctx->Driver.TestProxyTexImage);
3540         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3541                                             internalFormat, GL_NONE, GL_NONE,
3542                                             width, 1, 1, border);
3543      }
3544      if (error) {
3545         /* if error, clear all proxy texture image parameters */
3546         struct gl_texture_image *texImage;
3547         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3548         if (texImage)
3549            clear_teximage_fields(texImage);
3550      }
3551      else {
3552         /* store the teximage parameters */
3553         struct gl_texture_unit *texUnit;
3554         struct gl_texture_object *texObj;
3555         struct gl_texture_image *texImage;
3556         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3557	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3558
3559	 _mesa_lock_texture(ctx, texObj);
3560	 {
3561	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3562	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3563				       border, internalFormat);
3564	 }
3565	 _mesa_unlock_texture(ctx, texObj);
3566      }
3567   }
3568   else {
3569      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3570      return;
3571   }
3572}
3573
3574
3575void GLAPIENTRY
3576_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3577                              GLenum internalFormat, GLsizei width,
3578                              GLsizei height, GLint border, GLsizei imageSize,
3579                              const GLvoid *data)
3580{
3581   GET_CURRENT_CONTEXT(ctx);
3582   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3583
3584   if (target == GL_TEXTURE_2D ||
3585       (ctx->Extensions.ARB_texture_cube_map &&
3586        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3587        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3588      /* non-proxy target */
3589      struct gl_texture_unit *texUnit;
3590      struct gl_texture_object *texObj;
3591      struct gl_texture_image *texImage;
3592      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3593                          internalFormat, width, height, 1, border, imageSize);
3594      if (error) {
3595         _mesa_error(ctx, error, "glCompressedTexImage2D");
3596         return;
3597      }
3598
3599      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3600      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3601
3602      _mesa_lock_texture(ctx, texObj);
3603      {
3604	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3605	 if (!texImage) {
3606	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3607	    goto out;
3608	 }
3609
3610	 if (texImage->Data) {
3611	    ctx->Driver.FreeTexImageData( ctx, texImage );
3612	 }
3613	 ASSERT(texImage->Data == NULL);
3614
3615	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3616				    border, internalFormat);
3617
3618	 ASSERT(ctx->Driver.CompressedTexImage2D);
3619	 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
3620					     internalFormat, width, height,
3621					     border, imageSize, data,
3622					     texObj, texImage);
3623
3624	 /* state update */
3625	 texObj->_Complete = GL_FALSE;
3626	 ctx->NewState |= _NEW_TEXTURE;
3627      }
3628   out:
3629      _mesa_unlock_texture(ctx, texObj);
3630   }
3631   else if (target == GL_PROXY_TEXTURE_2D ||
3632            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3633             ctx->Extensions.ARB_texture_cube_map)) {
3634      /* Proxy texture: check for errors and update proxy state */
3635      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3636                          internalFormat, width, height, 1, border, imageSize);
3637      if (!error) {
3638         ASSERT(ctx->Driver.TestProxyTexImage);
3639         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3640                                              internalFormat, GL_NONE, GL_NONE,
3641                                              width, height, 1, border);
3642      }
3643      if (error) {
3644         /* if error, clear all proxy texture image parameters */
3645         struct gl_texture_image *texImage;
3646         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3647         if (texImage)
3648            clear_teximage_fields(texImage);
3649      }
3650      else {
3651         /* store the teximage parameters */
3652         struct gl_texture_unit *texUnit;
3653         struct gl_texture_object *texObj;
3654         struct gl_texture_image *texImage;
3655         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3656	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3657
3658	 _mesa_lock_texture(ctx, texObj);
3659	 {
3660	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3661	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3662				       border, internalFormat);
3663	 }
3664	 _mesa_unlock_texture(ctx, texObj);
3665      }
3666   }
3667   else {
3668      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3669      return;
3670   }
3671}
3672
3673
3674void GLAPIENTRY
3675_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3676                              GLenum internalFormat, GLsizei width,
3677                              GLsizei height, GLsizei depth, GLint border,
3678                              GLsizei imageSize, const GLvoid *data)
3679{
3680   GET_CURRENT_CONTEXT(ctx);
3681   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3682
3683   if (target == GL_TEXTURE_3D) {
3684      /* non-proxy target */
3685      struct gl_texture_unit *texUnit;
3686      struct gl_texture_object *texObj;
3687      struct gl_texture_image *texImage;
3688      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3689                      internalFormat, width, height, depth, border, imageSize);
3690      if (error) {
3691         _mesa_error(ctx, error, "glCompressedTexImage3D");
3692         return;
3693      }
3694
3695      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3696      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3697      _mesa_lock_texture(ctx, texObj);
3698      {
3699	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3700	 if (!texImage) {
3701	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3702	    goto out;
3703	 }
3704
3705	 if (texImage->Data) {
3706	    ctx->Driver.FreeTexImageData( ctx, texImage );
3707	 }
3708	 ASSERT(texImage->Data == NULL);
3709
3710	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
3711				    border, internalFormat);
3712
3713	 ASSERT(ctx->Driver.CompressedTexImage3D);
3714	 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3715					     internalFormat,
3716					     width, height, depth,
3717					     border, imageSize, data,
3718					     texObj, texImage);
3719
3720	 /* state update */
3721	 texObj->_Complete = GL_FALSE;
3722	 ctx->NewState |= _NEW_TEXTURE;
3723      }
3724   out:
3725      _mesa_unlock_texture(ctx, texObj);
3726   }
3727   else if (target == GL_PROXY_TEXTURE_3D) {
3728      /* Proxy texture: check for errors and update proxy state */
3729      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3730                      internalFormat, width, height, depth, border, imageSize);
3731      if (!error) {
3732         ASSERT(ctx->Driver.TestProxyTexImage);
3733         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3734                                             internalFormat, GL_NONE, GL_NONE,
3735                                             width, height, depth, border);
3736      }
3737      if (error) {
3738         /* if error, clear all proxy texture image parameters */
3739         struct gl_texture_image *texImage;
3740         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3741         if (texImage)
3742            clear_teximage_fields(texImage);
3743      }
3744      else {
3745         /* store the teximage parameters */
3746         struct gl_texture_unit *texUnit;
3747         struct gl_texture_object *texObj;
3748         struct gl_texture_image *texImage;
3749         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3750	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3751	 _mesa_lock_texture(ctx, texObj);
3752	 {
3753	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3754	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3755				       depth, border, internalFormat);
3756	 }
3757	 _mesa_unlock_texture(ctx, texObj);
3758      }
3759   }
3760   else {
3761      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3762      return;
3763   }
3764}
3765
3766
3767void GLAPIENTRY
3768_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3769                                 GLsizei width, GLenum format,
3770                                 GLsizei imageSize, const GLvoid *data)
3771{
3772   struct gl_texture_unit *texUnit;
3773   struct gl_texture_object *texObj;
3774   struct gl_texture_image *texImage;
3775   GLenum error;
3776   GET_CURRENT_CONTEXT(ctx);
3777   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3778
3779   error = compressed_subtexture_error_check(ctx, 1, target, level,
3780                                             xoffset, 0, 0, /* pos */
3781                                             width, 1, 1,   /* size */
3782                                             format, imageSize);
3783   if (error) {
3784      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3785      return;
3786   }
3787
3788   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3789   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3790   _mesa_lock_texture(ctx, texObj);
3791   {
3792      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3793      assert(texImage);
3794
3795      if ((GLint) format != texImage->InternalFormat) {
3796	 _mesa_error(ctx, GL_INVALID_OPERATION,
3797		     "glCompressedTexSubImage1D(format)");
3798	 goto out;
3799      }
3800
3801      if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
3802	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
3803	 goto out;
3804      }
3805
3806      if (width == 0)
3807	 goto out;  /* no-op, not an error */
3808
3809      if (ctx->Driver.CompressedTexSubImage1D) {
3810	 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3811						xoffset, width,
3812						format, imageSize, data,
3813						texObj, texImage);
3814      }
3815      ctx->NewState |= _NEW_TEXTURE;
3816   }
3817 out:
3818   _mesa_unlock_texture(ctx, texObj);
3819}
3820
3821
3822void GLAPIENTRY
3823_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3824                                 GLint yoffset, GLsizei width, GLsizei height,
3825                                 GLenum format, GLsizei imageSize,
3826                                 const GLvoid *data)
3827{
3828   struct gl_texture_unit *texUnit;
3829   struct gl_texture_object *texObj;
3830   struct gl_texture_image *texImage;
3831   GLenum error;
3832   GET_CURRENT_CONTEXT(ctx);
3833   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3834
3835   error = compressed_subtexture_error_check(ctx, 2, target, level,
3836                                             xoffset, yoffset, 0, /* pos */
3837                                             width, height, 1,    /* size */
3838                                             format, imageSize);
3839   if (error) {
3840      /* XXX proxy target? */
3841      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3842      return;
3843   }
3844
3845   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3846   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3847   _mesa_lock_texture(ctx, texObj);
3848   {
3849      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3850      assert(texImage);
3851
3852      if ((GLint) format != texImage->InternalFormat) {
3853	 _mesa_error(ctx, GL_INVALID_OPERATION,
3854		     "glCompressedTexSubImage2D(format)");
3855	 goto out;
3856      }
3857
3858      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3859	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
3860	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3861	 goto out;
3862      }
3863
3864      if (width == 0 || height == 0)
3865	 goto out;  /* no-op, not an error */
3866
3867      if (ctx->Driver.CompressedTexSubImage2D) {
3868	 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3869						xoffset, yoffset, width, height,
3870						format, imageSize, data,
3871						texObj, texImage);
3872      }
3873      ctx->NewState |= _NEW_TEXTURE;
3874   }
3875 out:
3876   _mesa_unlock_texture(ctx, texObj);
3877}
3878
3879
3880void GLAPIENTRY
3881_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3882                                 GLint yoffset, GLint zoffset, GLsizei width,
3883                                 GLsizei height, GLsizei depth, GLenum format,
3884                                 GLsizei imageSize, const GLvoid *data)
3885{
3886   struct gl_texture_unit *texUnit;
3887   struct gl_texture_object *texObj;
3888   struct gl_texture_image *texImage;
3889   GLenum error;
3890   GET_CURRENT_CONTEXT(ctx);
3891   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3892
3893   error = compressed_subtexture_error_check(ctx, 3, target, level,
3894                                             xoffset, yoffset, zoffset,/*pos*/
3895                                             width, height, depth, /*size*/
3896                                             format, imageSize);
3897   if (error) {
3898      _mesa_error(ctx, error, "glCompressedTexSubImage3D");
3899      return;
3900   }
3901
3902   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3903   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3904   _mesa_lock_texture(ctx, texObj);
3905   {
3906      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3907      assert(texImage);
3908
3909      if ((GLint) format != texImage->InternalFormat) {
3910	 _mesa_error(ctx, GL_INVALID_OPERATION,
3911		     "glCompressedTexSubImage3D(format)");
3912	 goto out;
3913      }
3914
3915      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3916	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
3917	  ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
3918	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3919	 goto out;
3920      }
3921
3922      if (width == 0 || height == 0 || depth == 0)
3923	 goto out;  /* no-op, not an error */
3924
3925      if (ctx->Driver.CompressedTexSubImage3D) {
3926	 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3927						xoffset, yoffset, zoffset,
3928						width, height, depth,
3929						format, imageSize, data,
3930						texObj, texImage);
3931      }
3932      ctx->NewState |= _NEW_TEXTURE;
3933   }
3934 out:
3935   _mesa_unlock_texture(ctx, texObj);
3936}
3937
3938
3939void GLAPIENTRY
3940_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3941{
3942   const struct gl_texture_unit *texUnit;
3943   struct gl_texture_object *texObj;
3944   struct gl_texture_image *texImage;
3945   GLint maxLevels;
3946   GET_CURRENT_CONTEXT(ctx);
3947   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3948
3949   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3950   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3951   if (!texObj) {
3952      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
3953      return;
3954   }
3955
3956   maxLevels = _mesa_max_texture_levels(ctx, target);
3957   ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
3958
3959   if (level < 0 || level >= maxLevels) {
3960      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3961      return;
3962   }
3963
3964   if (_mesa_is_proxy_texture(target)) {
3965      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3966      return;
3967   }
3968
3969   _mesa_lock_texture(ctx, texObj);
3970   {
3971      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3972      if (texImage) {
3973         if (texImage->IsCompressed) {
3974            /* this typically calls _mesa_get_compressed_teximage() */
3975            ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
3976                                              texObj, texImage);
3977         }
3978         else {
3979            _mesa_error(ctx, GL_INVALID_OPERATION,
3980                        "glGetCompressedTexImageARB");
3981         }
3982      }
3983      else {
3984         /* probably invalid mipmap level */
3985         _mesa_error(ctx, GL_INVALID_VALUE,
3986                     "glGetCompressedTexImageARB(level)");
3987      }
3988   }
3989   _mesa_unlock_texture(ctx, texObj);
3990}
3991