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