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