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