teximage.c revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.0.3
4 *
5 * Copyright (C) 1999-2008  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_UNSIGNED_BYTE
77   _mesa_problem(NULL, "PrintTexture not supported");
78#else
79   GLuint i, j, c;
80   const GLubyte *data = (const GLubyte *) 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 * Note that width, height, depth == 0 is not an error.  However, a
1211 * texture with zero width/height/depth will be considered "incomplete"
1212 * and texturing will effectively be disabled.
1213 *
1214 * \param target  one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1215 *                GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1216 *                GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1217 * \param level  as passed to glTexImage
1218 * \param internalFormat  as passed to glTexImage
1219 * \param format  as passed to glTexImage
1220 * \param type  as passed to glTexImage
1221 * \param width  as passed to glTexImage
1222 * \param height  as passed to glTexImage
1223 * \param depth  as passed to glTexImage
1224 * \param border  as passed to glTexImage
1225 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1226 */
1227GLboolean
1228_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1229                          GLint internalFormat, GLenum format, GLenum type,
1230                          GLint width, GLint height, GLint depth, GLint border)
1231{
1232   GLint maxSize;
1233
1234   (void) internalFormat;
1235   (void) format;
1236   (void) type;
1237
1238   switch (target) {
1239   case GL_PROXY_TEXTURE_1D:
1240      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1241      if (width < 2 * border || width > 2 + maxSize ||
1242          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1243           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
1244          level >= ctx->Const.MaxTextureLevels) {
1245         /* bad width or level */
1246         return GL_FALSE;
1247      }
1248      return GL_TRUE;
1249   case GL_PROXY_TEXTURE_2D:
1250      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1251      if (width < 2 * border || width > 2 + maxSize ||
1252          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1253           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
1254          height < 2 * border || height > 2 + maxSize ||
1255          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1256           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
1257          level >= ctx->Const.MaxTextureLevels) {
1258         /* bad width or height or level */
1259         return GL_FALSE;
1260      }
1261      return GL_TRUE;
1262   case GL_PROXY_TEXTURE_3D:
1263      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1264      if (width < 2 * border || width > 2 + maxSize ||
1265          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1266           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
1267          height < 2 * border || height > 2 + maxSize ||
1268          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1269           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
1270          depth < 2 * border || depth > 2 + maxSize ||
1271          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1272           depth > 0 && _mesa_bitcount(depth - 2 * border) != 1) ||
1273          level >= ctx->Const.Max3DTextureLevels) {
1274         /* bad width or height or depth or level */
1275         return GL_FALSE;
1276      }
1277      return GL_TRUE;
1278   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1279      if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
1280          height < 0 || height > ctx->Const.MaxTextureRectSize ||
1281          level != 0) {
1282         /* bad width or height or level */
1283         return GL_FALSE;
1284      }
1285      return GL_TRUE;
1286   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1287      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1288      if (width < 2 * border || width > 2 + maxSize ||
1289          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1290           width > 0 && _mesa_bitcount(width - 2 * border) != 1) ||
1291          height < 2 * border || height > 2 + maxSize ||
1292          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1293           height > 0 && _mesa_bitcount(height - 2 * border) != 1) ||
1294          level >= ctx->Const.MaxCubeTextureLevels) {
1295         /* bad width or height */
1296         return GL_FALSE;
1297      }
1298      return GL_TRUE;
1299   default:
1300      _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1301      return GL_FALSE;
1302   }
1303}
1304
1305
1306/**
1307 * Helper function to determine whether a target supports compressed textures
1308 */
1309static GLboolean
1310target_can_be_compressed(GLcontext *ctx, GLenum target)
1311{
1312   return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
1313           || ((ctx->Extensions.ARB_texture_cube_map &&
1314                (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1315                 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1316                  target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)))));
1317}
1318
1319
1320/**
1321 * Test the glTexImage[123]D() parameters for errors.
1322 *
1323 * \param ctx GL context.
1324 * \param target texture target given by the user.
1325 * \param level image level given by the user.
1326 * \param internalFormat internal format given by the user.
1327 * \param format pixel data format given by the user.
1328 * \param type pixel data type given by the user.
1329 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1330 * \param width image width given by the user.
1331 * \param height image height given by the user.
1332 * \param depth image depth given by the user.
1333 * \param border image border given by the user.
1334 *
1335 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1336 *
1337 * Verifies each of the parameters against the constants specified in
1338 * __GLcontextRec::Const and the supported extensions, and according to the
1339 * OpenGL specification.
1340 */
1341static GLboolean
1342texture_error_check( GLcontext *ctx, GLenum target,
1343                     GLint level, GLint internalFormat,
1344                     GLenum format, GLenum type,
1345                     GLuint dimensions,
1346                     GLint width, GLint height,
1347                     GLint depth, GLint border )
1348{
1349   const GLboolean isProxy = _mesa_is_proxy_texture(target);
1350   GLboolean sizeOK = GL_TRUE;
1351   GLboolean colorFormat, indexFormat;
1352   GLenum proxy_target;
1353
1354   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1355   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1356      if (!isProxy) {
1357         _mesa_error(ctx, GL_INVALID_VALUE,
1358                     "glTexImage%dD(level=%d)", dimensions, level);
1359      }
1360      return GL_TRUE;
1361   }
1362
1363   /* Check border */
1364   if (border < 0 || border > 1 ||
1365       ((target == GL_TEXTURE_RECTANGLE_NV ||
1366         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1367      if (!isProxy) {
1368         _mesa_error(ctx, GL_INVALID_VALUE,
1369                     "glTexImage%dD(border=%d)", dimensions, border);
1370      }
1371      return GL_TRUE;
1372   }
1373
1374   if (width < 0 || height < 0 || depth < 0) {
1375      if (!isProxy) {
1376         _mesa_error(ctx, GL_INVALID_VALUE,
1377                     "glTexImage%dD(width, height or depth < 0)", dimensions);
1378      }
1379      return GL_TRUE;
1380   }
1381
1382   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1383    * level, width, height and depth.
1384    */
1385   if (dimensions == 1) {
1386      if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1387         proxy_target = GL_PROXY_TEXTURE_1D;
1388         height = 1;
1389         depth = 1;
1390      }
1391      else {
1392         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1393         return GL_TRUE;
1394      }
1395   }
1396   else if (dimensions == 2) {
1397      depth = 1;
1398      if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1399         proxy_target = GL_PROXY_TEXTURE_2D;
1400      }
1401      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1402               (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1403                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1404         if (!ctx->Extensions.ARB_texture_cube_map) {
1405            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1406            return GL_TRUE;
1407         }
1408         proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
1409         sizeOK = (width == height);
1410      }
1411      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1412               target == GL_TEXTURE_RECTANGLE_NV) {
1413         if (!ctx->Extensions.NV_texture_rectangle) {
1414            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1415            return GL_TRUE;
1416         }
1417         proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
1418      }
1419      else {
1420         _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1421         return GL_TRUE;
1422      }
1423   }
1424   else if (dimensions == 3) {
1425      if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1426         proxy_target = GL_PROXY_TEXTURE_3D;
1427      }
1428      else {
1429         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1430         return GL_TRUE;
1431      }
1432   }
1433   else {
1434      _mesa_problem( ctx, "bad dims in texture_error_check" );
1435      return GL_TRUE;
1436   }
1437
1438   sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
1439                                                    internalFormat, format,
1440                                                    type, width, height,
1441                                                    depth, border);
1442   if (!sizeOK) {
1443      if (!isProxy) {
1444         _mesa_error(ctx, GL_INVALID_VALUE,
1445                     "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1446                     dimensions, level, width, height, depth);
1447      }
1448      return GL_TRUE;
1449   }
1450
1451   /* Check internalFormat */
1452   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1453      if (!isProxy) {
1454         _mesa_error(ctx, GL_INVALID_VALUE,
1455                     "glTexImage%dD(internalFormat=0x%x)",
1456                     dimensions, internalFormat);
1457      }
1458      return GL_TRUE;
1459   }
1460
1461   /* Check incoming image format and type */
1462   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1463      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1464       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
1465       */
1466      if (!isProxy) {
1467         _mesa_error(ctx, GL_INVALID_OPERATION,
1468                     "glTexImage%dD(format or type)", dimensions);
1469      }
1470      return GL_TRUE;
1471   }
1472
1473   /* make sure internal format and format basically agree */
1474   colorFormat = is_color_format(format);
1475   indexFormat = is_index_format(format);
1476   if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1477       (is_index_format(internalFormat) && !indexFormat) ||
1478       (is_depth_format(internalFormat) != is_depth_format(format)) ||
1479       (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
1480       (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
1481      if (!isProxy)
1482         _mesa_error(ctx, GL_INVALID_OPERATION,
1483                     "glTexImage(internalFormat/format)");
1484      return GL_TRUE;
1485   }
1486
1487   /* additional checks for ycbcr textures */
1488   if (internalFormat == GL_YCBCR_MESA) {
1489      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1490      if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1491          type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1492         char message[100];
1493         _mesa_sprintf(message,
1494                 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1495         _mesa_error(ctx, GL_INVALID_ENUM, message);
1496         return GL_TRUE; /* error */
1497      }
1498      if (target != GL_TEXTURE_2D &&
1499          target != GL_PROXY_TEXTURE_2D &&
1500          target != GL_TEXTURE_RECTANGLE_NV &&
1501          target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1502         if (!isProxy)
1503            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1504         return GL_TRUE;
1505      }
1506      if (border != 0) {
1507         if (!isProxy) {
1508            char message[100];
1509            _mesa_sprintf(message,
1510                    "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1511                    dimensions, border);
1512            _mesa_error(ctx, GL_INVALID_VALUE, message);
1513         }
1514         return GL_TRUE;
1515      }
1516   }
1517
1518   /* additional checks for depth textures */
1519   if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1520      /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1521      if (target != GL_TEXTURE_1D &&
1522          target != GL_PROXY_TEXTURE_1D &&
1523          target != GL_TEXTURE_2D &&
1524          target != GL_PROXY_TEXTURE_2D &&
1525          target != GL_TEXTURE_RECTANGLE_ARB &&
1526          target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
1527         if (!isProxy)
1528            _mesa_error(ctx, GL_INVALID_ENUM,
1529                        "glTexImage(target/internalFormat)");
1530         return GL_TRUE;
1531      }
1532   }
1533
1534   /* additional checks for compressed textures */
1535   if (is_compressed_format(ctx, internalFormat)) {
1536      if (!target_can_be_compressed(ctx, target) && !isProxy) {
1537         _mesa_error(ctx, GL_INVALID_ENUM,
1538                     "glTexImage%d(target)", dimensions);
1539         return GL_TRUE;
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_can_be_compressed(ctx, target)) {
1715         _mesa_error(ctx, GL_INVALID_ENUM,
1716                     "glTexSubImage%D(target)", dimensions);
1717         return GL_TRUE;
1718      }
1719      /* offset must be multiple of 4 */
1720      if ((xoffset & 3) || (yoffset & 3)) {
1721         _mesa_error(ctx, GL_INVALID_OPERATION,
1722                     "glTexSubImage%D(xoffset or yoffset)", dimensions);
1723         return GL_TRUE;
1724      }
1725      /* size must be multiple of 4 or equal to whole texture size */
1726      if ((width & 3) && (GLuint) width != destTex->Width) {
1727         _mesa_error(ctx, GL_INVALID_OPERATION,
1728                     "glTexSubImage%D(width)", dimensions);
1729         return GL_TRUE;
1730      }
1731      if ((height & 3) && (GLuint) height != destTex->Height) {
1732         _mesa_error(ctx, GL_INVALID_OPERATION,
1733                     "glTexSubImage%D(width)", dimensions);
1734         return GL_TRUE;
1735      }
1736   }
1737
1738   return GL_FALSE;
1739}
1740
1741
1742/**
1743 * Test glCopyTexImage[12]D() parameters for errors.
1744 *
1745 * \param ctx GL context.
1746 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1747 * \param target texture target given by the user.
1748 * \param level image level given by the user.
1749 * \param internalFormat internal format given by the user.
1750 * \param width image width given by the user.
1751 * \param height image height given by the user.
1752 * \param depth image depth given by the user.
1753 * \param border texture border.
1754 *
1755 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1756 *
1757 * Verifies each of the parameters against the constants specified in
1758 * __GLcontextRec::Const and the supported extensions, and according to the
1759 * OpenGL specification.
1760 */
1761static GLboolean
1762copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1763                         GLenum target, GLint level, GLint internalFormat,
1764                         GLint width, GLint height, GLint border )
1765{
1766   GLenum type;
1767   GLboolean sizeOK;
1768   GLint format;
1769
1770   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1771   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1772      _mesa_error(ctx, GL_INVALID_VALUE,
1773                  "glCopyTexImage%dD(level=%d)", dimensions, level);
1774      return GL_TRUE;
1775   }
1776
1777   /* Check that the source buffer is complete */
1778   if (ctx->ReadBuffer->Name) {
1779      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1780      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1781         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1782                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1783         return GL_TRUE;
1784      }
1785   }
1786
1787   /* Check border */
1788   if (border < 0 || border > 1 ||
1789       ((target == GL_TEXTURE_RECTANGLE_NV ||
1790         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1791      return GL_TRUE;
1792   }
1793
1794   format = _mesa_base_tex_format(ctx, internalFormat);
1795   if (format < 0) {
1796      _mesa_error(ctx, GL_INVALID_VALUE,
1797                  "glCopyTexImage%dD(internalFormat)", dimensions);
1798      return GL_TRUE;
1799   }
1800
1801   /* NOTE: the format and type aren't really significant for
1802    * TestProxyTexImage().  Only the internalformat really matters.
1803   if (!_mesa_source_buffer_exists(ctx, format)) {
1804      _mesa_error(ctx, GL_INVALID_OPERATION,
1805                  "glCopyTexImage%dD(missing readbuffer)", dimensions);
1806      return GL_TRUE;
1807   }
1808
1809    */
1810   type = GL_FLOAT;
1811
1812   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1813    * level, width, height and depth.
1814    */
1815   if (dimensions == 1) {
1816      if (target == GL_TEXTURE_1D) {
1817         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1818                                                level, internalFormat,
1819                                                format, type,
1820                                                width, 1, 1, border);
1821      }
1822      else {
1823         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1824         return GL_TRUE;
1825      }
1826   }
1827   else if (dimensions == 2) {
1828      if (target == GL_TEXTURE_2D) {
1829         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1830                                                level, internalFormat,
1831                                                format, type,
1832                                                width, height, 1, border);
1833      }
1834      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1835               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1836         if (!ctx->Extensions.ARB_texture_cube_map) {
1837            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1838            return GL_TRUE;
1839         }
1840         sizeOK = (width == height) &&
1841            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1842                                          level, internalFormat, format, type,
1843                                          width, height, 1, border);
1844      }
1845      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1846         if (!ctx->Extensions.NV_texture_rectangle) {
1847            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1848            return GL_TRUE;
1849         }
1850         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1851                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
1852                                                level, internalFormat,
1853                                                format, type,
1854                                                width, height, 1, border);
1855      }
1856      else {
1857         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1858         return GL_TRUE;
1859      }
1860   }
1861   else {
1862      _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1863      return GL_TRUE;
1864   }
1865
1866   if (!sizeOK) {
1867      if (dimensions == 1) {
1868         _mesa_error(ctx, GL_INVALID_VALUE,
1869                     "glCopyTexImage1D(width=%d)", width);
1870      }
1871      else {
1872         ASSERT(dimensions == 2);
1873         _mesa_error(ctx, GL_INVALID_VALUE,
1874                     "glCopyTexImage2D(width=%d, height=%d)", width, height);
1875      }
1876      return GL_TRUE;
1877   }
1878
1879   if (is_compressed_format(ctx, internalFormat)) {
1880      if (target != GL_TEXTURE_2D) {
1881         _mesa_error(ctx, GL_INVALID_ENUM,
1882                     "glCopyTexImage%d(target)", dimensions);
1883         return GL_TRUE;
1884      }
1885      if (border != 0) {
1886         _mesa_error(ctx, GL_INVALID_OPERATION,
1887                     "glCopyTexImage%D(border!=0)", dimensions);
1888         return GL_TRUE;
1889      }
1890   }
1891   else if (is_depth_format(internalFormat)) {
1892      /* make sure we have depth/stencil buffers */
1893      if (!ctx->ReadBuffer->_DepthBuffer) {
1894         _mesa_error(ctx, GL_INVALID_OPERATION,
1895                     "glCopyTexImage%D(no depth)", dimensions);
1896         return GL_TRUE;
1897      }
1898   }
1899   else if (is_depthstencil_format(internalFormat)) {
1900      /* make sure we have depth/stencil buffers */
1901      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1902         _mesa_error(ctx, GL_INVALID_OPERATION,
1903                     "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
1904         return GL_TRUE;
1905      }
1906   }
1907
1908   /* if we get here, the parameters are OK */
1909   return GL_FALSE;
1910}
1911
1912
1913/**
1914 * Test glCopyTexSubImage[12]D() parameters for errors.
1915 *
1916 * \param ctx GL context.
1917 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1918 * \param target texture target given by the user.
1919 * \param level image level given by the user.
1920 * \param xoffset sub-image x offset given by the user.
1921 * \param yoffset sub-image y offset given by the user.
1922 * \param zoffset sub-image z offset given by the user.
1923 * \param width image width given by the user.
1924 * \param height image height given by the user.
1925 *
1926 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1927 *
1928 * Verifies each of the parameters against the constants specified in
1929 * __GLcontextRec::Const and the supported extensions, and according to the
1930 * OpenGL specification.
1931 */
1932static GLboolean
1933copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1934                             GLenum target, GLint level,
1935                             GLint xoffset, GLint yoffset, GLint zoffset,
1936                             GLsizei width, GLsizei height)
1937{
1938   /* Check target */
1939   /* Check that the source buffer is complete */
1940   if (ctx->ReadBuffer->Name) {
1941      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1942      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1943         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1944                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1945         return GL_TRUE;
1946      }
1947   }
1948
1949   if (dimensions == 1) {
1950      if (target != GL_TEXTURE_1D) {
1951         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1952         return GL_TRUE;
1953      }
1954   }
1955   else if (dimensions == 2) {
1956      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1957          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1958         if (!ctx->Extensions.ARB_texture_cube_map) {
1959            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1960            return GL_TRUE;
1961         }
1962      }
1963      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1964         if (!ctx->Extensions.NV_texture_rectangle) {
1965            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1966            return GL_TRUE;
1967         }
1968      }
1969      else if (target != GL_TEXTURE_2D) {
1970         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1971         return GL_TRUE;
1972      }
1973   }
1974   else if (dimensions == 3) {
1975      if (target != GL_TEXTURE_3D) {
1976         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1977         return GL_TRUE;
1978      }
1979   }
1980
1981   /* Check level */
1982   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1983      _mesa_error(ctx, GL_INVALID_VALUE,
1984                  "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1985      return GL_TRUE;
1986   }
1987
1988   /* Check size */
1989   if (width < 0) {
1990      _mesa_error(ctx, GL_INVALID_VALUE,
1991                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1992      return GL_TRUE;
1993   }
1994   if (dimensions > 1 && height < 0) {
1995      _mesa_error(ctx, GL_INVALID_VALUE,
1996                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1997      return GL_TRUE;
1998   }
1999
2000   return GL_FALSE;
2001}
2002
2003static GLboolean
2004copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
2005			      GLenum target, GLint level,
2006			      GLint xoffset, GLint yoffset, GLint zoffset,
2007			      GLsizei width, GLsizei height,
2008			      const struct gl_texture_image *teximage )
2009{
2010   if (!teximage) {
2011      _mesa_error(ctx, GL_INVALID_OPERATION,
2012                  "glCopyTexSubImage%dD(undefined texture level: %d)",
2013                  dimensions, level);
2014      return GL_TRUE;
2015   }
2016
2017   if (xoffset < -((GLint)teximage->Border)) {
2018      _mesa_error(ctx, GL_INVALID_VALUE,
2019                  "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
2020      return GL_TRUE;
2021   }
2022   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
2023      _mesa_error(ctx, GL_INVALID_VALUE,
2024                  "glCopyTexSubImage%dD(xoffset+width)", dimensions);
2025      return GL_TRUE;
2026   }
2027   if (dimensions > 1) {
2028      if (yoffset < -((GLint)teximage->Border)) {
2029         _mesa_error(ctx, GL_INVALID_VALUE,
2030                     "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
2031         return GL_TRUE;
2032      }
2033      /* NOTE: we're adding the border here, not subtracting! */
2034      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
2035         _mesa_error(ctx, GL_INVALID_VALUE,
2036                     "glCopyTexSubImage%dD(yoffset+height)", dimensions);
2037         return GL_TRUE;
2038      }
2039   }
2040
2041   if (dimensions > 2) {
2042      if (zoffset < -((GLint)teximage->Border)) {
2043         _mesa_error(ctx, GL_INVALID_VALUE,
2044                     "glCopyTexSubImage%dD(zoffset)", dimensions);
2045         return GL_TRUE;
2046      }
2047      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
2048         _mesa_error(ctx, GL_INVALID_VALUE,
2049                     "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
2050         return GL_TRUE;
2051      }
2052   }
2053
2054   if (teximage->IsCompressed) {
2055      if (target != GL_TEXTURE_2D) {
2056         _mesa_error(ctx, GL_INVALID_ENUM,
2057                     "glCopyTexSubImage%d(target)", dimensions);
2058         return GL_TRUE;
2059      }
2060      /* offset must be multiple of 4 */
2061      if ((xoffset & 3) || (yoffset & 3)) {
2062         _mesa_error(ctx, GL_INVALID_VALUE,
2063                     "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
2064         return GL_TRUE;
2065      }
2066      /* size must be multiple of 4 */
2067      if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
2068         _mesa_error(ctx, GL_INVALID_VALUE,
2069                     "glCopyTexSubImage%D(width)", dimensions);
2070         return GL_TRUE;
2071      }
2072      if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
2073         _mesa_error(ctx, GL_INVALID_VALUE,
2074                     "glCopyTexSubImage%D(height)", dimensions);
2075         return GL_TRUE;
2076      }
2077   }
2078
2079   if (teximage->InternalFormat == GL_YCBCR_MESA) {
2080      _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
2081      return GL_TRUE;
2082   }
2083
2084   if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
2085      _mesa_error(ctx, GL_INVALID_OPERATION,
2086               "glCopyTexSubImage%dD(missing readbuffer)", dimensions);
2087      return GL_TRUE;
2088   }
2089
2090   if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
2091      if (!ctx->ReadBuffer->_DepthBuffer) {
2092         _mesa_error(ctx, GL_INVALID_OPERATION,
2093                     "glCopyTexSubImage%D(no depth buffer)",
2094                     dimensions);
2095         return GL_TRUE;
2096      }
2097   }
2098   else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
2099      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
2100         _mesa_error(ctx, GL_INVALID_OPERATION,
2101                     "glCopyTexSubImage%D(no depth/stencil buffer)",
2102                     dimensions);
2103         return GL_TRUE;
2104      }
2105   }
2106
2107   /* if we get here, the parameters are OK */
2108   return GL_FALSE;
2109}
2110
2111
2112/**
2113 * Get texture image.  Called by glGetTexImage.
2114 *
2115 * \param target texture target.
2116 * \param level image level.
2117 * \param format pixel data format for returned image.
2118 * \param type pixel data type for returned image.
2119 * \param pixels returned pixel data.
2120 */
2121void GLAPIENTRY
2122_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2123                   GLenum type, GLvoid *pixels )
2124{
2125   const struct gl_texture_unit *texUnit;
2126   struct gl_texture_object *texObj;
2127   struct gl_texture_image *texImage;
2128   GLint maxLevels = 0;
2129   GET_CURRENT_CONTEXT(ctx);
2130   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2131
2132   texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2133   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2134   if (!texObj || _mesa_is_proxy_texture(target)) {
2135      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2136      return;
2137   }
2138
2139   maxLevels = _mesa_max_texture_levels(ctx, target);
2140   ASSERT(maxLevels > 0);  /* 0 indicates bad target, caught above */
2141
2142   if (level < 0 || level >= maxLevels) {
2143      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2144      return;
2145   }
2146
2147   if (_mesa_sizeof_packed_type(type) <= 0) {
2148      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2149      return;
2150   }
2151
2152   if (_mesa_components_in_format(format) <= 0 ||
2153       format == GL_STENCIL_INDEX) {
2154      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2155      return;
2156   }
2157
2158   if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
2159      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2160      return;
2161   }
2162
2163   if (!ctx->Extensions.SGIX_depth_texture &&
2164       !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
2165      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2166      return;
2167   }
2168
2169   if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
2170      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2171      return;
2172   }
2173
2174   if (!ctx->Extensions.EXT_packed_depth_stencil
2175       && is_depthstencil_format(format)) {
2176      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2177      return;
2178   }
2179
2180   _mesa_lock_texture(ctx, texObj);
2181   {
2182      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2183      if (!texImage) {
2184	 /* invalid mipmap level, not an error */
2185	 goto out;
2186      }
2187
2188
2189      /* Make sure the requested image format is compatible with the
2190       * texture's format.  Note that a color index texture can be converted
2191       * to RGBA so that combo is allowed.
2192       */
2193      if (is_color_format(format)
2194	  && !is_color_format(texImage->TexFormat->BaseFormat)
2195	  && !is_index_format(texImage->TexFormat->BaseFormat)) {
2196	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2197	 goto out;
2198      }
2199      else if (is_index_format(format)
2200	       && !is_index_format(texImage->TexFormat->BaseFormat)) {
2201	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2202	 goto out;
2203      }
2204      else if (is_depth_format(format)
2205	       && !is_depth_format(texImage->TexFormat->BaseFormat)
2206	       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2207	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2208	 goto out;
2209      }
2210      else if (is_ycbcr_format(format)
2211	       && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
2212	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2213	 goto out;
2214      }
2215      else if (is_depthstencil_format(format)
2216	       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2217	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2218	 goto out;
2219      }
2220
2221      if (ctx->Pack.BufferObj->Name) {
2222	 /* packing texture image into a PBO */
2223	 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
2224	 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
2225					texImage->Height, texImage->Depth,
2226					format, type, pixels)) {
2227	    _mesa_error(ctx, GL_INVALID_OPERATION,
2228			"glGetTexImage(invalid PBO access)");
2229	    goto out;
2230	 }
2231      }
2232
2233      /* typically, this will call _mesa_get_teximage() */
2234      ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
2235			      texObj, texImage);
2236
2237   }
2238 out:
2239   _mesa_unlock_texture(ctx, texObj);
2240}
2241
2242
2243
2244/**
2245 * Check if the given texture image is bound to any framebuffer objects
2246 * and update/invalidate them.
2247 * XXX We're only checking the currently bound framebuffer object for now.
2248 * In the future, perhaps struct gl_texture_image should have a pointer (or
2249 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2250 */
2251static void
2252update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
2253                   GLuint face, GLuint level)
2254{
2255   if (ctx->DrawBuffer->Name) {
2256      GLuint i;
2257      for (i = 0; i < BUFFER_COUNT; i++) {
2258         struct gl_renderbuffer_attachment *att =
2259            ctx->DrawBuffer->Attachment + i;
2260         if (att->Type == GL_TEXTURE &&
2261             att->Texture == texObj &&
2262             att->TextureLevel == level &&
2263             att->CubeMapFace == face) {
2264            ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
2265            /* Tell driver about the new renderbuffer texture */
2266            ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
2267         }
2268      }
2269   }
2270}
2271
2272
2273
2274/*
2275 * Called from the API.  Note that width includes the border.
2276 */
2277void GLAPIENTRY
2278_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2279                  GLsizei width, GLint border, GLenum format,
2280                  GLenum type, const GLvoid *pixels )
2281{
2282   GLsizei postConvWidth = width;
2283   GET_CURRENT_CONTEXT(ctx);
2284   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2285
2286   if (is_color_format(internalFormat)) {
2287      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2288   }
2289
2290   if (target == GL_TEXTURE_1D) {
2291      /* non-proxy target */
2292      struct gl_texture_unit *texUnit;
2293      struct gl_texture_object *texObj;
2294      struct gl_texture_image *texImage;
2295      const GLuint face = texture_face(target);
2296
2297      if (texture_error_check(ctx, target, level, internalFormat,
2298                              format, type, 1, postConvWidth, 1, 1, border)) {
2299         return;   /* error was recorded */
2300      }
2301
2302      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2303	 _mesa_update_state(ctx);
2304
2305      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2306      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2307      _mesa_lock_texture(ctx, texObj);
2308      {
2309	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2310	 if (!texImage) {
2311	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2312	    goto out;
2313	 }
2314
2315	 if (texImage->Data) {
2316	    ctx->Driver.FreeTexImageData( ctx, texImage );
2317	 }
2318
2319	 ASSERT(texImage->Data == NULL);
2320
2321	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2322	 _mesa_init_teximage_fields(ctx, target, texImage,
2323				    postConvWidth, 1, 1,
2324				    border, internalFormat);
2325
2326	 ASSERT(ctx->Driver.TexImage1D);
2327
2328	 /* Give the texture to the driver!  <pixels> may be null! */
2329	 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
2330				   width, border, format, type, pixels,
2331				   &ctx->Unpack, texObj, texImage);
2332
2333	 ASSERT(texImage->TexFormat);
2334
2335	 update_fbo_texture(ctx, texObj, face, level);
2336
2337	 /* state update */
2338	 texObj->Complete = GL_FALSE;
2339	 ctx->NewState |= _NEW_TEXTURE;
2340      }
2341   out:
2342      _mesa_unlock_texture(ctx, texObj);
2343   }
2344   else if (target == GL_PROXY_TEXTURE_1D) {
2345      /* Proxy texture: check for errors and update proxy state */
2346      struct gl_texture_image *texImage;
2347      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2348      if (texture_error_check(ctx, target, level, internalFormat,
2349                              format, type, 1, postConvWidth, 1, 1, border)) {
2350         /* when error, clear all proxy texture image parameters */
2351         if (texImage)
2352            clear_teximage_fields(texImage);
2353      }
2354      else {
2355         /* no error, set the tex image parameters */
2356         ASSERT(texImage);
2357         _mesa_init_teximage_fields(ctx, target, texImage,
2358                                    postConvWidth, 1, 1,
2359                                    border, internalFormat);
2360         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2361                                          internalFormat, format, type);
2362      }
2363   }
2364   else {
2365      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2366      return;
2367   }
2368}
2369
2370
2371void GLAPIENTRY
2372_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2373                  GLsizei width, GLsizei height, GLint border,
2374                  GLenum format, GLenum type,
2375                  const GLvoid *pixels )
2376{
2377   GLsizei postConvWidth = width, postConvHeight = height;
2378   GET_CURRENT_CONTEXT(ctx);
2379   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2380
2381   if (is_color_format(internalFormat)) {
2382      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2383					 &postConvHeight);
2384   }
2385
2386   if (target == GL_TEXTURE_2D ||
2387       (ctx->Extensions.ARB_texture_cube_map &&
2388        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2389        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2390       (ctx->Extensions.NV_texture_rectangle &&
2391        target == GL_TEXTURE_RECTANGLE_NV)) {
2392      /* non-proxy target */
2393      struct gl_texture_unit *texUnit;
2394      struct gl_texture_object *texObj;
2395      struct gl_texture_image *texImage;
2396      const GLuint face = texture_face(target);
2397
2398      if (texture_error_check(ctx, target, level, internalFormat,
2399                              format, type, 2, postConvWidth, postConvHeight,
2400                              1, border)) {
2401         return;   /* error was recorded */
2402      }
2403
2404      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2405	 _mesa_update_state(ctx);
2406
2407      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2408      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2409      _mesa_lock_texture(ctx, texObj);
2410      {
2411	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2412	 if (!texImage) {
2413	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2414	    goto out;
2415	 }
2416
2417	 if (texImage->Data) {
2418	    ctx->Driver.FreeTexImageData( ctx, texImage );
2419	 }
2420
2421	 ASSERT(texImage->Data == NULL);
2422	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2423	 _mesa_init_teximage_fields(ctx, target, texImage,
2424				    postConvWidth, postConvHeight, 1,
2425				    border, internalFormat);
2426
2427	 ASSERT(ctx->Driver.TexImage2D);
2428
2429	 /* Give the texture to the driver!  <pixels> may be null! */
2430	 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
2431				   width, height, border, format, type, pixels,
2432				   &ctx->Unpack, texObj, texImage);
2433
2434	 ASSERT(texImage->TexFormat);
2435
2436	 update_fbo_texture(ctx, texObj, face, level);
2437
2438	 /* state update */
2439	 texObj->Complete = GL_FALSE;
2440	 ctx->NewState |= _NEW_TEXTURE;
2441      }
2442   out:
2443      _mesa_unlock_texture(ctx, texObj);
2444   }
2445   else if (target == GL_PROXY_TEXTURE_2D ||
2446            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2447             ctx->Extensions.ARB_texture_cube_map) ||
2448            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2449             ctx->Extensions.NV_texture_rectangle)) {
2450      /* Proxy texture: check for errors and update proxy state */
2451      struct gl_texture_image *texImage;
2452      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2453      if (texture_error_check(ctx, target, level, internalFormat,
2454                              format, type, 2, postConvWidth, postConvHeight,
2455                              1, border)) {
2456         /* when error, clear all proxy texture image parameters */
2457         if (texImage)
2458            clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]);
2459      }
2460      else {
2461         /* no error, set the tex image parameters */
2462         _mesa_init_teximage_fields(ctx, target, texImage,
2463                                    postConvWidth, postConvHeight, 1,
2464                                    border, internalFormat);
2465         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2466                                          internalFormat, format, type);
2467      }
2468   }
2469   else {
2470      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2471      return;
2472   }
2473}
2474
2475
2476/*
2477 * Called by the API or display list executor.
2478 * Note that width and height include the border.
2479 */
2480void GLAPIENTRY
2481_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2482                  GLsizei width, GLsizei height, GLsizei depth,
2483                  GLint border, GLenum format, GLenum type,
2484                  const GLvoid *pixels )
2485{
2486   GET_CURRENT_CONTEXT(ctx);
2487   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2488
2489   if (target == GL_TEXTURE_3D) {
2490      /* non-proxy target */
2491      struct gl_texture_unit *texUnit;
2492      struct gl_texture_object *texObj;
2493      struct gl_texture_image *texImage;
2494      const GLuint face = texture_face(target);
2495
2496      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2497                              format, type, 3, width, height, depth, border)) {
2498         return;   /* error was recorded */
2499      }
2500
2501      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2502	 _mesa_update_state(ctx);
2503
2504      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2505      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2506      _mesa_lock_texture(ctx, texObj);
2507      {
2508	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2509	 if (!texImage) {
2510	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2511	    goto out;
2512	 }
2513
2514	 if (texImage->Data) {
2515	    ctx->Driver.FreeTexImageData( ctx, texImage );
2516	 }
2517
2518	 ASSERT(texImage->Data == NULL);
2519	 clear_teximage_fields(texImage); /* not really needed, but helpful */
2520	 _mesa_init_teximage_fields(ctx, target, texImage,
2521				    width, height, depth,
2522				    border, internalFormat);
2523
2524	 ASSERT(ctx->Driver.TexImage3D);
2525
2526	 /* Give the texture to the driver!  <pixels> may be null! */
2527	 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
2528				   width, height, depth, border, format, type,
2529				   pixels, &ctx->Unpack, texObj, texImage);
2530
2531	 ASSERT(texImage->TexFormat);
2532
2533	 update_fbo_texture(ctx, texObj, face, level);
2534
2535	 /* state update */
2536	 texObj->Complete = GL_FALSE;
2537	 ctx->NewState |= _NEW_TEXTURE;
2538      }
2539   out:
2540      _mesa_unlock_texture(ctx, texObj);
2541   }
2542   else if (target == GL_PROXY_TEXTURE_3D) {
2543      /* Proxy texture: check for errors and update proxy state */
2544      struct gl_texture_image *texImage;
2545      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2546      if (texture_error_check(ctx, target, level, internalFormat,
2547                              format, type, 3, width, height, depth, border)) {
2548         /* when error, clear all proxy texture image parameters */
2549         if (texImage)
2550            clear_teximage_fields(texImage);
2551      }
2552      else {
2553         /* no error, set the tex image parameters */
2554         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2555                                    depth, border, internalFormat);
2556         texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2557                                          internalFormat, format, type);
2558      }
2559   }
2560   else {
2561      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2562      return;
2563   }
2564}
2565
2566
2567void GLAPIENTRY
2568_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2569                     GLsizei width, GLsizei height, GLsizei depth,
2570                     GLint border, GLenum format, GLenum type,
2571                     const GLvoid *pixels )
2572{
2573   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2574                    depth, border, format, type, pixels);
2575}
2576
2577
2578
2579void GLAPIENTRY
2580_mesa_TexSubImage1D( GLenum target, GLint level,
2581                     GLint xoffset, GLsizei width,
2582                     GLenum format, GLenum type,
2583                     const GLvoid *pixels )
2584{
2585   GLsizei postConvWidth = width;
2586   struct gl_texture_unit *texUnit;
2587   struct gl_texture_object *texObj;
2588   struct gl_texture_image *texImage = NULL;
2589   GET_CURRENT_CONTEXT(ctx);
2590   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2591
2592   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2593      _mesa_update_state(ctx);
2594
2595   /* XXX should test internal format */
2596   if (is_color_format(format)) {
2597      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2598   }
2599
2600   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2601			       postConvWidth, 1, 1, format, type)) {
2602      return;   /* error was detected */
2603   }
2604
2605
2606   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2607   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2608   assert(texObj);
2609
2610   _mesa_lock_texture(ctx, texObj);
2611   {
2612      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2613
2614      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2615				  postConvWidth, 1, 1, format, type, texImage)) {
2616	 goto out;   /* error was detected */
2617      }
2618
2619      if (width == 0)
2620	 goto out;  /* no-op, not an error */
2621
2622      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2623      xoffset += texImage->Border;
2624
2625      ASSERT(ctx->Driver.TexSubImage1D);
2626      (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
2627				   format, type, pixels, &ctx->Unpack,
2628				   texObj, texImage);
2629      ctx->NewState |= _NEW_TEXTURE;
2630   }
2631 out:
2632   _mesa_unlock_texture(ctx, texObj);
2633}
2634
2635
2636void GLAPIENTRY
2637_mesa_TexSubImage2D( GLenum target, GLint level,
2638                     GLint xoffset, GLint yoffset,
2639                     GLsizei width, GLsizei height,
2640                     GLenum format, GLenum type,
2641                     const GLvoid *pixels )
2642{
2643   GLsizei postConvWidth = width, postConvHeight = height;
2644   struct gl_texture_unit *texUnit;
2645   struct gl_texture_object *texObj;
2646   struct gl_texture_image *texImage;
2647   GET_CURRENT_CONTEXT(ctx);
2648   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2649
2650   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2651      _mesa_update_state(ctx);
2652
2653   /* XXX should test internal format */
2654   if (is_color_format(format)) {
2655      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2656                                         &postConvHeight);
2657   }
2658
2659   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2660			      postConvWidth, postConvHeight, 1, format, type)) {
2661      return;   /* error was detected */
2662   }
2663
2664   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2665   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2666   _mesa_lock_texture(ctx, texObj);
2667   {
2668      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2669
2670      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2671				  postConvWidth, postConvHeight, 1, format, type,
2672				  texImage)) {
2673	 goto out;   /* error was detected */
2674      }
2675
2676      if (width == 0 || height == 0)
2677	 goto out;  /* no-op, not an error */
2678
2679      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2680      xoffset += texImage->Border;
2681      yoffset += texImage->Border;
2682
2683      ASSERT(ctx->Driver.TexSubImage2D);
2684      (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2685				   width, height, format, type, pixels,
2686				   &ctx->Unpack, texObj, texImage);
2687      ctx->NewState |= _NEW_TEXTURE;
2688   }
2689 out:
2690   _mesa_unlock_texture(ctx, texObj);
2691}
2692
2693
2694
2695void GLAPIENTRY
2696_mesa_TexSubImage3D( GLenum target, GLint level,
2697                     GLint xoffset, GLint yoffset, GLint zoffset,
2698                     GLsizei width, GLsizei height, GLsizei depth,
2699                     GLenum format, GLenum type,
2700                     const GLvoid *pixels )
2701{
2702   struct gl_texture_unit *texUnit;
2703   struct gl_texture_object *texObj;
2704   struct gl_texture_image *texImage;
2705   GET_CURRENT_CONTEXT(ctx);
2706   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2707
2708   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2709      _mesa_update_state(ctx);
2710
2711   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2712                              width, height, depth, format, type)) {
2713      return;   /* error was detected */
2714   }
2715
2716   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2717   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2718
2719   _mesa_lock_texture(ctx, texObj);
2720   {
2721      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2722
2723      if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
2724				  width, height, depth, format, type, texImage)) {
2725	 goto out;   /* error was detected */
2726      }
2727
2728      if (width == 0 || height == 0 || height == 0)
2729	 goto out;  /* no-op, not an error */
2730
2731      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2732      xoffset += texImage->Border;
2733      yoffset += texImage->Border;
2734      zoffset += texImage->Border;
2735
2736      ASSERT(ctx->Driver.TexSubImage3D);
2737      (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2738				   xoffset, yoffset, zoffset,
2739				   width, height, depth,
2740				   format, type, pixels,
2741				   &ctx->Unpack, texObj, texImage );
2742      ctx->NewState |= _NEW_TEXTURE;
2743   }
2744 out:
2745   _mesa_unlock_texture(ctx, texObj);
2746}
2747
2748
2749
2750void GLAPIENTRY
2751_mesa_CopyTexImage1D( GLenum target, GLint level,
2752                      GLenum internalFormat,
2753                      GLint x, GLint y,
2754                      GLsizei width, GLint border )
2755{
2756   struct gl_texture_unit *texUnit;
2757   struct gl_texture_object *texObj;
2758   struct gl_texture_image *texImage;
2759   GLsizei postConvWidth = width;
2760   const GLuint face = texture_face(target);
2761   GET_CURRENT_CONTEXT(ctx);
2762   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2763
2764   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2765      _mesa_update_state(ctx);
2766
2767   if (is_color_format(internalFormat)) {
2768      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2769   }
2770
2771   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2772                               postConvWidth, 1, border))
2773      return;
2774
2775   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2776   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2777   _mesa_lock_texture(ctx, texObj);
2778   {
2779      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2780      if (!texImage) {
2781	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2782	 goto out;
2783      }
2784
2785      if (texImage->Data) {
2786	 ctx->Driver.FreeTexImageData( ctx, texImage );
2787      }
2788
2789      ASSERT(texImage->Data == NULL);
2790
2791      clear_teximage_fields(texImage); /* not really needed, but helpful */
2792      _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2793				 border, internalFormat);
2794
2795
2796      ASSERT(ctx->Driver.CopyTexImage1D);
2797      (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
2798				    x, y, width, border);
2799
2800      ASSERT(texImage->TexFormat);
2801
2802      update_fbo_texture(ctx, texObj, face, level);
2803
2804      /* state update */
2805      texObj->Complete = GL_FALSE;
2806      ctx->NewState |= _NEW_TEXTURE;
2807   }
2808 out:
2809   _mesa_unlock_texture(ctx, texObj);
2810}
2811
2812
2813
2814void GLAPIENTRY
2815_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2816                      GLint x, GLint y, GLsizei width, GLsizei height,
2817                      GLint border )
2818{
2819   struct gl_texture_unit *texUnit;
2820   struct gl_texture_object *texObj;
2821   struct gl_texture_image *texImage;
2822   GLsizei postConvWidth = width, postConvHeight = height;
2823   const GLuint face = texture_face(target);
2824   GET_CURRENT_CONTEXT(ctx);
2825   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2826
2827   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2828      _mesa_update_state(ctx);
2829
2830   if (is_color_format(internalFormat)) {
2831      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2832                                         &postConvHeight);
2833   }
2834
2835   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2836                               postConvWidth, postConvHeight, border))
2837      return;
2838
2839   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2840   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2841
2842   _mesa_lock_texture(ctx, texObj);
2843   {
2844      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2845
2846      if (!texImage) {
2847	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2848	 goto out;
2849      }
2850
2851      if (texImage->Data) {
2852	 ctx->Driver.FreeTexImageData( ctx, texImage );
2853      }
2854
2855      ASSERT(texImage->Data == NULL);
2856
2857      clear_teximage_fields(texImage); /* not really needed, but helpful */
2858      _mesa_init_teximage_fields(ctx, target, texImage,
2859				 postConvWidth, postConvHeight, 1,
2860				 border, internalFormat);
2861
2862      ASSERT(ctx->Driver.CopyTexImage2D);
2863      (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
2864				    x, y, width, height, border);
2865
2866      ASSERT(texImage->TexFormat);
2867
2868      update_fbo_texture(ctx, texObj, face, level);
2869
2870      /* state update */
2871      texObj->Complete = GL_FALSE;
2872      ctx->NewState |= _NEW_TEXTURE;
2873   }
2874 out:
2875   _mesa_unlock_texture(ctx, texObj);
2876}
2877
2878
2879void GLAPIENTRY
2880_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2881                         GLint xoffset, GLint x, GLint y, GLsizei width )
2882{
2883   struct gl_texture_unit *texUnit;
2884   struct gl_texture_object *texObj;
2885   struct gl_texture_image *texImage;
2886   GLsizei postConvWidth = width;
2887   GET_CURRENT_CONTEXT(ctx);
2888   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2889
2890   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2891      _mesa_update_state(ctx);
2892
2893   /* XXX should test internal format */
2894   _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2895
2896   if (copytexsubimage_error_check(ctx, 1, target, level,
2897                                   xoffset, 0, 0, postConvWidth, 1))
2898      return;
2899
2900   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2901   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2902
2903   _mesa_lock_texture(ctx, texObj);
2904   {
2905      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2906
2907      if (copytexsubimage_error_check2(ctx, 1, target, level,
2908				       xoffset, 0, 0, postConvWidth, 1,
2909				       texImage))
2910	 goto out;
2911
2912
2913      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2914      xoffset += texImage->Border;
2915
2916      ASSERT(ctx->Driver.CopyTexSubImage1D);
2917      (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
2918      ctx->NewState |= _NEW_TEXTURE;
2919   }
2920 out:
2921   _mesa_unlock_texture(ctx, texObj);
2922}
2923
2924
2925
2926void GLAPIENTRY
2927_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2928                         GLint xoffset, GLint yoffset,
2929                         GLint x, GLint y, GLsizei width, GLsizei height )
2930{
2931   struct gl_texture_unit *texUnit;
2932   struct gl_texture_object *texObj;
2933   struct gl_texture_image *texImage;
2934   GLsizei postConvWidth = width, postConvHeight = height;
2935   GET_CURRENT_CONTEXT(ctx);
2936   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2937
2938   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2939      _mesa_update_state(ctx);
2940
2941   /* XXX should test internal format */
2942   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2943
2944   if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2945                                   postConvWidth, postConvHeight))
2946      return;
2947
2948   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2949   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2950
2951   _mesa_lock_texture(ctx, texObj);
2952   {
2953      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2954
2955      if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2956				       postConvWidth, postConvHeight, texImage))
2957	 goto out;
2958
2959      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2960      xoffset += texImage->Border;
2961      yoffset += texImage->Border;
2962
2963      ASSERT(ctx->Driver.CopyTexSubImage2D);
2964      (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2965				       xoffset, yoffset, x, y, width, height);
2966      ctx->NewState |= _NEW_TEXTURE;
2967   }
2968 out:
2969   _mesa_unlock_texture(ctx, texObj);
2970}
2971
2972
2973
2974void GLAPIENTRY
2975_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2976                         GLint xoffset, GLint yoffset, GLint zoffset,
2977                         GLint x, GLint y, GLsizei width, GLsizei height )
2978{
2979   struct gl_texture_unit *texUnit;
2980   struct gl_texture_object *texObj;
2981   struct gl_texture_image *texImage;
2982   GLsizei postConvWidth = width, postConvHeight = height;
2983   GET_CURRENT_CONTEXT(ctx);
2984   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2985
2986   if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2987      _mesa_update_state(ctx);
2988
2989   /* XXX should test internal format */
2990   _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2991
2992   if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2993                                   zoffset, postConvWidth, postConvHeight))
2994      return;
2995
2996   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2997   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2998
2999   _mesa_lock_texture(ctx, texObj);
3000   {
3001      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3002
3003      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
3004				       zoffset, postConvWidth, postConvHeight,
3005				       texImage))
3006	 goto out;
3007
3008      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3009      xoffset += texImage->Border;
3010      yoffset += texImage->Border;
3011      zoffset += texImage->Border;
3012
3013      ASSERT(ctx->Driver.CopyTexSubImage3D);
3014      (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
3015				       xoffset, yoffset, zoffset,
3016				       x, y, width, height);
3017      ctx->NewState |= _NEW_TEXTURE;
3018   }
3019 out:
3020   _mesa_unlock_texture(ctx, texObj);
3021}
3022
3023
3024
3025
3026/**********************************************************************/
3027/******                   Compressed Textures                    ******/
3028/**********************************************************************/
3029
3030
3031/**
3032 * Error checking for glCompressedTexImage[123]D().
3033 * \return error code or GL_NO_ERROR.
3034 */
3035static GLenum
3036compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3037                               GLenum target, GLint level,
3038                               GLenum internalFormat, GLsizei width,
3039                               GLsizei height, GLsizei depth, GLint border,
3040                               GLsizei imageSize)
3041{
3042   GLint expectedSize, maxLevels = 0, maxTextureSize;
3043
3044   if (dimensions == 1) {
3045      /* 1D compressed textures not allowed */
3046      return GL_INVALID_ENUM;
3047   }
3048   else if (dimensions == 2) {
3049      if (target == GL_PROXY_TEXTURE_2D) {
3050         maxLevels = ctx->Const.MaxTextureLevels;
3051      }
3052      else if (target == GL_TEXTURE_2D) {
3053         maxLevels = ctx->Const.MaxTextureLevels;
3054      }
3055      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3056         if (!ctx->Extensions.ARB_texture_cube_map)
3057            return GL_INVALID_ENUM; /*target*/
3058         maxLevels = ctx->Const.MaxCubeTextureLevels;
3059      }
3060      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3061               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3062         if (!ctx->Extensions.ARB_texture_cube_map)
3063            return GL_INVALID_ENUM; /*target*/
3064         maxLevels = ctx->Const.MaxCubeTextureLevels;
3065      }
3066      else {
3067         return GL_INVALID_ENUM; /*target*/
3068      }
3069   }
3070   else if (dimensions == 3) {
3071      /* 3D compressed textures not allowed */
3072      return GL_INVALID_ENUM;
3073   }
3074
3075   maxTextureSize = 1 << (maxLevels - 1);
3076
3077   /* This will detect any invalid internalFormat value */
3078   if (!is_compressed_format(ctx, internalFormat))
3079      return GL_INVALID_ENUM;
3080
3081   /* This should really never fail */
3082   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3083      return GL_INVALID_ENUM;
3084
3085   if (border != 0)
3086      return GL_INVALID_VALUE;
3087
3088   /*
3089    * XXX We should probably use the proxy texture error check function here.
3090    */
3091   if (width < 1 || width > maxTextureSize ||
3092       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1))
3093      return GL_INVALID_VALUE;
3094
3095   if ((height < 1 || height > maxTextureSize ||
3096       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1))
3097       && dimensions > 1)
3098      return GL_INVALID_VALUE;
3099
3100   if ((depth < 1 || depth > maxTextureSize ||
3101       (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1))
3102       && dimensions > 2)
3103      return GL_INVALID_VALUE;
3104
3105   /* For cube map, width must equal height */
3106   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3107       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3108      return GL_INVALID_VALUE;
3109
3110   if (level < 0 || level >= maxLevels)
3111      return GL_INVALID_VALUE;
3112
3113   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3114                                                       depth, internalFormat);
3115   if (expectedSize != imageSize)
3116      return GL_INVALID_VALUE;
3117
3118#if FEATURE_EXT_texture_sRGB
3119   if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3120        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3121        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3122        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3123       && border != 0) {
3124      return GL_INVALID_OPERATION;
3125   }
3126#endif
3127
3128   return GL_NO_ERROR;
3129}
3130
3131
3132/**
3133 * Error checking for glCompressedTexSubImage[123]D().
3134 * \warning  There are some bad assumptions here about the size of compressed
3135 *           texture tiles (multiple of 4) used to test the validity of the
3136 *           offset and size parameters.
3137 * \return error code or GL_NO_ERROR.
3138 */
3139static GLenum
3140compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3141                                  GLenum target, GLint level,
3142                                  GLint xoffset, GLint yoffset, GLint zoffset,
3143                                  GLsizei width, GLsizei height, GLsizei depth,
3144                                  GLenum format, GLsizei imageSize)
3145{
3146   GLint expectedSize, maxLevels = 0, maxTextureSize;
3147   (void) zoffset;
3148
3149   if (dimensions == 1) {
3150      /* 1D compressed textures not allowed */
3151      return GL_INVALID_ENUM;
3152   }
3153   else if (dimensions == 2) {
3154      if (target == GL_PROXY_TEXTURE_2D) {
3155         maxLevels = ctx->Const.MaxTextureLevels;
3156      }
3157      else if (target == GL_TEXTURE_2D) {
3158         maxLevels = ctx->Const.MaxTextureLevels;
3159      }
3160      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3161         if (!ctx->Extensions.ARB_texture_cube_map)
3162            return GL_INVALID_ENUM; /*target*/
3163         maxLevels = ctx->Const.MaxCubeTextureLevels;
3164      }
3165      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3166               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3167         if (!ctx->Extensions.ARB_texture_cube_map)
3168            return GL_INVALID_ENUM; /*target*/
3169         maxLevels = ctx->Const.MaxCubeTextureLevels;
3170      }
3171      else {
3172         return GL_INVALID_ENUM; /*target*/
3173      }
3174   }
3175   else if (dimensions == 3) {
3176      /* 3D compressed textures not allowed */
3177      return GL_INVALID_ENUM;
3178   }
3179
3180   maxTextureSize = 1 << (maxLevels - 1);
3181
3182   /* this will catch any invalid compressed format token */
3183   if (!is_compressed_format(ctx, format))
3184      return GL_INVALID_ENUM;
3185
3186   if (width < 1 || width > maxTextureSize)
3187      return GL_INVALID_VALUE;
3188
3189   if ((height < 1 || height > maxTextureSize)
3190       && dimensions > 1)
3191      return GL_INVALID_VALUE;
3192
3193   if (level < 0 || level >= maxLevels)
3194      return GL_INVALID_VALUE;
3195
3196   /* XXX these tests are specific to the compressed format.
3197    * this code should be generalized in some way.
3198    */
3199   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3200      return GL_INVALID_VALUE;
3201
3202   if ((width & 3) != 0 && width != 2 && width != 1)
3203      return GL_INVALID_VALUE;
3204
3205   if ((height & 3) != 0 && height != 2 && height != 1)
3206      return GL_INVALID_VALUE;
3207
3208   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3209                                                       depth, format);
3210   if (expectedSize != imageSize)
3211      return GL_INVALID_VALUE;
3212
3213   return GL_NO_ERROR;
3214}
3215
3216
3217
3218void GLAPIENTRY
3219_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3220                              GLenum internalFormat, GLsizei width,
3221                              GLint border, GLsizei imageSize,
3222                              const GLvoid *data)
3223{
3224   GET_CURRENT_CONTEXT(ctx);
3225   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3226
3227   if (target == GL_TEXTURE_1D) {
3228      /* non-proxy target */
3229      struct gl_texture_unit *texUnit;
3230      struct gl_texture_object *texObj;
3231      struct gl_texture_image *texImage;
3232      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3233                               internalFormat, width, 1, 1, border, imageSize);
3234      if (error) {
3235         _mesa_error(ctx, error, "glCompressedTexImage1D");
3236         return;
3237      }
3238
3239      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3240      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3241
3242      _mesa_lock_texture(ctx, texObj);
3243      {
3244	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3245	 if (!texImage) {
3246	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3247	    goto out;
3248	 }
3249
3250	 if (texImage->Data) {
3251	    ctx->Driver.FreeTexImageData( ctx, texImage );
3252	 }
3253	 ASSERT(texImage->Data == NULL);
3254
3255	 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3256				    border, internalFormat);
3257
3258	 ASSERT(ctx->Driver.CompressedTexImage1D);
3259	 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
3260					     internalFormat, width, border,
3261					     imageSize, data,
3262					     texObj, texImage);
3263
3264	 /* state update */
3265	 texObj->Complete = GL_FALSE;
3266	 ctx->NewState |= _NEW_TEXTURE;
3267      }
3268   out:
3269      _mesa_unlock_texture(ctx, texObj);
3270   }
3271   else if (target == GL_PROXY_TEXTURE_1D) {
3272      /* Proxy texture: check for errors and update proxy state */
3273      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3274                               internalFormat, width, 1, 1, border, imageSize);
3275      if (!error) {
3276         ASSERT(ctx->Driver.TestProxyTexImage);
3277         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3278                                             internalFormat, GL_NONE, GL_NONE,
3279                                             width, 1, 1, border);
3280      }
3281      if (error) {
3282         /* if error, clear all proxy texture image parameters */
3283         struct gl_texture_image *texImage;
3284         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3285         if (texImage)
3286            clear_teximage_fields(texImage);
3287      }
3288      else {
3289         /* store the teximage parameters */
3290         struct gl_texture_unit *texUnit;
3291         struct gl_texture_object *texObj;
3292         struct gl_texture_image *texImage;
3293         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3294	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3295
3296	 _mesa_lock_texture(ctx, texObj);
3297	 {
3298	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3299	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3300				       border, internalFormat);
3301	 }
3302	 _mesa_unlock_texture(ctx, texObj);
3303      }
3304   }
3305   else {
3306      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3307      return;
3308   }
3309}
3310
3311
3312void GLAPIENTRY
3313_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3314                              GLenum internalFormat, GLsizei width,
3315                              GLsizei height, GLint border, GLsizei imageSize,
3316                              const GLvoid *data)
3317{
3318   GET_CURRENT_CONTEXT(ctx);
3319   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3320
3321   if (target == GL_TEXTURE_2D ||
3322       (ctx->Extensions.ARB_texture_cube_map &&
3323        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3324        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3325      /* non-proxy target */
3326      struct gl_texture_unit *texUnit;
3327      struct gl_texture_object *texObj;
3328      struct gl_texture_image *texImage;
3329      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3330                          internalFormat, width, height, 1, border, imageSize);
3331      if (error) {
3332         _mesa_error(ctx, error, "glCompressedTexImage2D");
3333         return;
3334      }
3335
3336      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3337      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3338
3339      _mesa_lock_texture(ctx, texObj);
3340      {
3341	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3342	 if (!texImage) {
3343	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3344	    goto out;
3345	 }
3346
3347	 if (texImage->Data) {
3348	    ctx->Driver.FreeTexImageData( ctx, texImage );
3349	 }
3350	 ASSERT(texImage->Data == NULL);
3351
3352	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3353				    border, internalFormat);
3354
3355	 ASSERT(ctx->Driver.CompressedTexImage2D);
3356	 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
3357					     internalFormat, width, height,
3358					     border, imageSize, data,
3359					     texObj, texImage);
3360
3361	 /* state update */
3362	 texObj->Complete = GL_FALSE;
3363	 ctx->NewState |= _NEW_TEXTURE;
3364      }
3365   out:
3366      _mesa_unlock_texture(ctx, texObj);
3367   }
3368   else if (target == GL_PROXY_TEXTURE_2D ||
3369            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3370             ctx->Extensions.ARB_texture_cube_map)) {
3371      /* Proxy texture: check for errors and update proxy state */
3372      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3373                          internalFormat, width, height, 1, border, imageSize);
3374      if (!error) {
3375         ASSERT(ctx->Driver.TestProxyTexImage);
3376         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3377                                              internalFormat, GL_NONE, GL_NONE,
3378                                              width, height, 1, border);
3379      }
3380      if (error) {
3381         /* if error, clear all proxy texture image parameters */
3382         struct gl_texture_image *texImage;
3383         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3384         if (texImage)
3385            clear_teximage_fields(texImage);
3386      }
3387      else {
3388         /* store the teximage parameters */
3389         struct gl_texture_unit *texUnit;
3390         struct gl_texture_object *texObj;
3391         struct gl_texture_image *texImage;
3392         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3393	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3394
3395	 _mesa_lock_texture(ctx, texObj);
3396	 {
3397	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3398	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3399				       border, internalFormat);
3400	 }
3401	 _mesa_unlock_texture(ctx, texObj);
3402      }
3403   }
3404   else {
3405      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3406      return;
3407   }
3408}
3409
3410
3411void GLAPIENTRY
3412_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3413                              GLenum internalFormat, GLsizei width,
3414                              GLsizei height, GLsizei depth, GLint border,
3415                              GLsizei imageSize, const GLvoid *data)
3416{
3417   GET_CURRENT_CONTEXT(ctx);
3418   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3419
3420   if (target == GL_TEXTURE_3D) {
3421      /* non-proxy target */
3422      struct gl_texture_unit *texUnit;
3423      struct gl_texture_object *texObj;
3424      struct gl_texture_image *texImage;
3425      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3426                      internalFormat, width, height, depth, border, imageSize);
3427      if (error) {
3428         _mesa_error(ctx, error, "glCompressedTexImage3D");
3429         return;
3430      }
3431
3432      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3433      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3434      _mesa_lock_texture(ctx, texObj);
3435      {
3436	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3437	 if (!texImage) {
3438	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3439	    goto out;
3440	 }
3441
3442	 if (texImage->Data) {
3443	    ctx->Driver.FreeTexImageData( ctx, texImage );
3444	 }
3445	 ASSERT(texImage->Data == NULL);
3446
3447	 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
3448				    border, internalFormat);
3449
3450	 ASSERT(ctx->Driver.CompressedTexImage3D);
3451	 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3452					     internalFormat,
3453					     width, height, depth,
3454					     border, imageSize, data,
3455					     texObj, texImage);
3456
3457	 /* state update */
3458	 texObj->Complete = GL_FALSE;
3459	 ctx->NewState |= _NEW_TEXTURE;
3460      }
3461   out:
3462      _mesa_unlock_texture(ctx, texObj);
3463   }
3464   else if (target == GL_PROXY_TEXTURE_3D) {
3465      /* Proxy texture: check for errors and update proxy state */
3466      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3467                      internalFormat, width, height, depth, border, imageSize);
3468      if (!error) {
3469         ASSERT(ctx->Driver.TestProxyTexImage);
3470         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3471                                             internalFormat, GL_NONE, GL_NONE,
3472                                             width, height, depth, border);
3473      }
3474      if (error) {
3475         /* if error, clear all proxy texture image parameters */
3476         struct gl_texture_image *texImage;
3477         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3478         if (texImage)
3479            clear_teximage_fields(texImage);
3480      }
3481      else {
3482         /* store the teximage parameters */
3483         struct gl_texture_unit *texUnit;
3484         struct gl_texture_object *texObj;
3485         struct gl_texture_image *texImage;
3486         texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3487	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3488	 _mesa_lock_texture(ctx, texObj);
3489	 {
3490	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3491	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3492				       depth, border, internalFormat);
3493	 }
3494	 _mesa_unlock_texture(ctx, texObj);
3495      }
3496   }
3497   else {
3498      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3499      return;
3500   }
3501}
3502
3503
3504void GLAPIENTRY
3505_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3506                                 GLsizei width, GLenum format,
3507                                 GLsizei imageSize, const GLvoid *data)
3508{
3509   struct gl_texture_unit *texUnit;
3510   struct gl_texture_object *texObj;
3511   struct gl_texture_image *texImage;
3512   GLenum error;
3513   GET_CURRENT_CONTEXT(ctx);
3514   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3515
3516   error = compressed_subtexture_error_check(ctx, 1, target, level,
3517                                             xoffset, 0, 0, /* pos */
3518                                             width, 1, 1,   /* size */
3519                                             format, imageSize);
3520   if (error) {
3521      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3522      return;
3523   }
3524
3525   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3526   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3527   _mesa_lock_texture(ctx, texObj);
3528   {
3529      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3530      assert(texImage);
3531
3532      if ((GLint) format != texImage->InternalFormat) {
3533	 _mesa_error(ctx, GL_INVALID_OPERATION,
3534		     "glCompressedTexSubImage1D(format)");
3535	 goto out;
3536      }
3537
3538      if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
3539	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
3540	 goto out;
3541      }
3542
3543      if (width == 0)
3544	 goto out;  /* no-op, not an error */
3545
3546      if (ctx->Driver.CompressedTexSubImage1D) {
3547	 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3548						xoffset, width,
3549						format, imageSize, data,
3550						texObj, texImage);
3551      }
3552      ctx->NewState |= _NEW_TEXTURE;
3553   }
3554 out:
3555   _mesa_unlock_texture(ctx, texObj);
3556}
3557
3558
3559void GLAPIENTRY
3560_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3561                                 GLint yoffset, GLsizei width, GLsizei height,
3562                                 GLenum format, GLsizei imageSize,
3563                                 const GLvoid *data)
3564{
3565   struct gl_texture_unit *texUnit;
3566   struct gl_texture_object *texObj;
3567   struct gl_texture_image *texImage;
3568   GLenum error;
3569   GET_CURRENT_CONTEXT(ctx);
3570   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3571
3572   error = compressed_subtexture_error_check(ctx, 2, target, level,
3573                                             xoffset, yoffset, 0, /* pos */
3574                                             width, height, 1,    /* size */
3575                                             format, imageSize);
3576   if (error) {
3577      /* XXX proxy target? */
3578      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3579      return;
3580   }
3581
3582   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3583   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3584   _mesa_lock_texture(ctx, texObj);
3585   {
3586      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3587      assert(texImage);
3588
3589      if ((GLint) format != texImage->InternalFormat) {
3590	 _mesa_error(ctx, GL_INVALID_OPERATION,
3591		     "glCompressedTexSubImage2D(format)");
3592	 goto out;
3593      }
3594
3595      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3596	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
3597	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3598	 goto out;
3599      }
3600
3601      if (width == 0 || height == 0)
3602	 goto out;  /* no-op, not an error */
3603
3604      if (ctx->Driver.CompressedTexSubImage2D) {
3605	 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3606						xoffset, yoffset, width, height,
3607						format, imageSize, data,
3608						texObj, texImage);
3609      }
3610      ctx->NewState |= _NEW_TEXTURE;
3611   }
3612 out:
3613   _mesa_unlock_texture(ctx, texObj);
3614}
3615
3616
3617void GLAPIENTRY
3618_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3619                                 GLint yoffset, GLint zoffset, GLsizei width,
3620                                 GLsizei height, GLsizei depth, GLenum format,
3621                                 GLsizei imageSize, const GLvoid *data)
3622{
3623   struct gl_texture_unit *texUnit;
3624   struct gl_texture_object *texObj;
3625   struct gl_texture_image *texImage;
3626   GLenum error;
3627   GET_CURRENT_CONTEXT(ctx);
3628   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3629
3630   error = compressed_subtexture_error_check(ctx, 3, target, level,
3631                                             xoffset, yoffset, zoffset,/*pos*/
3632                                             width, height, depth, /*size*/
3633                                             format, imageSize);
3634   if (error) {
3635      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3636      return;
3637   }
3638
3639   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3640   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3641   _mesa_lock_texture(ctx, texObj);
3642   {
3643      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3644      assert(texImage);
3645
3646      if ((GLint) format != texImage->InternalFormat) {
3647	 _mesa_error(ctx, GL_INVALID_OPERATION,
3648		     "glCompressedTexSubImage3D(format)");
3649	 goto out;
3650      }
3651
3652      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3653	  ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
3654	  ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
3655	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3656	 goto out;
3657      }
3658
3659      if (width == 0 || height == 0 || depth == 0)
3660	 goto out;  /* no-op, not an error */
3661
3662      if (ctx->Driver.CompressedTexSubImage3D) {
3663	 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3664						xoffset, yoffset, zoffset,
3665						width, height, depth,
3666						format, imageSize, data,
3667						texObj, texImage);
3668      }
3669      ctx->NewState |= _NEW_TEXTURE;
3670   }
3671 out:
3672   _mesa_unlock_texture(ctx, texObj);
3673}
3674
3675
3676void GLAPIENTRY
3677_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3678{
3679   const struct gl_texture_unit *texUnit;
3680   struct gl_texture_object *texObj;
3681   struct gl_texture_image *texImage;
3682   GLint maxLevels;
3683   GET_CURRENT_CONTEXT(ctx);
3684   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3685
3686
3687   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3688   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3689   if (!texObj) {
3690      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
3691      return;
3692   }
3693
3694   maxLevels = _mesa_max_texture_levels(ctx, target);
3695   ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
3696
3697   if (level < 0 || level >= maxLevels) {
3698      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3699      return;
3700   }
3701
3702   if (_mesa_is_proxy_texture(target)) {
3703      _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3704      return;
3705   }
3706
3707
3708   _mesa_lock_texture(ctx, texObj);
3709   {
3710      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3711      if (!texImage) {
3712	 /* probably invalid mipmap level */
3713	 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3714	 goto out;
3715      }
3716
3717      if (!texImage->IsCompressed) {
3718	 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3719	 goto out;
3720      }
3721
3722      /* this typically calls _mesa_get_compressed_teximage() */
3723      ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
3724   }
3725 out:
3726   _mesa_unlock_texture(ctx, texObj);
3727}
3728