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