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