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