teximage.c revision 1a2bb37264b4448d33f2948fe1702c9dc936395d
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#include "convolve.h"
37#include "enums.h"
38#include "fbobject.h"
39#include "framebuffer.h"
40#include "hash.h"
41#include "image.h"
42#include "imports.h"
43#include "macros.h"
44#include "state.h"
45#include "texcompress.h"
46#include "texfetch.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 * Get the texture object that corresponds to the target of the given texture unit.
580 *
581 * \param ctx GL context.
582 * \param texUnit texture unit.
583 * \param target texture target.
584 *
585 * \return pointer to the texture object on success, or NULL on failure.
586 *
587 * \sa gl_texture_unit.
588 */
589struct gl_texture_object *
590_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
591                        GLenum target)
592{
593   switch (target) {
594      case GL_TEXTURE_1D:
595         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
596      case GL_PROXY_TEXTURE_1D:
597         return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
598      case GL_TEXTURE_2D:
599         return texUnit->CurrentTex[TEXTURE_2D_INDEX];
600      case GL_PROXY_TEXTURE_2D:
601         return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
602      case GL_TEXTURE_3D:
603         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
604      case GL_PROXY_TEXTURE_3D:
605         return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
606      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
607      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
608      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
609      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
610      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
611      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
612      case GL_TEXTURE_CUBE_MAP_ARB:
613         return ctx->Extensions.ARB_texture_cube_map
614                ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
615      case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
616         return ctx->Extensions.ARB_texture_cube_map
617                ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
618      case GL_TEXTURE_RECTANGLE_NV:
619         return ctx->Extensions.NV_texture_rectangle
620                ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
621      case GL_PROXY_TEXTURE_RECTANGLE_NV:
622         return ctx->Extensions.NV_texture_rectangle
623                ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
624      case GL_TEXTURE_1D_ARRAY_EXT:
625         return ctx->Extensions.MESA_texture_array
626                ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
627      case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
628         return ctx->Extensions.MESA_texture_array
629                ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
630      case GL_TEXTURE_2D_ARRAY_EXT:
631         return ctx->Extensions.MESA_texture_array
632                ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
633      case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
634         return ctx->Extensions.MESA_texture_array
635                ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
636      default:
637         _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
638         return NULL;
639   }
640}
641
642
643/**
644 * Get a texture image pointer from a texture object, given a texture
645 * target and mipmap level.  The target and level parameters should
646 * have already been error-checked.
647 *
648 * \param ctx GL context.
649 * \param texObj texture unit.
650 * \param target texture target.
651 * \param level image level.
652 *
653 * \return pointer to the texture image structure, or NULL on failure.
654 */
655struct gl_texture_image *
656_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
657		       GLenum target, GLint level)
658{
659   const GLuint face = _mesa_tex_target_to_face(target);
660
661   ASSERT(texObj);
662   ASSERT(level >= 0);
663   ASSERT(level < MAX_TEXTURE_LEVELS);
664
665   return texObj->Image[face][level];
666}
667
668
669/**
670 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
671 * it and install it.  Only return NULL if passed a bad parameter or run
672 * out of memory.
673 */
674struct gl_texture_image *
675_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
676                    GLenum target, GLint level)
677{
678   struct gl_texture_image *texImage;
679
680   if (!texObj)
681      return NULL;
682
683   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
684   if (!texImage) {
685      texImage = ctx->Driver.NewTextureImage(ctx);
686      if (!texImage) {
687         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
688         return NULL;
689      }
690
691      _mesa_set_tex_image(texObj, target, level, texImage);
692   }
693
694   return texImage;
695}
696
697
698/**
699 * Return pointer to the specified proxy texture image.
700 * Note that proxy textures are per-context, not per-texture unit.
701 * \return pointer to texture image or NULL if invalid target, invalid
702 *         level, or out of memory.
703 */
704struct gl_texture_image *
705_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
706{
707   struct gl_texture_image *texImage;
708   GLuint texIndex;
709
710   if (level < 0 )
711      return NULL;
712
713   switch (target) {
714   case GL_PROXY_TEXTURE_1D:
715      if (level >= ctx->Const.MaxTextureLevels)
716         return NULL;
717      texIndex = TEXTURE_1D_INDEX;
718      break;
719   case GL_PROXY_TEXTURE_2D:
720      if (level >= ctx->Const.MaxTextureLevels)
721         return NULL;
722      texIndex = TEXTURE_2D_INDEX;
723      break;
724   case GL_PROXY_TEXTURE_3D:
725      if (level >= ctx->Const.Max3DTextureLevels)
726         return NULL;
727      texIndex = TEXTURE_3D_INDEX;
728      break;
729   case GL_PROXY_TEXTURE_CUBE_MAP:
730      if (level >= ctx->Const.MaxCubeTextureLevels)
731         return NULL;
732      texIndex = TEXTURE_CUBE_INDEX;
733      break;
734   case GL_PROXY_TEXTURE_RECTANGLE_NV:
735      if (level > 0)
736         return NULL;
737      texIndex = TEXTURE_RECT_INDEX;
738      break;
739   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
740      if (level >= ctx->Const.MaxTextureLevels)
741         return NULL;
742      texIndex = TEXTURE_1D_ARRAY_INDEX;
743      break;
744   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
745      if (level >= ctx->Const.MaxTextureLevels)
746         return NULL;
747      texIndex = TEXTURE_2D_ARRAY_INDEX;
748      break;
749   default:
750      return NULL;
751   }
752
753   texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
754   if (!texImage) {
755      texImage = ctx->Driver.NewTextureImage(ctx);
756      if (!texImage) {
757         _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
758         return NULL;
759      }
760      ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
761      /* Set the 'back' pointer */
762      texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
763   }
764   return texImage;
765}
766
767
768/**
769 * Get the maximum number of allowed mipmap levels.
770 *
771 * \param ctx GL context.
772 * \param target texture target.
773 *
774 * \return the maximum number of allowed mipmap levels for the given
775 * texture target, or zero if passed a bad target.
776 *
777 * \sa gl_constants.
778 */
779GLint
780_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
781{
782   switch (target) {
783   case GL_TEXTURE_1D:
784   case GL_PROXY_TEXTURE_1D:
785   case GL_TEXTURE_2D:
786   case GL_PROXY_TEXTURE_2D:
787      return ctx->Const.MaxTextureLevels;
788   case GL_TEXTURE_3D:
789   case GL_PROXY_TEXTURE_3D:
790      return ctx->Const.Max3DTextureLevels;
791   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
792   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
793   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
794   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
795   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
796   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
797   case GL_TEXTURE_CUBE_MAP_ARB:
798   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
799      return ctx->Extensions.ARB_texture_cube_map
800         ? ctx->Const.MaxCubeTextureLevels : 0;
801   case GL_TEXTURE_RECTANGLE_NV:
802   case GL_PROXY_TEXTURE_RECTANGLE_NV:
803      return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
804   case GL_TEXTURE_1D_ARRAY_EXT:
805   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
806   case GL_TEXTURE_2D_ARRAY_EXT:
807   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
808      return ctx->Extensions.MESA_texture_array
809         ? ctx->Const.MaxTextureLevels : 0;
810   default:
811      return 0; /* bad target */
812   }
813}
814
815
816
817#if 000 /* not used anymore */
818/*
819 * glTexImage[123]D can accept a NULL image pointer.  In this case we
820 * create a texture image with unspecified image contents per the OpenGL
821 * spec.
822 */
823static GLubyte *
824make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
825{
826   const GLint components = _mesa_components_in_format(format);
827   const GLint numPixels = width * height * depth;
828   GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
829
830#ifdef DEBUG
831   /*
832    * Let's see if anyone finds this.  If glTexImage2D() is called with
833    * a NULL image pointer then load the texture image with something
834    * interesting instead of leaving it indeterminate.
835    */
836   if (data) {
837      static const char message[8][32] = {
838         "   X   X  XXXXX   XXX     X    ",
839         "   XX XX  X      X   X   X X   ",
840         "   X X X  X      X      X   X  ",
841         "   X   X  XXXX    XXX   XXXXX  ",
842         "   X   X  X          X  X   X  ",
843         "   X   X  X      X   X  X   X  ",
844         "   X   X  XXXXX   XXX   X   X  ",
845         "                               "
846      };
847
848      GLubyte *imgPtr = data;
849      GLint h, i, j, k;
850      for (h = 0; h < depth; h++) {
851         for (i = 0; i < height; i++) {
852            GLint srcRow = 7 - (i % 8);
853            for (j = 0; j < width; j++) {
854               GLint srcCol = j % 32;
855               GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
856               for (k = 0; k < components; k++) {
857                  *imgPtr++ = texel;
858               }
859            }
860         }
861      }
862   }
863#endif
864
865   return data;
866}
867#endif
868
869
870
871/**
872 * Reset the fields of a gl_texture_image struct to zero.
873 *
874 * \param img texture image structure.
875 *
876 * This is called when a proxy texture test fails, we set all the
877 * image members (except DriverData) to zero.
878 * It's also used in glTexImage[123]D as a safeguard to be sure all
879 * required fields get initialized properly by the Driver.TexImage[123]D
880 * functions.
881 */
882static void
883clear_teximage_fields(struct gl_texture_image *img)
884{
885   ASSERT(img);
886   img->_BaseFormat = 0;
887   img->InternalFormat = 0;
888   img->Border = 0;
889   img->Width = 0;
890   img->Height = 0;
891   img->Depth = 0;
892   img->RowStride = 0;
893   if (img->ImageOffsets) {
894      _mesa_free(img->ImageOffsets);
895      img->ImageOffsets = NULL;
896   }
897   img->Width2 = 0;
898   img->Height2 = 0;
899   img->Depth2 = 0;
900   img->WidthLog2 = 0;
901   img->HeightLog2 = 0;
902   img->DepthLog2 = 0;
903   img->Data = NULL;
904   img->TexFormat = MESA_FORMAT_NONE;
905   img->FetchTexelc = NULL;
906   img->FetchTexelf = NULL;
907}
908
909
910/**
911 * Initialize basic fields of the gl_texture_image struct.
912 *
913 * \param ctx GL context.
914 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
915 * \param img texture image structure to be initialized.
916 * \param width image width.
917 * \param height image height.
918 * \param depth image depth.
919 * \param border image border.
920 * \param internalFormat internal format.
921 *
922 * Fills in the fields of \p img with the given information.
923 * Note: width, height and depth include the border.
924 */
925void
926_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
927                           struct gl_texture_image *img,
928                           GLsizei width, GLsizei height, GLsizei depth,
929                           GLint border, GLenum internalFormat)
930{
931   GLint i;
932
933   ASSERT(img);
934   ASSERT(width >= 0);
935   ASSERT(height >= 0);
936   ASSERT(depth >= 0);
937
938   img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
939   ASSERT(img->_BaseFormat > 0);
940   img->InternalFormat = internalFormat;
941   img->Border = border;
942   img->Width = width;
943   img->Height = height;
944   img->Depth = depth;
945
946   img->Width2 = width - 2 * border;   /* == 1 << img->WidthLog2; */
947   img->WidthLog2 = logbase2(img->Width2);
948
949   if (height == 1) { /* 1-D texture */
950      img->Height2 = 1;
951      img->HeightLog2 = 0;
952   }
953   else {
954      img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
955      img->HeightLog2 = logbase2(img->Height2);
956   }
957
958   if (depth == 1) {  /* 2-D texture */
959      img->Depth2 = 1;
960      img->DepthLog2 = 0;
961   }
962   else {
963      img->Depth2 = depth - 2 * border;   /* == 1 << img->DepthLog2; */
964      img->DepthLog2 = logbase2(img->Depth2);
965   }
966
967   img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
968
969   if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
970       (height == 1 || _mesa_is_pow_two(img->Height2)) &&
971       (depth == 1 || _mesa_is_pow_two(img->Depth2)))
972      img->_IsPowerOfTwo = GL_TRUE;
973   else
974      img->_IsPowerOfTwo = GL_FALSE;
975
976   /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
977   img->RowStride = width;
978   /* Allocate the ImageOffsets array and initialize to typical values.
979    * We allocate the array for 1D/2D textures too in order to avoid special-
980    * case code in the texstore routines.
981    */
982   if (img->ImageOffsets)
983      _mesa_free(img->ImageOffsets);
984   img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
985   for (i = 0; i < depth; i++) {
986      img->ImageOffsets[i] = i * width * height;
987   }
988
989   /* Compute Width/Height/DepthScale for mipmap lod computation */
990   if (target == GL_TEXTURE_RECTANGLE_NV) {
991      /* scale = 1.0 since texture coords directly map to texels */
992      img->WidthScale = 1.0;
993      img->HeightScale = 1.0;
994      img->DepthScale = 1.0;
995   }
996   else {
997      img->WidthScale = (GLfloat) img->Width;
998      img->HeightScale = (GLfloat) img->Height;
999      img->DepthScale = (GLfloat) img->Depth;
1000   }
1001
1002   img->FetchTexelc = NULL;
1003   img->FetchTexelf = NULL;
1004}
1005
1006
1007/**
1008 * Free and clear fields of the gl_texture_image struct.
1009 *
1010 * \param ctx GL context.
1011 * \param texImage texture image structure to be cleared.
1012 *
1013 * After the call, \p texImage will have no data associated with it.  Its
1014 * fields are cleared so that its parent object will test incomplete.
1015 */
1016void
1017_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage)
1018{
1019   ctx->Driver.FreeTexImageData(ctx, texImage);
1020   clear_teximage_fields(texImage);
1021}
1022
1023
1024/**
1025 * This is the fallback for Driver.TestProxyTexImage().  Test the texture
1026 * level, width, height and depth against the ctx->Const limits for textures.
1027 *
1028 * A hardware driver might override this function if, for example, the
1029 * max 3D texture size is 512x512x64 (i.e. not a cube).
1030 *
1031 * Note that width, height, depth == 0 is not an error.  However, a
1032 * texture with zero width/height/depth will be considered "incomplete"
1033 * and texturing will effectively be disabled.
1034 *
1035 * \param target  one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1036 *                GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1037 *                GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1038 * \param level  as passed to glTexImage
1039 * \param internalFormat  as passed to glTexImage
1040 * \param format  as passed to glTexImage
1041 * \param type  as passed to glTexImage
1042 * \param width  as passed to glTexImage
1043 * \param height  as passed to glTexImage
1044 * \param depth  as passed to glTexImage
1045 * \param border  as passed to glTexImage
1046 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1047 */
1048GLboolean
1049_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1050                          GLint internalFormat, GLenum format, GLenum type,
1051                          GLint width, GLint height, GLint depth, GLint border)
1052{
1053   GLint maxSize;
1054
1055   (void) internalFormat;
1056   (void) format;
1057   (void) type;
1058
1059   switch (target) {
1060   case GL_PROXY_TEXTURE_1D:
1061      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1062      if (width < 2 * border || width > 2 + maxSize ||
1063          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1064           width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
1065          level >= ctx->Const.MaxTextureLevels) {
1066         /* bad width or level */
1067         return GL_FALSE;
1068      }
1069      return GL_TRUE;
1070   case GL_PROXY_TEXTURE_2D:
1071      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1072      if (width < 2 * border || width > 2 + maxSize ||
1073          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1074           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1075          height < 2 * border || height > 2 + maxSize ||
1076          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1077           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1078          level >= ctx->Const.MaxTextureLevels) {
1079         /* bad width or height or level */
1080         return GL_FALSE;
1081      }
1082      return GL_TRUE;
1083   case GL_PROXY_TEXTURE_3D:
1084      maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1085      if (width < 2 * border || width > 2 + maxSize ||
1086          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1087           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1088          height < 2 * border || height > 2 + maxSize ||
1089          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1090           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1091          depth < 2 * border || depth > 2 + maxSize ||
1092          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1093           depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
1094          level >= ctx->Const.Max3DTextureLevels) {
1095         /* bad width or height or depth or level */
1096         return GL_FALSE;
1097      }
1098      return GL_TRUE;
1099   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1100      if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
1101          height < 0 || height > ctx->Const.MaxTextureRectSize ||
1102          level != 0) {
1103         /* bad width or height or level */
1104         return GL_FALSE;
1105      }
1106      return GL_TRUE;
1107   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1108      maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1109      if (width < 2 * border || width > 2 + maxSize ||
1110          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1111           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1112          height < 2 * border || height > 2 + maxSize ||
1113          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1114           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1115          level >= ctx->Const.MaxCubeTextureLevels) {
1116         /* bad width or height */
1117         return GL_FALSE;
1118      }
1119      return GL_TRUE;
1120   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1121      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1122      if (width < 2 * border || width > 2 + maxSize ||
1123          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1124           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1125          level >= ctx->Const.MaxTextureLevels) {
1126         /* bad width or level */
1127         return GL_FALSE;
1128      }
1129
1130      if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
1131         return GL_FALSE;
1132      }
1133      return GL_TRUE;
1134   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1135      maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1136      if (width < 2 * border || width > 2 + maxSize ||
1137          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1138           width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1139          height < 2 * border || height > 2 + maxSize ||
1140          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1141           height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1142          level >= ctx->Const.MaxTextureLevels) {
1143         /* bad width or height or level */
1144         return GL_FALSE;
1145      }
1146      if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
1147         return GL_FALSE;
1148      }
1149      return GL_TRUE;
1150   default:
1151      _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1152      return GL_FALSE;
1153   }
1154}
1155
1156
1157/**
1158 * Helper function to determine whether a target supports compressed textures
1159 */
1160static GLboolean
1161target_can_be_compressed(GLcontext *ctx, GLenum target)
1162{
1163   return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
1164           || ((ctx->Extensions.ARB_texture_cube_map &&
1165                (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1166                 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1167                  target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
1168           || ((ctx->Extensions.MESA_texture_array &&
1169                ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
1170                 (target == GL_TEXTURE_2D_ARRAY_EXT)))));
1171}
1172
1173
1174/**
1175 * Test the glTexImage[123]D() parameters for errors.
1176 *
1177 * \param ctx GL context.
1178 * \param target texture target given by the user.
1179 * \param level image level given by the user.
1180 * \param internalFormat internal format given by the user.
1181 * \param format pixel data format given by the user.
1182 * \param type pixel data type given by the user.
1183 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1184 * \param width image width given by the user.
1185 * \param height image height given by the user.
1186 * \param depth image depth given by the user.
1187 * \param border image border given by the user.
1188 *
1189 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1190 *
1191 * Verifies each of the parameters against the constants specified in
1192 * __GLcontextRec::Const and the supported extensions, and according to the
1193 * OpenGL specification.
1194 */
1195static GLboolean
1196texture_error_check( GLcontext *ctx, GLenum target,
1197                     GLint level, GLint internalFormat,
1198                     GLenum format, GLenum type,
1199                     GLuint dimensions,
1200                     GLint width, GLint height,
1201                     GLint depth, GLint border )
1202{
1203   const GLboolean isProxy = _mesa_is_proxy_texture(target);
1204   GLboolean sizeOK = GL_TRUE;
1205   GLboolean colorFormat, indexFormat;
1206   GLenum proxy_target;
1207
1208   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1209   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1210      if (!isProxy) {
1211         _mesa_error(ctx, GL_INVALID_VALUE,
1212                     "glTexImage%dD(level=%d)", dimensions, level);
1213      }
1214      return GL_TRUE;
1215   }
1216
1217   /* Check border */
1218   if (border < 0 || border > 1 ||
1219       ((target == GL_TEXTURE_RECTANGLE_NV ||
1220         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1221      if (!isProxy) {
1222         _mesa_error(ctx, GL_INVALID_VALUE,
1223                     "glTexImage%dD(border=%d)", dimensions, border);
1224      }
1225      return GL_TRUE;
1226   }
1227
1228   if (width < 0 || height < 0 || depth < 0) {
1229      if (!isProxy) {
1230         _mesa_error(ctx, GL_INVALID_VALUE,
1231                     "glTexImage%dD(width, height or depth < 0)", dimensions);
1232      }
1233      return GL_TRUE;
1234   }
1235
1236   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1237    * level, width, height and depth.
1238    */
1239   if (dimensions == 1) {
1240      if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1241         proxy_target = GL_PROXY_TEXTURE_1D;
1242         height = 1;
1243         depth = 1;
1244      }
1245      else {
1246         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1247         return GL_TRUE;
1248      }
1249   }
1250   else if (dimensions == 2) {
1251      depth = 1;
1252      if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1253         proxy_target = GL_PROXY_TEXTURE_2D;
1254      }
1255      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1256               (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1257                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1258         if (!ctx->Extensions.ARB_texture_cube_map) {
1259            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1260            return GL_TRUE;
1261         }
1262         proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
1263         sizeOK = (width == height);
1264      }
1265      else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1266               target == GL_TEXTURE_RECTANGLE_NV) {
1267         if (!ctx->Extensions.NV_texture_rectangle) {
1268            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1269            return GL_TRUE;
1270         }
1271         proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
1272      }
1273      else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
1274               target == GL_TEXTURE_1D_ARRAY_EXT) {
1275         proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
1276      }
1277      else {
1278         _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1279         return GL_TRUE;
1280      }
1281   }
1282   else if (dimensions == 3) {
1283      if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1284         proxy_target = GL_PROXY_TEXTURE_3D;
1285      }
1286      else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
1287               target == GL_TEXTURE_2D_ARRAY_EXT) {
1288         proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
1289      }
1290      else {
1291         _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1292         return GL_TRUE;
1293      }
1294   }
1295   else {
1296      _mesa_problem( ctx, "bad dims in texture_error_check" );
1297      return GL_TRUE;
1298   }
1299
1300   sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
1301                                                    internalFormat, format,
1302                                                    type, width, height,
1303                                                    depth, border);
1304   if (!sizeOK) {
1305      if (!isProxy) {
1306         _mesa_error(ctx, GL_INVALID_VALUE,
1307                     "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1308                     dimensions, level, width, height, depth);
1309      }
1310      return GL_TRUE;
1311   }
1312
1313   /* Check internalFormat */
1314   if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1315      if (!isProxy) {
1316         _mesa_error(ctx, GL_INVALID_VALUE,
1317                     "glTexImage%dD(internalFormat=0x%x)",
1318                     dimensions, internalFormat);
1319      }
1320      return GL_TRUE;
1321   }
1322
1323   /* Check incoming image format and type */
1324   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1325      /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1326       * is a type/format mismatch.  See 1.2 spec page 94, sec 3.6.4.
1327       */
1328      if (!isProxy) {
1329         _mesa_error(ctx, GL_INVALID_OPERATION,
1330                     "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
1331                     dimensions, format, type);
1332      }
1333      return GL_TRUE;
1334   }
1335
1336   /* make sure internal format and format basically agree */
1337   colorFormat = _mesa_is_color_format(format);
1338   indexFormat = _mesa_is_index_format(format);
1339   if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1340       (_mesa_is_index_format(internalFormat) && !indexFormat) ||
1341       (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
1342       (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
1343       (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
1344       (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
1345      if (!isProxy)
1346         _mesa_error(ctx, GL_INVALID_OPERATION,
1347                     "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
1348                     dimensions, internalFormat, format);
1349      return GL_TRUE;
1350   }
1351
1352   /* additional checks for ycbcr textures */
1353   if (internalFormat == GL_YCBCR_MESA) {
1354      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1355      if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1356          type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1357         char message[100];
1358         _mesa_sprintf(message,
1359                 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1360         _mesa_error(ctx, GL_INVALID_ENUM, message);
1361         return GL_TRUE; /* error */
1362      }
1363      if (target != GL_TEXTURE_2D &&
1364          target != GL_PROXY_TEXTURE_2D &&
1365          target != GL_TEXTURE_RECTANGLE_NV &&
1366          target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1367         if (!isProxy)
1368            _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1369         return GL_TRUE;
1370      }
1371      if (border != 0) {
1372         if (!isProxy) {
1373            char message[100];
1374            _mesa_sprintf(message,
1375                    "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1376                    dimensions, border);
1377            _mesa_error(ctx, GL_INVALID_VALUE, message);
1378         }
1379         return GL_TRUE;
1380      }
1381   }
1382
1383   /* additional checks for depth textures */
1384   if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1385      /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1386      if (target != GL_TEXTURE_1D &&
1387          target != GL_PROXY_TEXTURE_1D &&
1388          target != GL_TEXTURE_2D &&
1389          target != GL_PROXY_TEXTURE_2D &&
1390          target != GL_TEXTURE_RECTANGLE_ARB &&
1391          target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
1392         if (!isProxy)
1393            _mesa_error(ctx, GL_INVALID_ENUM,
1394                        "glTexImage(target/internalFormat)");
1395         return GL_TRUE;
1396      }
1397   }
1398
1399   /* additional checks for compressed textures */
1400   if (is_compressed_format(ctx, internalFormat)) {
1401      if (!target_can_be_compressed(ctx, target) && !isProxy) {
1402         _mesa_error(ctx, GL_INVALID_ENUM,
1403                     "glTexImage%d(target)", dimensions);
1404         return GL_TRUE;
1405      }
1406      if (border != 0) {
1407         if (!isProxy) {
1408            _mesa_error(ctx, GL_INVALID_OPERATION,
1409                        "glTexImage%D(border!=0)", dimensions);
1410         }
1411         return GL_TRUE;
1412      }
1413   }
1414
1415   /* if we get here, the parameters are OK */
1416   return GL_FALSE;
1417}
1418
1419
1420/**
1421 * Test glTexSubImage[123]D() parameters for errors.
1422 *
1423 * \param ctx GL context.
1424 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1425 * \param target texture target given by the user.
1426 * \param level image level given by the user.
1427 * \param xoffset sub-image x offset given by the user.
1428 * \param yoffset sub-image y offset given by the user.
1429 * \param zoffset sub-image z offset given by the user.
1430 * \param format pixel data format given by the user.
1431 * \param type pixel data type given by the user.
1432 * \param width image width given by the user.
1433 * \param height image height given by the user.
1434 * \param depth image depth given by the user.
1435 *
1436 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1437 *
1438 * Verifies each of the parameters against the constants specified in
1439 * __GLcontextRec::Const and the supported extensions, and according to the
1440 * OpenGL specification.
1441 */
1442static GLboolean
1443subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1444                        GLenum target, GLint level,
1445                        GLint xoffset, GLint yoffset, GLint zoffset,
1446                        GLint width, GLint height, GLint depth,
1447                        GLenum format, GLenum type )
1448{
1449   /* Check target */
1450   if (dimensions == 1) {
1451      if (target != GL_TEXTURE_1D) {
1452         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1453         return GL_TRUE;
1454      }
1455   }
1456   else if (dimensions == 2) {
1457      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1458          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1459         if (!ctx->Extensions.ARB_texture_cube_map) {
1460            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1461            return GL_TRUE;
1462         }
1463      }
1464      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1465         if (!ctx->Extensions.NV_texture_rectangle) {
1466            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1467            return GL_TRUE;
1468         }
1469      }
1470      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1471        if (!ctx->Extensions.MESA_texture_array) {
1472           _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1473           return GL_TRUE;
1474        }
1475      }
1476      else if (target != GL_TEXTURE_2D) {
1477         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1478         return GL_TRUE;
1479      }
1480   }
1481   else if (dimensions == 3) {
1482      if (target == GL_TEXTURE_2D_ARRAY_EXT) {
1483         if (!ctx->Extensions.MESA_texture_array) {
1484            _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1485            return GL_TRUE;
1486         }
1487      }
1488      else if (target != GL_TEXTURE_3D) {
1489         _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1490         return GL_TRUE;
1491      }
1492   }
1493   else {
1494      _mesa_problem( ctx, "invalid dims in texture_error_check" );
1495      return GL_TRUE;
1496   }
1497
1498   /* Basic level check */
1499   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1500      _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1501      return GL_TRUE;
1502   }
1503
1504   if (width < 0) {
1505      _mesa_error(ctx, GL_INVALID_VALUE,
1506                  "glTexSubImage%dD(width=%d)", dimensions, width);
1507      return GL_TRUE;
1508   }
1509   if (height < 0 && dimensions > 1) {
1510      _mesa_error(ctx, GL_INVALID_VALUE,
1511                  "glTexSubImage%dD(height=%d)", dimensions, height);
1512      return GL_TRUE;
1513   }
1514   if (depth < 0 && dimensions > 2) {
1515      _mesa_error(ctx, GL_INVALID_VALUE,
1516                  "glTexSubImage%dD(depth=%d)", dimensions, depth);
1517      return GL_TRUE;
1518   }
1519
1520   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1521      _mesa_error(ctx, GL_INVALID_ENUM,
1522                  "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
1523                  dimensions, format, type);
1524      return GL_TRUE;
1525   }
1526
1527   return GL_FALSE;
1528}
1529
1530static GLboolean
1531subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
1532			 GLenum target, GLint level,
1533			 GLint xoffset, GLint yoffset, GLint zoffset,
1534			 GLint width, GLint height, GLint depth,
1535			 GLenum format, GLenum type,
1536			 const struct gl_texture_image *destTex )
1537{
1538   if (!destTex) {
1539      /* undefined image level */
1540      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
1541      return GL_TRUE;
1542   }
1543
1544   if (xoffset < -((GLint)destTex->Border)) {
1545      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
1546                  dimensions);
1547      return GL_TRUE;
1548   }
1549   if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1550      _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
1551                  dimensions);
1552      return GL_TRUE;
1553   }
1554   if (dimensions > 1) {
1555      if (yoffset < -((GLint)destTex->Border)) {
1556         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
1557                     dimensions);
1558         return GL_TRUE;
1559      }
1560      if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1561         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
1562                     dimensions);
1563         return GL_TRUE;
1564      }
1565   }
1566   if (dimensions > 2) {
1567      if (zoffset < -((GLint)destTex->Border)) {
1568         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1569         return GL_TRUE;
1570      }
1571      if (zoffset + depth  > (GLint) (destTex->Depth + destTex->Border)) {
1572         _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1573         return GL_TRUE;
1574      }
1575   }
1576
1577#if FEATURE_EXT_texture_sRGB
1578   if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
1579       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
1580       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
1581       destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
1582      if ((width & 0x3) || (height & 0x3) ||
1583          (xoffset & 0x3) || (yoffset & 0x3))
1584         _mesa_error(ctx, GL_INVALID_OPERATION,
1585                     "glTexSubImage%dD(size or offset not multiple of 4)",
1586                     dimensions);
1587      return GL_TRUE;
1588   }
1589#endif
1590
1591   if (_mesa_is_format_compressed(destTex->TexFormat)) {
1592      if (!target_can_be_compressed(ctx, target)) {
1593         _mesa_error(ctx, GL_INVALID_ENUM,
1594                     "glTexSubImage%D(target)", dimensions);
1595         return GL_TRUE;
1596      }
1597      /* offset must be multiple of 4 */
1598      if ((xoffset & 3) || (yoffset & 3)) {
1599         _mesa_error(ctx, GL_INVALID_OPERATION,
1600                     "glTexSubImage%D(xoffset or yoffset)", dimensions);
1601         return GL_TRUE;
1602      }
1603      /* size must be multiple of 4 or equal to whole texture size */
1604      if ((width & 3) && (GLuint) width != destTex->Width) {
1605         _mesa_error(ctx, GL_INVALID_OPERATION,
1606                     "glTexSubImage%D(width)", dimensions);
1607         return GL_TRUE;
1608      }
1609      if ((height & 3) && (GLuint) height != destTex->Height) {
1610         _mesa_error(ctx, GL_INVALID_OPERATION,
1611                     "glTexSubImage%D(width)", dimensions);
1612         return GL_TRUE;
1613      }
1614   }
1615
1616   return GL_FALSE;
1617}
1618
1619
1620/**
1621 * Test glCopyTexImage[12]D() parameters for errors.
1622 *
1623 * \param ctx GL context.
1624 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1625 * \param target texture target given by the user.
1626 * \param level image level given by the user.
1627 * \param internalFormat internal format given by the user.
1628 * \param width image width given by the user.
1629 * \param height image height given by the user.
1630 * \param border texture border.
1631 *
1632 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1633 *
1634 * Verifies each of the parameters against the constants specified in
1635 * __GLcontextRec::Const and the supported extensions, and according to the
1636 * OpenGL specification.
1637 */
1638static GLboolean
1639copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1640                         GLenum target, GLint level, GLint internalFormat,
1641                         GLint width, GLint height, GLint border )
1642{
1643   GLenum type;
1644   GLboolean sizeOK;
1645   GLint format;
1646
1647   /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1648   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1649      _mesa_error(ctx, GL_INVALID_VALUE,
1650                  "glCopyTexImage%dD(level=%d)", dimensions, level);
1651      return GL_TRUE;
1652   }
1653
1654   /* Check that the source buffer is complete */
1655   if (ctx->ReadBuffer->Name) {
1656      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1657      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1658         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1659                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1660         return GL_TRUE;
1661      }
1662   }
1663
1664   /* Check border */
1665   if (border < 0 || border > 1 ||
1666       ((target == GL_TEXTURE_RECTANGLE_NV ||
1667         target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1668      return GL_TRUE;
1669   }
1670
1671   format = _mesa_base_tex_format(ctx, internalFormat);
1672   if (format < 0) {
1673      _mesa_error(ctx, GL_INVALID_VALUE,
1674                  "glCopyTexImage%dD(internalFormat)", dimensions);
1675      return GL_TRUE;
1676   }
1677
1678   if (!_mesa_source_buffer_exists(ctx, format)) {
1679      _mesa_error(ctx, GL_INVALID_OPERATION,
1680                  "glCopyTexImage%dD(missing readbuffer)", dimensions);
1681      return GL_TRUE;
1682   }
1683
1684   /* NOTE: the format and type aren't really significant for
1685    * TestProxyTexImage().  Only the internalformat really matters.
1686    */
1687   type = GL_FLOAT;
1688
1689   /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1690    * level, width, height and depth.
1691    */
1692   if (dimensions == 1) {
1693      if (target == GL_TEXTURE_1D) {
1694         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1695                                                level, internalFormat,
1696                                                format, type,
1697                                                width, 1, 1, border);
1698      }
1699      else {
1700         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1701         return GL_TRUE;
1702      }
1703   }
1704   else if (dimensions == 2) {
1705      if (target == GL_TEXTURE_2D) {
1706         sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1707                                                level, internalFormat,
1708                                                format, type,
1709                                                width, height, 1, border);
1710      }
1711      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1712               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1713         if (!ctx->Extensions.ARB_texture_cube_map) {
1714            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1715            return GL_TRUE;
1716         }
1717         sizeOK = (width == height) &&
1718            ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1719                                          level, internalFormat, format, type,
1720                                          width, height, 1, border);
1721      }
1722      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1723         if (!ctx->Extensions.NV_texture_rectangle) {
1724            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1725            return GL_TRUE;
1726         }
1727         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1728                                                GL_PROXY_TEXTURE_RECTANGLE_NV,
1729                                                level, internalFormat,
1730                                                format, type,
1731                                                width, height, 1, border);
1732      }
1733      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1734         if (!ctx->Extensions.MESA_texture_array) {
1735            _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
1736            return GL_TRUE;
1737         }
1738         sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1739                                                GL_PROXY_TEXTURE_1D_ARRAY_EXT,
1740                                                level, internalFormat,
1741                                                format, type,
1742                                                width, height, 1, border);
1743      }
1744      else {
1745         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1746         return GL_TRUE;
1747      }
1748   }
1749   else {
1750      _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1751      return GL_TRUE;
1752   }
1753
1754   if (!sizeOK) {
1755      if (dimensions == 1) {
1756         _mesa_error(ctx, GL_INVALID_VALUE,
1757                     "glCopyTexImage1D(width=%d)", width);
1758      }
1759      else {
1760         ASSERT(dimensions == 2);
1761         _mesa_error(ctx, GL_INVALID_VALUE,
1762                     "glCopyTexImage2D(width=%d, height=%d)", width, height);
1763      }
1764      return GL_TRUE;
1765   }
1766
1767   if (is_compressed_format(ctx, internalFormat)) {
1768      if (!target_can_be_compressed(ctx, target)) {
1769         _mesa_error(ctx, GL_INVALID_ENUM,
1770                     "glCopyTexImage%d(target)", dimensions);
1771         return GL_TRUE;
1772      }
1773      if (border != 0) {
1774         _mesa_error(ctx, GL_INVALID_OPERATION,
1775                     "glCopyTexImage%D(border!=0)", dimensions);
1776         return GL_TRUE;
1777      }
1778   }
1779   else if (_mesa_is_depth_format(internalFormat)) {
1780      /* make sure we have depth/stencil buffers */
1781      if (!ctx->ReadBuffer->_DepthBuffer) {
1782         _mesa_error(ctx, GL_INVALID_OPERATION,
1783                     "glCopyTexImage%D(no depth)", dimensions);
1784         return GL_TRUE;
1785      }
1786   }
1787   else if (_mesa_is_depthstencil_format(internalFormat)) {
1788      /* make sure we have depth/stencil buffers */
1789      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1790         _mesa_error(ctx, GL_INVALID_OPERATION,
1791                     "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
1792         return GL_TRUE;
1793      }
1794   }
1795
1796   /* if we get here, the parameters are OK */
1797   return GL_FALSE;
1798}
1799
1800
1801/**
1802 * Test glCopyTexSubImage[12]D() parameters for errors.
1803 * Note that this is the first part of error checking.
1804 * See also copytexsubimage_error_check2() below for the second part.
1805 *
1806 * \param ctx GL context.
1807 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1808 * \param target texture target given by the user.
1809 * \param level image level given by the user.
1810 *
1811 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1812 */
1813static GLboolean
1814copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
1815                              GLenum target, GLint level)
1816{
1817   /* Check that the source buffer is complete */
1818   if (ctx->ReadBuffer->Name) {
1819      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1820      if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1821         _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1822                     "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1823         return GL_TRUE;
1824      }
1825   }
1826
1827   /* Check target */
1828   if (dimensions == 1) {
1829      if (target != GL_TEXTURE_1D) {
1830         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1831         return GL_TRUE;
1832      }
1833   }
1834   else if (dimensions == 2) {
1835      if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1836          target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1837         if (!ctx->Extensions.ARB_texture_cube_map) {
1838            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1839            return GL_TRUE;
1840         }
1841      }
1842      else if (target == GL_TEXTURE_RECTANGLE_NV) {
1843         if (!ctx->Extensions.NV_texture_rectangle) {
1844            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1845            return GL_TRUE;
1846         }
1847      }
1848      else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1849         if (!ctx->Extensions.MESA_texture_array) {
1850            _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1851            return GL_TRUE;
1852         }
1853      }
1854      else if (target != GL_TEXTURE_2D) {
1855         _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1856         return GL_TRUE;
1857      }
1858   }
1859   else if (dimensions == 3) {
1860      if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
1861	   (!ctx->Extensions.MESA_texture_array))
1862	  && (target != GL_TEXTURE_3D)) {
1863	 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1864	 return GL_TRUE;
1865      }
1866   }
1867
1868   /* Check level */
1869   if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1870      _mesa_error(ctx, GL_INVALID_VALUE,
1871                  "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1872      return GL_TRUE;
1873   }
1874
1875   return GL_FALSE;
1876}
1877
1878
1879/**
1880 * Second part of error checking for glCopyTexSubImage[12]D().
1881 * \param xoffset sub-image x offset given by the user.
1882 * \param yoffset sub-image y offset given by the user.
1883 * \param zoffset sub-image z offset given by the user.
1884 * \param width image width given by the user.
1885 * \param height image height given by the user.
1886 */
1887static GLboolean
1888copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
1889			      GLenum target, GLint level,
1890			      GLint xoffset, GLint yoffset, GLint zoffset,
1891			      GLsizei width, GLsizei height,
1892			      const struct gl_texture_image *teximage )
1893{
1894   /* check that dest tex image exists */
1895   if (!teximage) {
1896      _mesa_error(ctx, GL_INVALID_OPERATION,
1897                  "glCopyTexSubImage%dD(undefined texture level: %d)",
1898                  dimensions, level);
1899      return GL_TRUE;
1900   }
1901
1902   /* Check size */
1903   if (width < 0) {
1904      _mesa_error(ctx, GL_INVALID_VALUE,
1905                  "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1906      return GL_TRUE;
1907   }
1908   if (dimensions > 1 && height < 0) {
1909      _mesa_error(ctx, GL_INVALID_VALUE,
1910                  "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1911      return GL_TRUE;
1912   }
1913
1914   /* check x/y offsets */
1915   if (xoffset < -((GLint)teximage->Border)) {
1916      _mesa_error(ctx, GL_INVALID_VALUE,
1917                  "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1918      return GL_TRUE;
1919   }
1920   if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1921      _mesa_error(ctx, GL_INVALID_VALUE,
1922                  "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1923      return GL_TRUE;
1924   }
1925   if (dimensions > 1) {
1926      if (yoffset < -((GLint)teximage->Border)) {
1927         _mesa_error(ctx, GL_INVALID_VALUE,
1928                     "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1929         return GL_TRUE;
1930      }
1931      /* NOTE: we're adding the border here, not subtracting! */
1932      if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1933         _mesa_error(ctx, GL_INVALID_VALUE,
1934                     "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1935         return GL_TRUE;
1936      }
1937   }
1938
1939   /* check z offset */
1940   if (dimensions > 2) {
1941      if (zoffset < -((GLint)teximage->Border)) {
1942         _mesa_error(ctx, GL_INVALID_VALUE,
1943                     "glCopyTexSubImage%dD(zoffset)", dimensions);
1944         return GL_TRUE;
1945      }
1946      if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1947         _mesa_error(ctx, GL_INVALID_VALUE,
1948                     "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1949         return GL_TRUE;
1950      }
1951   }
1952
1953   if (_mesa_is_format_compressed(teximage->TexFormat)) {
1954      if (!target_can_be_compressed(ctx, target)) {
1955         _mesa_error(ctx, GL_INVALID_ENUM,
1956                     "glCopyTexSubImage%d(target)", dimensions);
1957         return GL_TRUE;
1958      }
1959      /* offset must be multiple of 4 */
1960      if ((xoffset & 3) || (yoffset & 3)) {
1961         _mesa_error(ctx, GL_INVALID_VALUE,
1962                     "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
1963         return GL_TRUE;
1964      }
1965      /* size must be multiple of 4 */
1966      if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
1967         _mesa_error(ctx, GL_INVALID_VALUE,
1968                     "glCopyTexSubImage%D(width)", dimensions);
1969         return GL_TRUE;
1970      }
1971      if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
1972         _mesa_error(ctx, GL_INVALID_VALUE,
1973                     "glCopyTexSubImage%D(height)", dimensions);
1974         return GL_TRUE;
1975      }
1976   }
1977
1978   if (teximage->InternalFormat == GL_YCBCR_MESA) {
1979      _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
1980      return GL_TRUE;
1981   }
1982
1983   if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
1984      _mesa_error(ctx, GL_INVALID_OPERATION,
1985                  "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
1986                  dimensions, teximage->_BaseFormat);
1987      return GL_TRUE;
1988   }
1989
1990   if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
1991      if (!ctx->ReadBuffer->_DepthBuffer) {
1992         _mesa_error(ctx, GL_INVALID_OPERATION,
1993                     "glCopyTexSubImage%D(no depth buffer)",
1994                     dimensions);
1995         return GL_TRUE;
1996      }
1997   }
1998   else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
1999      if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
2000         _mesa_error(ctx, GL_INVALID_OPERATION,
2001                     "glCopyTexSubImage%D(no depth/stencil buffer)",
2002                     dimensions);
2003         return GL_TRUE;
2004      }
2005   }
2006
2007   /* if we get here, the parameters are OK */
2008   return GL_FALSE;
2009}
2010
2011
2012/** Callback info for walking over FBO hash table */
2013struct cb_info
2014{
2015   GLcontext *ctx;
2016   struct gl_texture_object *texObj;
2017   GLuint level, face;
2018};
2019
2020
2021/**
2022 * Check render to texture callback.  Called from _mesa_HashWalk().
2023 */
2024static void
2025check_rtt_cb(GLuint key, void *data, void *userData)
2026{
2027   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2028   const struct cb_info *info = (struct cb_info *) userData;
2029   GLcontext *ctx = info->ctx;
2030   const struct gl_texture_object *texObj = info->texObj;
2031   const GLuint level = info->level, face = info->face;
2032
2033   /* If this is a user-created FBO */
2034   if (fb->Name) {
2035      GLuint i;
2036      /* check if any of the FBO's attachments point to 'texObj' */
2037      for (i = 0; i < BUFFER_COUNT; i++) {
2038         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2039         if (att->Type == GL_TEXTURE &&
2040             att->Texture == texObj &&
2041             att->TextureLevel == level &&
2042             att->CubeMapFace == face) {
2043            ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
2044            /* Tell driver about the new renderbuffer texture */
2045            ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
2046            /* Mark fb status as indeterminate to force re-validation */
2047            fb->_Status = 0;
2048         }
2049      }
2050   }
2051}
2052
2053
2054/**
2055 * When a texture image is specified we have to check if it's bound to
2056 * any framebuffer objects (render to texture) in order to detect changes
2057 * in size or format since that effects FBO completeness.
2058 * Any FBOs rendering into the texture must be re-validated.
2059 */
2060static void
2061update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
2062                   GLuint face, GLuint level)
2063{
2064   /* Only check this texture if it's been marked as RenderToTexture */
2065   if (texObj->_RenderToTexture) {
2066      struct cb_info info;
2067      info.ctx = ctx;
2068      info.texObj = texObj;
2069      info.level = level;
2070      info.face = face;
2071      _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
2072   }
2073}
2074
2075
2076/**
2077 * If the texture object's GenerateMipmap flag is set and we've
2078 * changed the texture base level image, regenerate the rest of the
2079 * mipmap levels now.
2080 */
2081static INLINE void
2082check_gen_mipmap(GLcontext *ctx, GLenum target,
2083                 struct gl_texture_object *texObj, GLint level)
2084{
2085   ASSERT(target != GL_TEXTURE_CUBE_MAP);
2086   if (texObj->GenerateMipmap && level == texObj->BaseLevel) {
2087      ASSERT(ctx->Driver.GenerateMipmap);
2088      ctx->Driver.GenerateMipmap(ctx, target, texObj);
2089   }
2090}
2091
2092
2093/** Debug helper: override the user-requested internal format */
2094static GLenum
2095override_internal_format(GLenum internalFormat, GLint width, GLint height)
2096{
2097#if 0
2098   if (internalFormat == GL_RGBA16F_ARB ||
2099       internalFormat == GL_RGBA32F_ARB) {
2100      printf("Convert rgba float tex to int %d x %d\n", width, height);
2101      return GL_RGBA;
2102   }
2103   else if (internalFormat == GL_RGB16F_ARB ||
2104            internalFormat == GL_RGB32F_ARB) {
2105      printf("Convert rgb float tex to int %d x %d\n", width, height);
2106      return GL_RGB;
2107   }
2108   else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
2109            internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
2110      printf("Convert luminance float tex to int %d x %d\n", width, height);
2111      return GL_LUMINANCE_ALPHA;
2112   }
2113   else if (internalFormat == GL_LUMINANCE16F_ARB ||
2114            internalFormat == GL_LUMINANCE32F_ARB) {
2115      printf("Convert luminance float tex to int %d x %d\n", width, height);
2116      return GL_LUMINANCE;
2117   }
2118   else if (internalFormat == GL_ALPHA16F_ARB ||
2119            internalFormat == GL_ALPHA32F_ARB) {
2120      printf("Convert luminance float tex to int %d x %d\n", width, height);
2121      return GL_ALPHA;
2122   }
2123   /*
2124   else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
2125      internalFormat = GL_RGBA;
2126   }
2127   */
2128   else {
2129      return internalFormat;
2130   }
2131#else
2132   return internalFormat;
2133#endif
2134}
2135
2136
2137/*
2138 * Called from the API.  Note that width includes the border.
2139 */
2140void GLAPIENTRY
2141_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2142                  GLsizei width, GLint border, GLenum format,
2143                  GLenum type, const GLvoid *pixels )
2144{
2145   GLsizei postConvWidth = width;
2146   GET_CURRENT_CONTEXT(ctx);
2147   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2148
2149   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2150      _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n",
2151                  _mesa_lookup_enum_by_nr(target), level,
2152                  _mesa_lookup_enum_by_nr(internalFormat), width, border,
2153                  _mesa_lookup_enum_by_nr(format),
2154                  _mesa_lookup_enum_by_nr(type), pixels);
2155
2156   internalFormat = override_internal_format(internalFormat, width, 1);
2157
2158#if FEATURE_convolve
2159   if (_mesa_is_color_format(internalFormat)) {
2160      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2161   }
2162#endif
2163
2164   if (target == GL_TEXTURE_1D) {
2165      /* non-proxy target */
2166      struct gl_texture_unit *texUnit;
2167      struct gl_texture_object *texObj;
2168      struct gl_texture_image *texImage;
2169      const GLuint face = _mesa_tex_target_to_face(target);
2170
2171      if (texture_error_check(ctx, target, level, internalFormat,
2172                              format, type, 1, postConvWidth, 1, 1, border)) {
2173         return;   /* error was recorded */
2174      }
2175
2176      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2177	 _mesa_update_state(ctx);
2178
2179      texUnit = _mesa_get_current_tex_unit(ctx);
2180      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2181      _mesa_lock_texture(ctx, texObj);
2182      {
2183	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2184	 if (!texImage) {
2185	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2186	 }
2187         else {
2188            if (texImage->Data) {
2189               ctx->Driver.FreeTexImageData( ctx, texImage );
2190            }
2191
2192            ASSERT(texImage->Data == NULL);
2193
2194            clear_teximage_fields(texImage); /* not really needed, but helpful */
2195            _mesa_init_teximage_fields(ctx, target, texImage,
2196                                       postConvWidth, 1, 1,
2197                                       border, internalFormat);
2198
2199            /* Give the texture to the driver.  <pixels> may be null. */
2200            ASSERT(ctx->Driver.TexImage1D);
2201            ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
2202                                   width, border, format, type, pixels,
2203                                   &ctx->Unpack, texObj, texImage);
2204
2205            ASSERT(texImage->TexFormat);
2206
2207            _mesa_set_fetch_functions(texImage, 1);
2208
2209            check_gen_mipmap(ctx, target, texObj, level);
2210
2211            update_fbo_texture(ctx, texObj, face, level);
2212
2213            /* state update */
2214            texObj->_Complete = GL_FALSE;
2215            ctx->NewState |= _NEW_TEXTURE;
2216         }
2217      }
2218      _mesa_unlock_texture(ctx, texObj);
2219   }
2220   else if (target == GL_PROXY_TEXTURE_1D) {
2221      /* Proxy texture: check for errors and update proxy state */
2222      struct gl_texture_image *texImage;
2223      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2224      if (texture_error_check(ctx, target, level, internalFormat,
2225                              format, type, 1, postConvWidth, 1, 1, border)) {
2226         /* when error, clear all proxy texture image parameters */
2227         if (texImage)
2228            clear_teximage_fields(texImage);
2229      }
2230      else {
2231         /* no error, set the tex image parameters */
2232         ASSERT(texImage);
2233         _mesa_init_teximage_fields(ctx, target, texImage,
2234                                    postConvWidth, 1, 1,
2235                                    border, internalFormat);
2236         texImage->TexFormat =
2237            ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2238      }
2239   }
2240   else {
2241      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2242      return;
2243   }
2244}
2245
2246
2247void GLAPIENTRY
2248_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2249                  GLsizei width, GLsizei height, GLint border,
2250                  GLenum format, GLenum type,
2251                  const GLvoid *pixels )
2252{
2253   GLsizei postConvWidth = width, postConvHeight = height;
2254   GET_CURRENT_CONTEXT(ctx);
2255   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2256
2257   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2258      _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n",
2259                  _mesa_lookup_enum_by_nr(target), level,
2260                  _mesa_lookup_enum_by_nr(internalFormat), width, height,
2261                  border, _mesa_lookup_enum_by_nr(format),
2262                  _mesa_lookup_enum_by_nr(type), pixels);
2263
2264   internalFormat = override_internal_format(internalFormat, width, height);
2265
2266#if FEATURE_convolve
2267   if (_mesa_is_color_format(internalFormat)) {
2268      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2269					 &postConvHeight);
2270   }
2271#endif
2272
2273   if (target == GL_TEXTURE_2D ||
2274       (ctx->Extensions.ARB_texture_cube_map &&
2275        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2276        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2277       (ctx->Extensions.NV_texture_rectangle &&
2278        target == GL_TEXTURE_RECTANGLE_NV) ||
2279       (ctx->Extensions.MESA_texture_array &&
2280        target == GL_TEXTURE_1D_ARRAY_EXT)) {
2281      /* non-proxy target */
2282      struct gl_texture_unit *texUnit;
2283      struct gl_texture_object *texObj;
2284      struct gl_texture_image *texImage;
2285      const GLuint face = _mesa_tex_target_to_face(target);
2286
2287      if (texture_error_check(ctx, target, level, internalFormat,
2288                              format, type, 2, postConvWidth, postConvHeight,
2289                              1, border)) {
2290         return;   /* error was recorded */
2291      }
2292
2293      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2294	 _mesa_update_state(ctx);
2295
2296      texUnit = _mesa_get_current_tex_unit(ctx);
2297      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2298      _mesa_lock_texture(ctx, texObj);
2299      {
2300	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2301	 if (!texImage) {
2302	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2303	 }
2304         else {
2305            if (texImage->Data) {
2306               ctx->Driver.FreeTexImageData( ctx, texImage );
2307            }
2308
2309            ASSERT(texImage->Data == NULL);
2310            clear_teximage_fields(texImage); /* not really needed, but helpful */
2311            _mesa_init_teximage_fields(ctx, target, texImage,
2312                                       postConvWidth, postConvHeight, 1,
2313                                       border, internalFormat);
2314
2315            /* Give the texture to the driver.  <pixels> may be null. */
2316            ASSERT(ctx->Driver.TexImage2D);
2317            ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
2318                                   width, height, border, format, type,
2319                                   pixels, &ctx->Unpack, texObj, texImage);
2320
2321            ASSERT(texImage->TexFormat);
2322
2323            _mesa_set_fetch_functions(texImage, 2);
2324
2325            check_gen_mipmap(ctx, target, texObj, level);
2326
2327            update_fbo_texture(ctx, texObj, face, level);
2328
2329            /* state update */
2330            texObj->_Complete = GL_FALSE;
2331            ctx->NewState |= _NEW_TEXTURE;
2332         }
2333      }
2334      _mesa_unlock_texture(ctx, texObj);
2335   }
2336   else if (target == GL_PROXY_TEXTURE_2D ||
2337            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2338             ctx->Extensions.ARB_texture_cube_map) ||
2339            (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2340             ctx->Extensions.NV_texture_rectangle) ||
2341            (ctx->Extensions.MESA_texture_array &&
2342             target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
2343      /* Proxy texture: check for errors and update proxy state */
2344      struct gl_texture_image *texImage;
2345      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2346      if (texture_error_check(ctx, target, level, internalFormat,
2347                              format, type, 2, postConvWidth, postConvHeight,
2348                              1, border)) {
2349         /* when error, clear all proxy texture image parameters */
2350         if (texImage)
2351            clear_teximage_fields(texImage);
2352      }
2353      else {
2354         /* no error, set the tex image parameters */
2355         _mesa_init_teximage_fields(ctx, target, texImage,
2356                                    postConvWidth, postConvHeight, 1,
2357                                    border, internalFormat);
2358         texImage->TexFormat =
2359            ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2360      }
2361   }
2362   else {
2363      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2364      return;
2365   }
2366}
2367
2368
2369/*
2370 * Called by the API or display list executor.
2371 * Note that width and height include the border.
2372 */
2373void GLAPIENTRY
2374_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2375                  GLsizei width, GLsizei height, GLsizei depth,
2376                  GLint border, GLenum format, GLenum type,
2377                  const GLvoid *pixels )
2378{
2379   GET_CURRENT_CONTEXT(ctx);
2380   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2381
2382   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2383      _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n",
2384                  _mesa_lookup_enum_by_nr(target), level,
2385                  _mesa_lookup_enum_by_nr(internalFormat), width, height,
2386                  depth, border, _mesa_lookup_enum_by_nr(format),
2387                  _mesa_lookup_enum_by_nr(type), pixels);
2388
2389   internalFormat = override_internal_format(internalFormat, width, height);
2390
2391   if (target == GL_TEXTURE_3D ||
2392       (ctx->Extensions.MESA_texture_array &&
2393        target == GL_TEXTURE_2D_ARRAY_EXT)) {
2394      /* non-proxy target */
2395      struct gl_texture_unit *texUnit;
2396      struct gl_texture_object *texObj;
2397      struct gl_texture_image *texImage;
2398      const GLuint face = _mesa_tex_target_to_face(target);
2399
2400      if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2401                              format, type, 3, width, height, depth, border)) {
2402         return;   /* error was recorded */
2403      }
2404
2405      if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2406	 _mesa_update_state(ctx);
2407
2408      texUnit = _mesa_get_current_tex_unit(ctx);
2409      texObj = _mesa_select_tex_object(ctx, texUnit, target);
2410      _mesa_lock_texture(ctx, texObj);
2411      {
2412	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2413	 if (!texImage) {
2414	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2415	 }
2416         else {
2417            if (texImage->Data) {
2418               ctx->Driver.FreeTexImageData( ctx, texImage );
2419            }
2420
2421            ASSERT(texImage->Data == NULL);
2422            clear_teximage_fields(texImage); /* not really needed, but helpful */
2423            _mesa_init_teximage_fields(ctx, target, texImage,
2424                                       width, height, depth,
2425                                       border, internalFormat);
2426
2427            /* Give the texture to the driver.  <pixels> may be null. */
2428            ASSERT(ctx->Driver.TexImage3D);
2429            ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
2430                                   width, height, depth, border, format, type,
2431                                   pixels, &ctx->Unpack, texObj, texImage);
2432
2433            ASSERT(texImage->TexFormat);
2434
2435            _mesa_set_fetch_functions(texImage, 3);
2436
2437            check_gen_mipmap(ctx, target, texObj, level);
2438
2439            update_fbo_texture(ctx, texObj, face, level);
2440
2441            /* state update */
2442            texObj->_Complete = GL_FALSE;
2443            ctx->NewState |= _NEW_TEXTURE;
2444         }
2445      }
2446      _mesa_unlock_texture(ctx, texObj);
2447   }
2448   else if (target == GL_PROXY_TEXTURE_3D ||
2449       (ctx->Extensions.MESA_texture_array &&
2450        target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
2451      /* Proxy texture: check for errors and update proxy state */
2452      struct gl_texture_image *texImage;
2453      texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2454      if (texture_error_check(ctx, target, level, internalFormat,
2455                              format, type, 3, width, height, depth, border)) {
2456         /* when error, clear all proxy texture image parameters */
2457         if (texImage)
2458            clear_teximage_fields(texImage);
2459      }
2460      else {
2461         /* no error, set the tex image parameters */
2462         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2463                                    depth, border, internalFormat);
2464         texImage->TexFormat =
2465            ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2466      }
2467   }
2468   else {
2469      _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2470      return;
2471   }
2472}
2473
2474
2475void GLAPIENTRY
2476_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2477                     GLsizei width, GLsizei height, GLsizei depth,
2478                     GLint border, GLenum format, GLenum type,
2479                     const GLvoid *pixels )
2480{
2481   _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2482                    depth, border, format, type, pixels);
2483}
2484
2485
2486
2487void GLAPIENTRY
2488_mesa_TexSubImage1D( GLenum target, GLint level,
2489                     GLint xoffset, GLsizei width,
2490                     GLenum format, GLenum type,
2491                     const GLvoid *pixels )
2492{
2493   GLsizei postConvWidth = width;
2494   struct gl_texture_unit *texUnit;
2495   struct gl_texture_object *texObj;
2496   struct gl_texture_image *texImage = NULL;
2497   GET_CURRENT_CONTEXT(ctx);
2498   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2499
2500   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2501      _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n",
2502                  _mesa_lookup_enum_by_nr(target), level,
2503                  xoffset, width, _mesa_lookup_enum_by_nr(format),
2504                  _mesa_lookup_enum_by_nr(type), pixels);
2505
2506   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2507      _mesa_update_state(ctx);
2508
2509#if FEATURE_convolve
2510   /* XXX should test internal format */
2511   if (_mesa_is_color_format(format)) {
2512      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2513   }
2514#endif
2515
2516   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2517			       postConvWidth, 1, 1, format, type)) {
2518      return;   /* error was detected */
2519   }
2520
2521
2522   texUnit = _mesa_get_current_tex_unit(ctx);
2523   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2524   assert(texObj);
2525
2526   _mesa_lock_texture(ctx, texObj);
2527   {
2528      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2529
2530      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2531				  postConvWidth, 1, 1,
2532                                  format, type, texImage)) {
2533         /* error was recorded */
2534      }
2535      else if (width > 0) {
2536         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2537         xoffset += texImage->Border;
2538
2539         ASSERT(ctx->Driver.TexSubImage1D);
2540         ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
2541                                   format, type, pixels, &ctx->Unpack,
2542                                   texObj, texImage);
2543
2544         check_gen_mipmap(ctx, target, texObj, level);
2545
2546         ctx->NewState |= _NEW_TEXTURE;
2547      }
2548   }
2549   _mesa_unlock_texture(ctx, texObj);
2550}
2551
2552
2553void GLAPIENTRY
2554_mesa_TexSubImage2D( GLenum target, GLint level,
2555                     GLint xoffset, GLint yoffset,
2556                     GLsizei width, GLsizei height,
2557                     GLenum format, GLenum type,
2558                     const GLvoid *pixels )
2559{
2560   GLsizei postConvWidth = width, postConvHeight = height;
2561   struct gl_texture_unit *texUnit;
2562   struct gl_texture_object *texObj;
2563   struct gl_texture_image *texImage;
2564   GET_CURRENT_CONTEXT(ctx);
2565   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2566
2567   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2568      _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n",
2569                  _mesa_lookup_enum_by_nr(target), level,
2570                  xoffset, yoffset, width, height,
2571                  _mesa_lookup_enum_by_nr(format),
2572                  _mesa_lookup_enum_by_nr(type), pixels);
2573
2574   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2575      _mesa_update_state(ctx);
2576
2577#if FEATURE_convolve
2578   /* XXX should test internal format */
2579   if (_mesa_is_color_format(format)) {
2580      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2581                                         &postConvHeight);
2582   }
2583#endif
2584
2585   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2586			      postConvWidth, postConvHeight, 1, format, type)) {
2587      return;   /* error was detected */
2588   }
2589
2590   texUnit = _mesa_get_current_tex_unit(ctx);
2591   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2592
2593   _mesa_lock_texture(ctx, texObj);
2594   {
2595      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2596
2597      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2598				  postConvWidth, postConvHeight, 1,
2599                                  format, type, texImage)) {
2600	 /* error was recorded */
2601      }
2602      else if (width > 0 && height >= 0) {
2603         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2604         xoffset += texImage->Border;
2605         yoffset += texImage->Border;
2606
2607         ASSERT(ctx->Driver.TexSubImage2D);
2608         ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
2609                                   width, height, format, type, pixels,
2610                                   &ctx->Unpack, texObj, texImage);
2611
2612         check_gen_mipmap(ctx, target, texObj, level);
2613
2614         ctx->NewState |= _NEW_TEXTURE;
2615      }
2616   }
2617   _mesa_unlock_texture(ctx, texObj);
2618}
2619
2620
2621
2622void GLAPIENTRY
2623_mesa_TexSubImage3D( GLenum target, GLint level,
2624                     GLint xoffset, GLint yoffset, GLint zoffset,
2625                     GLsizei width, GLsizei height, GLsizei depth,
2626                     GLenum format, GLenum type,
2627                     const GLvoid *pixels )
2628{
2629   struct gl_texture_unit *texUnit;
2630   struct gl_texture_object *texObj;
2631   struct gl_texture_image *texImage;
2632   GET_CURRENT_CONTEXT(ctx);
2633   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2634
2635   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2636      _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n",
2637                  _mesa_lookup_enum_by_nr(target), level,
2638                  xoffset, yoffset, zoffset, width, height, depth,
2639                  _mesa_lookup_enum_by_nr(format),
2640                  _mesa_lookup_enum_by_nr(type), pixels);
2641
2642   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2643      _mesa_update_state(ctx);
2644
2645   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2646                              width, height, depth, format, type)) {
2647      return;   /* error was detected */
2648   }
2649
2650   texUnit = _mesa_get_current_tex_unit(ctx);
2651   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2652
2653   _mesa_lock_texture(ctx, texObj);
2654   {
2655      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2656
2657      if (subtexture_error_check2(ctx, 3, target, level,
2658                                  xoffset, yoffset, zoffset,
2659				  width, height, depth,
2660                                  format, type, texImage)) {
2661         /* error was recorded */
2662      }
2663      else if (width > 0 && height > 0 && height > 0) {
2664         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2665         xoffset += texImage->Border;
2666         yoffset += texImage->Border;
2667         zoffset += texImage->Border;
2668
2669         ASSERT(ctx->Driver.TexSubImage3D);
2670         ctx->Driver.TexSubImage3D(ctx, target, level,
2671                                   xoffset, yoffset, zoffset,
2672                                   width, height, depth,
2673                                   format, type, pixels,
2674                                   &ctx->Unpack, texObj, texImage );
2675
2676         check_gen_mipmap(ctx, target, texObj, level);
2677
2678         ctx->NewState |= _NEW_TEXTURE;
2679      }
2680   }
2681   _mesa_unlock_texture(ctx, texObj);
2682}
2683
2684
2685
2686void GLAPIENTRY
2687_mesa_CopyTexImage1D( GLenum target, GLint level,
2688                      GLenum internalFormat,
2689                      GLint x, GLint y,
2690                      GLsizei width, GLint border )
2691{
2692   struct gl_texture_unit *texUnit;
2693   struct gl_texture_object *texObj;
2694   struct gl_texture_image *texImage;
2695   GLsizei postConvWidth = width;
2696   const GLuint face = _mesa_tex_target_to_face(target);
2697   GET_CURRENT_CONTEXT(ctx);
2698   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2699
2700   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2701      _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n",
2702                  _mesa_lookup_enum_by_nr(target), level,
2703                  _mesa_lookup_enum_by_nr(internalFormat),
2704                  x, y, width, border);
2705
2706   if (ctx->NewState & NEW_COPY_TEX_STATE)
2707      _mesa_update_state(ctx);
2708
2709#if FEATURE_convolve
2710   if (_mesa_is_color_format(internalFormat)) {
2711      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2712   }
2713#endif
2714
2715   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2716                               postConvWidth, 1, border))
2717      return;
2718
2719   texUnit = _mesa_get_current_tex_unit(ctx);
2720   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2721
2722   _mesa_lock_texture(ctx, texObj);
2723   {
2724      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2725      if (!texImage) {
2726	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2727      }
2728      else {
2729         if (texImage->Data) {
2730            ctx->Driver.FreeTexImageData( ctx, texImage );
2731         }
2732
2733         ASSERT(texImage->Data == NULL);
2734
2735         clear_teximage_fields(texImage); /* not really needed, but helpful */
2736         _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2737                                    border, internalFormat);
2738
2739         ASSERT(ctx->Driver.CopyTexImage1D);
2740         ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
2741                                    x, y, width, border);
2742
2743         ASSERT(texImage->TexFormat);
2744
2745         _mesa_set_fetch_functions(texImage, 1);
2746
2747         check_gen_mipmap(ctx, target, texObj, level);
2748
2749         update_fbo_texture(ctx, texObj, face, level);
2750
2751         /* state update */
2752         texObj->_Complete = GL_FALSE;
2753         ctx->NewState |= _NEW_TEXTURE;
2754      }
2755   }
2756   _mesa_unlock_texture(ctx, texObj);
2757}
2758
2759
2760
2761void GLAPIENTRY
2762_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2763                      GLint x, GLint y, GLsizei width, GLsizei height,
2764                      GLint border )
2765{
2766   struct gl_texture_unit *texUnit;
2767   struct gl_texture_object *texObj;
2768   struct gl_texture_image *texImage;
2769   GLsizei postConvWidth = width, postConvHeight = height;
2770   const GLuint face = _mesa_tex_target_to_face(target);
2771   GET_CURRENT_CONTEXT(ctx);
2772   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2773
2774   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2775      _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n",
2776                  _mesa_lookup_enum_by_nr(target), level,
2777                  _mesa_lookup_enum_by_nr(internalFormat),
2778                  x, y, width, height, border);
2779
2780   if (ctx->NewState & NEW_COPY_TEX_STATE)
2781      _mesa_update_state(ctx);
2782
2783#if FEATURE_convolve
2784   if (_mesa_is_color_format(internalFormat)) {
2785      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2786                                         &postConvHeight);
2787   }
2788#endif
2789
2790   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2791                               postConvWidth, postConvHeight, border))
2792      return;
2793
2794   texUnit = _mesa_get_current_tex_unit(ctx);
2795   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2796
2797   _mesa_lock_texture(ctx, texObj);
2798   {
2799      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2800
2801      if (!texImage) {
2802	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2803      }
2804      else {
2805         if (texImage->Data) {
2806            ctx->Driver.FreeTexImageData( ctx, texImage );
2807         }
2808
2809         ASSERT(texImage->Data == NULL);
2810
2811         clear_teximage_fields(texImage); /* not really needed, but helpful */
2812         _mesa_init_teximage_fields(ctx, target, texImage,
2813                                    postConvWidth, postConvHeight, 1,
2814                                    border, internalFormat);
2815
2816         ASSERT(ctx->Driver.CopyTexImage2D);
2817         ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
2818                                    x, y, width, height, border);
2819
2820         ASSERT(texImage->TexFormat);
2821
2822         _mesa_set_fetch_functions(texImage, 2);
2823
2824         check_gen_mipmap(ctx, target, texObj, level);
2825
2826         update_fbo_texture(ctx, texObj, face, level);
2827
2828         /* state update */
2829         texObj->_Complete = GL_FALSE;
2830         ctx->NewState |= _NEW_TEXTURE;
2831      }
2832   }
2833   _mesa_unlock_texture(ctx, texObj);
2834}
2835
2836
2837void GLAPIENTRY
2838_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2839                         GLint xoffset, GLint x, GLint y, GLsizei width )
2840{
2841   struct gl_texture_unit *texUnit;
2842   struct gl_texture_object *texObj;
2843   struct gl_texture_image *texImage;
2844   GLsizei postConvWidth = width;
2845   GLint yoffset = 0;
2846   GLsizei height = 1;
2847
2848   GET_CURRENT_CONTEXT(ctx);
2849   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2850
2851   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2852      _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n",
2853                  _mesa_lookup_enum_by_nr(target),
2854                  level, xoffset, x, y, width);
2855
2856   if (ctx->NewState & NEW_COPY_TEX_STATE)
2857      _mesa_update_state(ctx);
2858
2859   if (copytexsubimage_error_check1(ctx, 1, target, level))
2860      return;
2861
2862   texUnit = _mesa_get_current_tex_unit(ctx);
2863   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2864
2865   _mesa_lock_texture(ctx, texObj);
2866   {
2867      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2868
2869#if FEATURE_convolve
2870      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2871         _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2872      }
2873#endif
2874
2875      if (copytexsubimage_error_check2(ctx, 1, target, level,
2876				       xoffset, 0, 0, postConvWidth, 1,
2877				       texImage)) {
2878         /* error was recorded */
2879      }
2880      else {
2881         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2882         xoffset += texImage->Border;
2883
2884         if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2885                                        &width, &height)) {
2886            ASSERT(ctx->Driver.CopyTexSubImage1D);
2887            ctx->Driver.CopyTexSubImage1D(ctx, target, level,
2888                                          xoffset, x, y, width);
2889
2890            check_gen_mipmap(ctx, target, texObj, level);
2891
2892            ctx->NewState |= _NEW_TEXTURE;
2893         }
2894      }
2895   }
2896   _mesa_unlock_texture(ctx, texObj);
2897}
2898
2899
2900
2901void GLAPIENTRY
2902_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2903                         GLint xoffset, GLint yoffset,
2904                         GLint x, GLint y, GLsizei width, GLsizei height )
2905{
2906   struct gl_texture_unit *texUnit;
2907   struct gl_texture_object *texObj;
2908   struct gl_texture_image *texImage;
2909   GLsizei postConvWidth = width, postConvHeight = height;
2910   GET_CURRENT_CONTEXT(ctx);
2911   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2912
2913   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2914      _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n",
2915                  _mesa_lookup_enum_by_nr(target),
2916                  level, xoffset, yoffset, x, y, width, height);
2917
2918   if (ctx->NewState & NEW_COPY_TEX_STATE)
2919      _mesa_update_state(ctx);
2920
2921   if (copytexsubimage_error_check1(ctx, 2, target, level))
2922      return;
2923
2924   texUnit = _mesa_get_current_tex_unit(ctx);
2925   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2926
2927   _mesa_lock_texture(ctx, texObj);
2928   {
2929      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2930
2931#if FEATURE_convolve
2932      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2933         _mesa_adjust_image_for_convolution(ctx, 2,
2934                                            &postConvWidth, &postConvHeight);
2935      }
2936#endif
2937
2938      if (copytexsubimage_error_check2(ctx, 2, target, level,
2939                                       xoffset, yoffset, 0,
2940				       postConvWidth, postConvHeight,
2941                                       texImage)) {
2942         /* error was recorded */
2943      }
2944      else {
2945         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2946         xoffset += texImage->Border;
2947         yoffset += texImage->Border;
2948
2949         if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2950                                        &width, &height)) {
2951            ASSERT(ctx->Driver.CopyTexSubImage2D);
2952            ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset,
2953                                          x, y, width, height);
2954
2955            check_gen_mipmap(ctx, target, texObj, level);
2956
2957            ctx->NewState |= _NEW_TEXTURE;
2958         }
2959      }
2960   }
2961   _mesa_unlock_texture(ctx, texObj);
2962}
2963
2964
2965
2966void GLAPIENTRY
2967_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2968                         GLint xoffset, GLint yoffset, GLint zoffset,
2969                         GLint x, GLint y, GLsizei width, GLsizei height )
2970{
2971   struct gl_texture_unit *texUnit;
2972   struct gl_texture_object *texObj;
2973   struct gl_texture_image *texImage;
2974   GLsizei postConvWidth = width, postConvHeight = height;
2975   GET_CURRENT_CONTEXT(ctx);
2976   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2977
2978   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2979      _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n",
2980                  _mesa_lookup_enum_by_nr(target),
2981                  level, xoffset, yoffset, zoffset, x, y, width, height);
2982
2983   if (ctx->NewState & NEW_COPY_TEX_STATE)
2984      _mesa_update_state(ctx);
2985
2986   if (copytexsubimage_error_check1(ctx, 3, target, level))
2987      return;
2988
2989   texUnit = _mesa_get_current_tex_unit(ctx);
2990   texObj = _mesa_select_tex_object(ctx, texUnit, target);
2991
2992   _mesa_lock_texture(ctx, texObj);
2993   {
2994      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2995
2996#if FEATURE_convolve
2997      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2998         _mesa_adjust_image_for_convolution(ctx, 2,
2999                                            &postConvWidth, &postConvHeight);
3000      }
3001#endif
3002
3003      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
3004				       zoffset, postConvWidth, postConvHeight,
3005				       texImage)) {
3006         /* error was recored */
3007      }
3008      else {
3009         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
3010         xoffset += texImage->Border;
3011         yoffset += texImage->Border;
3012         zoffset += texImage->Border;
3013
3014         if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3015                                        &width, &height)) {
3016            ASSERT(ctx->Driver.CopyTexSubImage3D);
3017            ctx->Driver.CopyTexSubImage3D(ctx, target, level,
3018                                          xoffset, yoffset, zoffset,
3019                                          x, y, width, height);
3020
3021            check_gen_mipmap(ctx, target, texObj, level);
3022
3023            ctx->NewState |= _NEW_TEXTURE;
3024         }
3025      }
3026   }
3027   _mesa_unlock_texture(ctx, texObj);
3028}
3029
3030
3031
3032
3033/**********************************************************************/
3034/******                   Compressed Textures                    ******/
3035/**********************************************************************/
3036
3037
3038/**
3039 * Error checking for glCompressedTexImage[123]D().
3040 * \return error code or GL_NO_ERROR.
3041 */
3042static GLenum
3043compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3044                               GLenum target, GLint level,
3045                               GLenum internalFormat, GLsizei width,
3046                               GLsizei height, GLsizei depth, GLint border,
3047                               GLsizei imageSize)
3048{
3049   GLint expectedSize, maxLevels = 0, maxTextureSize;
3050
3051   if (dimensions == 1) {
3052      /* 1D compressed textures not allowed */
3053      return GL_INVALID_ENUM;
3054   }
3055   else if (dimensions == 2) {
3056      if (target == GL_PROXY_TEXTURE_2D) {
3057         maxLevels = ctx->Const.MaxTextureLevels;
3058      }
3059      else if (target == GL_TEXTURE_2D) {
3060         maxLevels = ctx->Const.MaxTextureLevels;
3061      }
3062      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3063         if (!ctx->Extensions.ARB_texture_cube_map)
3064            return GL_INVALID_ENUM; /*target*/
3065         maxLevels = ctx->Const.MaxCubeTextureLevels;
3066      }
3067      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3068               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3069         if (!ctx->Extensions.ARB_texture_cube_map)
3070            return GL_INVALID_ENUM; /*target*/
3071         maxLevels = ctx->Const.MaxCubeTextureLevels;
3072      }
3073      else {
3074         return GL_INVALID_ENUM; /*target*/
3075      }
3076   }
3077   else if (dimensions == 3) {
3078      /* 3D compressed textures not allowed */
3079      return GL_INVALID_ENUM;
3080   }
3081
3082   maxTextureSize = 1 << (maxLevels - 1);
3083
3084   /* This will detect any invalid internalFormat value */
3085   if (!is_compressed_format(ctx, internalFormat))
3086      return GL_INVALID_ENUM;
3087
3088   /* This should really never fail */
3089   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3090      return GL_INVALID_ENUM;
3091
3092   if (border != 0)
3093      return GL_INVALID_VALUE;
3094
3095   /*
3096    * XXX We should probably use the proxy texture error check function here.
3097    */
3098   if (width < 1 || width > maxTextureSize ||
3099       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
3100      return GL_INVALID_VALUE;
3101
3102   if ((height < 1 || height > maxTextureSize ||
3103       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
3104       && dimensions > 1)
3105      return GL_INVALID_VALUE;
3106
3107   if ((depth < 1 || depth > maxTextureSize ||
3108       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
3109       && dimensions > 2)
3110      return GL_INVALID_VALUE;
3111
3112   /* For cube map, width must equal height */
3113   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3114       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3115      return GL_INVALID_VALUE;
3116
3117   if (level < 0 || level >= maxLevels)
3118      return GL_INVALID_VALUE;
3119
3120   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3121                                                       depth, internalFormat);
3122   if (expectedSize != imageSize)
3123      return GL_INVALID_VALUE;
3124
3125#if FEATURE_EXT_texture_sRGB
3126   if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3127        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3128        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3129        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3130       && border != 0) {
3131      return GL_INVALID_OPERATION;
3132   }
3133#endif
3134
3135   return GL_NO_ERROR;
3136}
3137
3138
3139/**
3140 * Error checking for glCompressedTexSubImage[123]D().
3141 * \warning  There are some bad assumptions here about the size of compressed
3142 *           texture tiles (multiple of 4) used to test the validity of the
3143 *           offset and size parameters.
3144 * \return error code or GL_NO_ERROR.
3145 */
3146static GLenum
3147compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3148                                  GLenum target, GLint level,
3149                                  GLint xoffset, GLint yoffset, GLint zoffset,
3150                                  GLsizei width, GLsizei height, GLsizei depth,
3151                                  GLenum format, GLsizei imageSize)
3152{
3153   GLint expectedSize, maxLevels = 0, maxTextureSize;
3154   (void) zoffset;
3155
3156   if (dimensions == 1) {
3157      /* 1D compressed textures not allowed */
3158      return GL_INVALID_ENUM;
3159   }
3160   else if (dimensions == 2) {
3161      if (target == GL_PROXY_TEXTURE_2D) {
3162         maxLevels = ctx->Const.MaxTextureLevels;
3163      }
3164      else if (target == GL_TEXTURE_2D) {
3165         maxLevels = ctx->Const.MaxTextureLevels;
3166      }
3167      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3168         if (!ctx->Extensions.ARB_texture_cube_map)
3169            return GL_INVALID_ENUM; /*target*/
3170         maxLevels = ctx->Const.MaxCubeTextureLevels;
3171      }
3172      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3173               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3174         if (!ctx->Extensions.ARB_texture_cube_map)
3175            return GL_INVALID_ENUM; /*target*/
3176         maxLevels = ctx->Const.MaxCubeTextureLevels;
3177      }
3178      else {
3179         return GL_INVALID_ENUM; /*target*/
3180      }
3181   }
3182   else if (dimensions == 3) {
3183      /* 3D compressed textures not allowed */
3184      return GL_INVALID_ENUM;
3185   }
3186
3187   maxTextureSize = 1 << (maxLevels - 1);
3188
3189   /* this will catch any invalid compressed format token */
3190   if (!is_compressed_format(ctx, format))
3191      return GL_INVALID_ENUM;
3192
3193   if (width < 1 || width > maxTextureSize)
3194      return GL_INVALID_VALUE;
3195
3196   if ((height < 1 || height > maxTextureSize)
3197       && dimensions > 1)
3198      return GL_INVALID_VALUE;
3199
3200   if (level < 0 || level >= maxLevels)
3201      return GL_INVALID_VALUE;
3202
3203   /* XXX these tests are specific to the compressed format.
3204    * this code should be generalized in some way.
3205    */
3206   if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3207      return GL_INVALID_VALUE;
3208
3209   if ((width & 3) != 0 && width != 2 && width != 1)
3210      return GL_INVALID_VALUE;
3211
3212   if ((height & 3) != 0 && height != 2 && height != 1)
3213      return GL_INVALID_VALUE;
3214
3215   expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3216                                                       depth, format);
3217   if (expectedSize != imageSize)
3218      return GL_INVALID_VALUE;
3219
3220   return GL_NO_ERROR;
3221}
3222
3223
3224
3225void GLAPIENTRY
3226_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3227                              GLenum internalFormat, GLsizei width,
3228                              GLint border, GLsizei imageSize,
3229                              const GLvoid *data)
3230{
3231   GET_CURRENT_CONTEXT(ctx);
3232   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3233
3234   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3235      _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n",
3236                  _mesa_lookup_enum_by_nr(target), level,
3237                  _mesa_lookup_enum_by_nr(internalFormat),
3238                  width, border, imageSize, data);
3239
3240   if (target == GL_TEXTURE_1D) {
3241      /* non-proxy target */
3242      struct gl_texture_unit *texUnit;
3243      struct gl_texture_object *texObj;
3244      struct gl_texture_image *texImage;
3245      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3246                               internalFormat, width, 1, 1, border, imageSize);
3247      if (error) {
3248         _mesa_error(ctx, error, "glCompressedTexImage1D");
3249         return;
3250      }
3251
3252      texUnit = _mesa_get_current_tex_unit(ctx);
3253      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3254
3255      _mesa_lock_texture(ctx, texObj);
3256      {
3257	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3258	 if (!texImage) {
3259	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3260	 }
3261         else {
3262            if (texImage->Data) {
3263               ctx->Driver.FreeTexImageData( ctx, texImage );
3264            }
3265            ASSERT(texImage->Data == NULL);
3266
3267            _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3268                                       border, internalFormat);
3269
3270            ASSERT(ctx->Driver.CompressedTexImage1D);
3271            ctx->Driver.CompressedTexImage1D(ctx, target, level,
3272                                             internalFormat, width, border,
3273                                             imageSize, data,
3274                                             texObj, texImage);
3275
3276            _mesa_set_fetch_functions(texImage, 1);
3277
3278            check_gen_mipmap(ctx, target, texObj, level);
3279
3280            /* state update */
3281            texObj->_Complete = GL_FALSE;
3282            ctx->NewState |= _NEW_TEXTURE;
3283         }
3284      }
3285      _mesa_unlock_texture(ctx, texObj);
3286   }
3287   else if (target == GL_PROXY_TEXTURE_1D) {
3288      /* Proxy texture: check for errors and update proxy state */
3289      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3290                               internalFormat, width, 1, 1, border, imageSize);
3291      if (!error) {
3292         ASSERT(ctx->Driver.TestProxyTexImage);
3293         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3294                                             internalFormat, GL_NONE, GL_NONE,
3295                                             width, 1, 1, border);
3296      }
3297      if (error) {
3298         /* if error, clear all proxy texture image parameters */
3299         struct gl_texture_image *texImage;
3300         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3301         if (texImage)
3302            clear_teximage_fields(texImage);
3303      }
3304      else {
3305         /* store the teximage parameters */
3306         struct gl_texture_unit *texUnit;
3307         struct gl_texture_object *texObj;
3308         struct gl_texture_image *texImage;
3309         texUnit = _mesa_get_current_tex_unit(ctx);
3310	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3311
3312	 _mesa_lock_texture(ctx, texObj);
3313	 {
3314	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3315	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3316				       border, internalFormat);
3317	 }
3318	 _mesa_unlock_texture(ctx, texObj);
3319      }
3320   }
3321   else {
3322      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3323      return;
3324   }
3325}
3326
3327
3328void GLAPIENTRY
3329_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3330                              GLenum internalFormat, GLsizei width,
3331                              GLsizei height, GLint border, GLsizei imageSize,
3332                              const GLvoid *data)
3333{
3334   GET_CURRENT_CONTEXT(ctx);
3335   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3336
3337   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3338      _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n",
3339                  _mesa_lookup_enum_by_nr(target), level,
3340                  _mesa_lookup_enum_by_nr(internalFormat),
3341                  width, height, border, imageSize, data);
3342
3343   if (target == GL_TEXTURE_2D ||
3344       (ctx->Extensions.ARB_texture_cube_map &&
3345        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3346        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3347      /* non-proxy target */
3348      struct gl_texture_unit *texUnit;
3349      struct gl_texture_object *texObj;
3350      struct gl_texture_image *texImage;
3351      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3352                          internalFormat, width, height, 1, border, imageSize);
3353      if (error) {
3354         _mesa_error(ctx, error, "glCompressedTexImage2D");
3355         return;
3356      }
3357
3358      texUnit = _mesa_get_current_tex_unit(ctx);
3359      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3360
3361      _mesa_lock_texture(ctx, texObj);
3362      {
3363	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3364	 if (!texImage) {
3365	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3366	 }
3367         else {
3368            if (texImage->Data) {
3369               ctx->Driver.FreeTexImageData( ctx, texImage );
3370            }
3371            ASSERT(texImage->Data == NULL);
3372
3373            _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3374                                       border, internalFormat);
3375
3376            ASSERT(ctx->Driver.CompressedTexImage2D);
3377            ctx->Driver.CompressedTexImage2D(ctx, target, level,
3378                                             internalFormat, width, height,
3379                                             border, imageSize, data,
3380                                             texObj, texImage);
3381
3382            _mesa_set_fetch_functions(texImage, 2);
3383
3384            check_gen_mipmap(ctx, target, texObj, level);
3385
3386            /* state update */
3387            texObj->_Complete = GL_FALSE;
3388            ctx->NewState |= _NEW_TEXTURE;
3389         }
3390      }
3391      _mesa_unlock_texture(ctx, texObj);
3392   }
3393   else if (target == GL_PROXY_TEXTURE_2D ||
3394            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3395             ctx->Extensions.ARB_texture_cube_map)) {
3396      /* Proxy texture: check for errors and update proxy state */
3397      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3398                          internalFormat, width, height, 1, border, imageSize);
3399      if (!error) {
3400         ASSERT(ctx->Driver.TestProxyTexImage);
3401         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3402                                              internalFormat, GL_NONE, GL_NONE,
3403                                              width, height, 1, border);
3404      }
3405      if (error) {
3406         /* if error, clear all proxy texture image parameters */
3407         struct gl_texture_image *texImage;
3408         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3409         if (texImage)
3410            clear_teximage_fields(texImage);
3411      }
3412      else {
3413         /* store the teximage parameters */
3414         struct gl_texture_unit *texUnit;
3415         struct gl_texture_object *texObj;
3416         struct gl_texture_image *texImage;
3417         texUnit = _mesa_get_current_tex_unit(ctx);
3418	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3419
3420	 _mesa_lock_texture(ctx, texObj);
3421	 {
3422	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3423	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3424				       border, internalFormat);
3425	 }
3426	 _mesa_unlock_texture(ctx, texObj);
3427      }
3428   }
3429   else {
3430      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3431      return;
3432   }
3433}
3434
3435
3436void GLAPIENTRY
3437_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3438                              GLenum internalFormat, GLsizei width,
3439                              GLsizei height, GLsizei depth, GLint border,
3440                              GLsizei imageSize, const GLvoid *data)
3441{
3442   GET_CURRENT_CONTEXT(ctx);
3443   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3444
3445   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3446      _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n",
3447                  _mesa_lookup_enum_by_nr(target), level,
3448                  _mesa_lookup_enum_by_nr(internalFormat),
3449                  width, height, depth, border, imageSize, data);
3450
3451   if (target == GL_TEXTURE_3D) {
3452      /* non-proxy target */
3453      struct gl_texture_unit *texUnit;
3454      struct gl_texture_object *texObj;
3455      struct gl_texture_image *texImage;
3456      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3457                      internalFormat, width, height, depth, border, imageSize);
3458      if (error) {
3459         _mesa_error(ctx, error, "glCompressedTexImage3D");
3460         return;
3461      }
3462
3463      texUnit = _mesa_get_current_tex_unit(ctx);
3464      texObj = _mesa_select_tex_object(ctx, texUnit, target);
3465      _mesa_lock_texture(ctx, texObj);
3466      {
3467	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3468	 if (!texImage) {
3469	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3470	 }
3471         else {
3472            if (texImage->Data) {
3473               ctx->Driver.FreeTexImageData( ctx, texImage );
3474            }
3475            ASSERT(texImage->Data == NULL);
3476
3477            _mesa_init_teximage_fields(ctx, target, texImage,
3478                                       width, height, depth,
3479                                       border, internalFormat);
3480
3481            ASSERT(ctx->Driver.CompressedTexImage3D);
3482            ctx->Driver.CompressedTexImage3D(ctx, target, level,
3483                                             internalFormat,
3484                                             width, height, depth,
3485                                             border, imageSize, data,
3486                                             texObj, texImage);
3487
3488            _mesa_set_fetch_functions(texImage, 3);
3489
3490            check_gen_mipmap(ctx, target, texObj, level);
3491
3492            /* state update */
3493            texObj->_Complete = GL_FALSE;
3494            ctx->NewState |= _NEW_TEXTURE;
3495         }
3496      }
3497      _mesa_unlock_texture(ctx, texObj);
3498   }
3499   else if (target == GL_PROXY_TEXTURE_3D) {
3500      /* Proxy texture: check for errors and update proxy state */
3501      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3502                      internalFormat, width, height, depth, border, imageSize);
3503      if (!error) {
3504         ASSERT(ctx->Driver.TestProxyTexImage);
3505         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3506                                             internalFormat, GL_NONE, GL_NONE,
3507                                             width, height, depth, border);
3508      }
3509      if (error) {
3510         /* if error, clear all proxy texture image parameters */
3511         struct gl_texture_image *texImage;
3512         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3513         if (texImage)
3514            clear_teximage_fields(texImage);
3515      }
3516      else {
3517         /* store the teximage parameters */
3518         struct gl_texture_unit *texUnit;
3519         struct gl_texture_object *texObj;
3520         struct gl_texture_image *texImage;
3521         texUnit = _mesa_get_current_tex_unit(ctx);
3522	 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3523	 _mesa_lock_texture(ctx, texObj);
3524	 {
3525	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3526	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3527				       depth, border, internalFormat);
3528	 }
3529	 _mesa_unlock_texture(ctx, texObj);
3530      }
3531   }
3532   else {
3533      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3534      return;
3535   }
3536}
3537
3538
3539void GLAPIENTRY
3540_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3541                                 GLsizei width, GLenum format,
3542                                 GLsizei imageSize, const GLvoid *data)
3543{
3544   struct gl_texture_unit *texUnit;
3545   struct gl_texture_object *texObj;
3546   struct gl_texture_image *texImage;
3547   GLenum error;
3548   GET_CURRENT_CONTEXT(ctx);
3549   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3550
3551   error = compressed_subtexture_error_check(ctx, 1, target, level,
3552                                             xoffset, 0, 0, /* pos */
3553                                             width, 1, 1,   /* size */
3554                                             format, imageSize);
3555   if (error) {
3556      _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3557      return;
3558   }
3559
3560   texUnit = _mesa_get_current_tex_unit(ctx);
3561   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3562
3563   _mesa_lock_texture(ctx, texObj);
3564   {
3565      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3566      assert(texImage);
3567
3568      if ((GLint) format != texImage->InternalFormat) {
3569	 _mesa_error(ctx, GL_INVALID_OPERATION,
3570		     "glCompressedTexSubImage1D(format)");
3571      }
3572      else if ((width == 1 || width == 2) &&
3573               (GLuint) width != texImage->Width) {
3574	 _mesa_error(ctx, GL_INVALID_VALUE,
3575                     "glCompressedTexSubImage1D(width)");
3576      }
3577      else if (width > 0) {
3578         if (ctx->Driver.CompressedTexSubImage1D) {
3579            ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
3580                                                xoffset, width,
3581                                                format, imageSize, data,
3582                                                texObj, texImage);
3583         }
3584
3585         check_gen_mipmap(ctx, target, texObj, level);
3586
3587         ctx->NewState |= _NEW_TEXTURE;
3588      }
3589   }
3590   _mesa_unlock_texture(ctx, texObj);
3591}
3592
3593
3594void GLAPIENTRY
3595_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3596                                 GLint yoffset, GLsizei width, GLsizei height,
3597                                 GLenum format, GLsizei imageSize,
3598                                 const GLvoid *data)
3599{
3600   struct gl_texture_unit *texUnit;
3601   struct gl_texture_object *texObj;
3602   struct gl_texture_image *texImage;
3603   GLenum error;
3604   GET_CURRENT_CONTEXT(ctx);
3605   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3606
3607   error = compressed_subtexture_error_check(ctx, 2, target, level,
3608                                             xoffset, yoffset, 0, /* pos */
3609                                             width, height, 1,    /* size */
3610                                             format, imageSize);
3611   if (error) {
3612      /* XXX proxy target? */
3613      _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3614      return;
3615   }
3616
3617   texUnit = _mesa_get_current_tex_unit(ctx);
3618   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3619
3620   _mesa_lock_texture(ctx, texObj);
3621   {
3622      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3623      assert(texImage);
3624
3625      if ((GLint) format != texImage->InternalFormat) {
3626	 _mesa_error(ctx, GL_INVALID_OPERATION,
3627		     "glCompressedTexSubImage2D(format)");
3628      }
3629      else if (((width == 1 || width == 2)
3630                && (GLuint) width != texImage->Width) ||
3631               ((height == 1 || height == 2)
3632                && (GLuint) height != texImage->Height)) {
3633	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3634      }
3635      else if (width > 0 && height > 0) {
3636         if (ctx->Driver.CompressedTexSubImage2D) {
3637            ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
3638						xoffset, yoffset, width, height,
3639						format, imageSize, data,
3640						texObj, texImage);
3641         }
3642
3643         check_gen_mipmap(ctx, target, texObj, level);
3644
3645         ctx->NewState |= _NEW_TEXTURE;
3646      }
3647   }
3648   _mesa_unlock_texture(ctx, texObj);
3649}
3650
3651
3652void GLAPIENTRY
3653_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3654                                 GLint yoffset, GLint zoffset, GLsizei width,
3655                                 GLsizei height, GLsizei depth, GLenum format,
3656                                 GLsizei imageSize, const GLvoid *data)
3657{
3658   struct gl_texture_unit *texUnit;
3659   struct gl_texture_object *texObj;
3660   struct gl_texture_image *texImage;
3661   GLenum error;
3662   GET_CURRENT_CONTEXT(ctx);
3663   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3664
3665   error = compressed_subtexture_error_check(ctx, 3, target, level,
3666                                             xoffset, yoffset, zoffset,/*pos*/
3667                                             width, height, depth, /*size*/
3668                                             format, imageSize);
3669   if (error) {
3670      _mesa_error(ctx, error, "glCompressedTexSubImage3D");
3671      return;
3672   }
3673
3674   texUnit = _mesa_get_current_tex_unit(ctx);
3675   texObj = _mesa_select_tex_object(ctx, texUnit, target);
3676
3677   _mesa_lock_texture(ctx, texObj);
3678   {
3679      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3680      assert(texImage);
3681
3682      if ((GLint) format != texImage->InternalFormat) {
3683	 _mesa_error(ctx, GL_INVALID_OPERATION,
3684		     "glCompressedTexSubImage3D(format)");
3685      }
3686      else if (((width == 1 || width == 2)
3687                && (GLuint) width != texImage->Width) ||
3688               ((height == 1 || height == 2)
3689                && (GLuint) height != texImage->Height) ||
3690               ((depth == 1 || depth == 2)
3691                && (GLuint) depth != texImage->Depth)) {
3692	 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3693      }
3694      else if (width > 0 && height > 0 && depth > 0) {
3695         if (ctx->Driver.CompressedTexSubImage3D) {
3696            ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
3697						xoffset, yoffset, zoffset,
3698						width, height, depth,
3699						format, imageSize, data,
3700						texObj, texImage);
3701         }
3702
3703         check_gen_mipmap(ctx, target, texObj, level);
3704
3705         ctx->NewState |= _NEW_TEXTURE;
3706      }
3707   }
3708   _mesa_unlock_texture(ctx, texObj);
3709}
3710
3711
3712