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