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