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