teximage.c revision 4a49301e
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      _mesa_free(texImage->ImageOffsets);
492   _mesa_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      _mesa_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      _mesa_free(img->ImageOffsets);
936   img->ImageOffsets = (GLuint *) _mesa_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         _mesa_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            _mesa_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
2452void GLAPIENTRY
2453_mesa_TexSubImage1D( GLenum target, GLint level,
2454                     GLint xoffset, GLsizei width,
2455                     GLenum format, GLenum type,
2456                     const GLvoid *pixels )
2457{
2458   GLsizei postConvWidth = width;
2459   struct gl_texture_object *texObj;
2460   struct gl_texture_image *texImage;
2461   GET_CURRENT_CONTEXT(ctx);
2462   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2463
2464   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2465      _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n",
2466                  _mesa_lookup_enum_by_nr(target), level,
2467                  xoffset, width, _mesa_lookup_enum_by_nr(format),
2468                  _mesa_lookup_enum_by_nr(type), pixels);
2469
2470   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2471      _mesa_update_state(ctx);
2472
2473#if FEATURE_convolve
2474   /* XXX should test internal format */
2475   if (_mesa_is_color_format(format)) {
2476      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2477   }
2478#endif
2479
2480   if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2481			       postConvWidth, 1, 1, format, type)) {
2482      return;   /* error was detected */
2483   }
2484
2485
2486   texObj = _mesa_get_current_tex_object(ctx, target);
2487   assert(texObj);
2488
2489   _mesa_lock_texture(ctx, texObj);
2490   {
2491      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2492
2493      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2494				  postConvWidth, 1, 1,
2495                                  format, type, texImage)) {
2496         /* error was recorded */
2497      }
2498      else if (width > 0) {
2499         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2500         xoffset += texImage->Border;
2501
2502         ASSERT(ctx->Driver.TexSubImage1D);
2503         ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
2504                                   format, type, pixels, &ctx->Unpack,
2505                                   texObj, texImage);
2506
2507         check_gen_mipmap(ctx, target, texObj, level);
2508
2509         ctx->NewState |= _NEW_TEXTURE;
2510      }
2511   }
2512   _mesa_unlock_texture(ctx, texObj);
2513}
2514
2515
2516void GLAPIENTRY
2517_mesa_TexSubImage2D( GLenum target, GLint level,
2518                     GLint xoffset, GLint yoffset,
2519                     GLsizei width, GLsizei height,
2520                     GLenum format, GLenum type,
2521                     const GLvoid *pixels )
2522{
2523   GLsizei postConvWidth = width, postConvHeight = height;
2524   struct gl_texture_object *texObj;
2525   struct gl_texture_image *texImage;
2526   GET_CURRENT_CONTEXT(ctx);
2527   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2528
2529   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2530      _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n",
2531                  _mesa_lookup_enum_by_nr(target), level,
2532                  xoffset, yoffset, width, height,
2533                  _mesa_lookup_enum_by_nr(format),
2534                  _mesa_lookup_enum_by_nr(type), pixels);
2535
2536   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2537      _mesa_update_state(ctx);
2538
2539#if FEATURE_convolve
2540   /* XXX should test internal format */
2541   if (_mesa_is_color_format(format)) {
2542      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2543                                         &postConvHeight);
2544   }
2545#endif
2546
2547   if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2548			      postConvWidth, postConvHeight, 1, format, type)) {
2549      return;   /* error was detected */
2550   }
2551
2552   texObj = _mesa_get_current_tex_object(ctx, target);
2553
2554   _mesa_lock_texture(ctx, texObj);
2555   {
2556      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2557
2558      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2559				  postConvWidth, postConvHeight, 1,
2560                                  format, type, texImage)) {
2561	 /* error was recorded */
2562      }
2563      else if (width > 0 && height >= 0) {
2564         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2565         xoffset += texImage->Border;
2566         yoffset += texImage->Border;
2567
2568         ASSERT(ctx->Driver.TexSubImage2D);
2569         ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
2570                                   width, height, format, type, pixels,
2571                                   &ctx->Unpack, texObj, texImage);
2572
2573         check_gen_mipmap(ctx, target, texObj, level);
2574
2575         ctx->NewState |= _NEW_TEXTURE;
2576      }
2577   }
2578   _mesa_unlock_texture(ctx, texObj);
2579}
2580
2581
2582
2583void GLAPIENTRY
2584_mesa_TexSubImage3D( GLenum target, GLint level,
2585                     GLint xoffset, GLint yoffset, GLint zoffset,
2586                     GLsizei width, GLsizei height, GLsizei depth,
2587                     GLenum format, GLenum type,
2588                     const GLvoid *pixels )
2589{
2590   struct gl_texture_object *texObj;
2591   struct gl_texture_image *texImage;
2592   GET_CURRENT_CONTEXT(ctx);
2593   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2594
2595   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2596      _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n",
2597                  _mesa_lookup_enum_by_nr(target), level,
2598                  xoffset, yoffset, zoffset, width, height, depth,
2599                  _mesa_lookup_enum_by_nr(format),
2600                  _mesa_lookup_enum_by_nr(type), pixels);
2601
2602   if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2603      _mesa_update_state(ctx);
2604
2605   if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2606                              width, height, depth, format, type)) {
2607      return;   /* error was detected */
2608   }
2609
2610   texObj = _mesa_get_current_tex_object(ctx, target);
2611
2612   _mesa_lock_texture(ctx, texObj);
2613   {
2614      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2615
2616      if (subtexture_error_check2(ctx, 3, target, level,
2617                                  xoffset, yoffset, zoffset,
2618				  width, height, depth,
2619                                  format, type, texImage)) {
2620         /* error was recorded */
2621      }
2622      else if (width > 0 && height > 0 && height > 0) {
2623         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2624         xoffset += texImage->Border;
2625         yoffset += texImage->Border;
2626         zoffset += texImage->Border;
2627
2628         ASSERT(ctx->Driver.TexSubImage3D);
2629         ctx->Driver.TexSubImage3D(ctx, target, level,
2630                                   xoffset, yoffset, zoffset,
2631                                   width, height, depth,
2632                                   format, type, pixels,
2633                                   &ctx->Unpack, texObj, texImage );
2634
2635         check_gen_mipmap(ctx, target, texObj, level);
2636
2637         ctx->NewState |= _NEW_TEXTURE;
2638      }
2639   }
2640   _mesa_unlock_texture(ctx, texObj);
2641}
2642
2643
2644
2645void GLAPIENTRY
2646_mesa_CopyTexImage1D( GLenum target, GLint level,
2647                      GLenum internalFormat,
2648                      GLint x, GLint y,
2649                      GLsizei width, GLint border )
2650{
2651   struct gl_texture_object *texObj;
2652   struct gl_texture_image *texImage;
2653   GLsizei postConvWidth = width;
2654   const GLuint face = _mesa_tex_target_to_face(target);
2655   GET_CURRENT_CONTEXT(ctx);
2656   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2657
2658   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2659      _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n",
2660                  _mesa_lookup_enum_by_nr(target), level,
2661                  _mesa_lookup_enum_by_nr(internalFormat),
2662                  x, y, width, border);
2663
2664   if (ctx->NewState & NEW_COPY_TEX_STATE)
2665      _mesa_update_state(ctx);
2666
2667#if FEATURE_convolve
2668   if (_mesa_is_color_format(internalFormat)) {
2669      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2670   }
2671#endif
2672
2673   if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2674                               postConvWidth, 1, border))
2675      return;
2676
2677   texObj = _mesa_get_current_tex_object(ctx, target);
2678
2679   _mesa_lock_texture(ctx, texObj);
2680   {
2681      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2682      if (!texImage) {
2683	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2684      }
2685      else {
2686         if (texImage->Data) {
2687            ctx->Driver.FreeTexImageData( ctx, texImage );
2688         }
2689
2690         ASSERT(texImage->Data == NULL);
2691
2692         clear_teximage_fields(texImage); /* not really needed, but helpful */
2693         _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2694                                    border, internalFormat);
2695
2696         /* Choose actual texture format */
2697         texImage->TexFormat =
2698            ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2699                                            GL_NONE, GL_NONE);
2700         ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2701
2702         ASSERT(ctx->Driver.CopyTexImage1D);
2703         ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
2704                                    x, y, width, border);
2705
2706         ASSERT(texImage->TexFormat);
2707
2708         _mesa_set_fetch_functions(texImage, 1);
2709
2710         check_gen_mipmap(ctx, target, texObj, level);
2711
2712         update_fbo_texture(ctx, texObj, face, level);
2713
2714         /* state update */
2715         texObj->_Complete = GL_FALSE;
2716         ctx->NewState |= _NEW_TEXTURE;
2717      }
2718   }
2719   _mesa_unlock_texture(ctx, texObj);
2720}
2721
2722
2723
2724void GLAPIENTRY
2725_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2726                      GLint x, GLint y, GLsizei width, GLsizei height,
2727                      GLint border )
2728{
2729   struct gl_texture_object *texObj;
2730   struct gl_texture_image *texImage;
2731   GLsizei postConvWidth = width, postConvHeight = height;
2732   const GLuint face = _mesa_tex_target_to_face(target);
2733   GET_CURRENT_CONTEXT(ctx);
2734   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2735
2736   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2737      _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n",
2738                  _mesa_lookup_enum_by_nr(target), level,
2739                  _mesa_lookup_enum_by_nr(internalFormat),
2740                  x, y, width, height, border);
2741
2742   if (ctx->NewState & NEW_COPY_TEX_STATE)
2743      _mesa_update_state(ctx);
2744
2745#if FEATURE_convolve
2746   if (_mesa_is_color_format(internalFormat)) {
2747      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2748                                         &postConvHeight);
2749   }
2750#endif
2751
2752   if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2753                               postConvWidth, postConvHeight, border))
2754      return;
2755
2756   texObj = _mesa_get_current_tex_object(ctx, target);
2757
2758   _mesa_lock_texture(ctx, texObj);
2759   {
2760      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2761
2762      if (!texImage) {
2763	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2764      }
2765      else {
2766         if (texImage->Data) {
2767            ctx->Driver.FreeTexImageData( ctx, texImage );
2768         }
2769
2770         ASSERT(texImage->Data == NULL);
2771
2772         clear_teximage_fields(texImage); /* not really needed, but helpful */
2773         _mesa_init_teximage_fields(ctx, target, texImage,
2774                                    postConvWidth, postConvHeight, 1,
2775                                    border, internalFormat);
2776
2777         /* Choose actual texture format */
2778         texImage->TexFormat =
2779            ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2780                                            GL_NONE, GL_NONE);
2781         ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2782
2783         ASSERT(ctx->Driver.CopyTexImage2D);
2784         ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
2785                                    x, y, width, height, border);
2786
2787         ASSERT(texImage->TexFormat);
2788
2789         _mesa_set_fetch_functions(texImage, 2);
2790
2791         check_gen_mipmap(ctx, target, texObj, level);
2792
2793         update_fbo_texture(ctx, texObj, face, level);
2794
2795         /* state update */
2796         texObj->_Complete = GL_FALSE;
2797         ctx->NewState |= _NEW_TEXTURE;
2798      }
2799   }
2800   _mesa_unlock_texture(ctx, texObj);
2801}
2802
2803
2804void GLAPIENTRY
2805_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2806                         GLint xoffset, GLint x, GLint y, GLsizei width )
2807{
2808   struct gl_texture_object *texObj;
2809   struct gl_texture_image *texImage;
2810   GLsizei postConvWidth = width;
2811   GLint yoffset = 0;
2812   GLsizei height = 1;
2813
2814   GET_CURRENT_CONTEXT(ctx);
2815   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2816
2817   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2818      _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n",
2819                  _mesa_lookup_enum_by_nr(target),
2820                  level, xoffset, x, y, width);
2821
2822   if (ctx->NewState & NEW_COPY_TEX_STATE)
2823      _mesa_update_state(ctx);
2824
2825   if (copytexsubimage_error_check1(ctx, 1, target, level))
2826      return;
2827
2828   texObj = _mesa_get_current_tex_object(ctx, target);
2829
2830   _mesa_lock_texture(ctx, texObj);
2831   {
2832      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2833
2834#if FEATURE_convolve
2835      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2836         _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2837      }
2838#endif
2839
2840      if (copytexsubimage_error_check2(ctx, 1, target, level,
2841				       xoffset, 0, 0, postConvWidth, 1,
2842				       texImage)) {
2843         /* error was recorded */
2844      }
2845      else {
2846         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2847         xoffset += texImage->Border;
2848
2849         if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2850                                        &width, &height)) {
2851            ASSERT(ctx->Driver.CopyTexSubImage1D);
2852            ctx->Driver.CopyTexSubImage1D(ctx, target, level,
2853                                          xoffset, x, y, width);
2854
2855            check_gen_mipmap(ctx, target, texObj, level);
2856
2857            ctx->NewState |= _NEW_TEXTURE;
2858         }
2859      }
2860   }
2861   _mesa_unlock_texture(ctx, texObj);
2862}
2863
2864
2865
2866void GLAPIENTRY
2867_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2868                         GLint xoffset, GLint yoffset,
2869                         GLint x, GLint y, GLsizei width, GLsizei height )
2870{
2871   struct gl_texture_object *texObj;
2872   struct gl_texture_image *texImage;
2873   GLsizei postConvWidth = width, postConvHeight = height;
2874   GET_CURRENT_CONTEXT(ctx);
2875   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2876
2877   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2878      _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n",
2879                  _mesa_lookup_enum_by_nr(target),
2880                  level, xoffset, yoffset, x, y, width, height);
2881
2882   if (ctx->NewState & NEW_COPY_TEX_STATE)
2883      _mesa_update_state(ctx);
2884
2885   if (copytexsubimage_error_check1(ctx, 2, target, level))
2886      return;
2887
2888   texObj = _mesa_get_current_tex_object(ctx, target);
2889
2890   _mesa_lock_texture(ctx, texObj);
2891   {
2892      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2893
2894#if FEATURE_convolve
2895      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2896         _mesa_adjust_image_for_convolution(ctx, 2,
2897                                            &postConvWidth, &postConvHeight);
2898      }
2899#endif
2900
2901      if (copytexsubimage_error_check2(ctx, 2, target, level,
2902                                       xoffset, yoffset, 0,
2903				       postConvWidth, postConvHeight,
2904                                       texImage)) {
2905         /* error was recorded */
2906      }
2907      else {
2908         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2909         xoffset += texImage->Border;
2910         yoffset += texImage->Border;
2911
2912         if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2913                                        &width, &height)) {
2914            ASSERT(ctx->Driver.CopyTexSubImage2D);
2915            ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset,
2916                                          x, y, width, height);
2917
2918            check_gen_mipmap(ctx, target, texObj, level);
2919
2920            ctx->NewState |= _NEW_TEXTURE;
2921         }
2922      }
2923   }
2924   _mesa_unlock_texture(ctx, texObj);
2925}
2926
2927
2928
2929void GLAPIENTRY
2930_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2931                         GLint xoffset, GLint yoffset, GLint zoffset,
2932                         GLint x, GLint y, GLsizei width, GLsizei height )
2933{
2934   struct gl_texture_object *texObj;
2935   struct gl_texture_image *texImage;
2936   GLsizei postConvWidth = width, postConvHeight = height;
2937   GET_CURRENT_CONTEXT(ctx);
2938   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2939
2940   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2941      _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n",
2942                  _mesa_lookup_enum_by_nr(target),
2943                  level, xoffset, yoffset, zoffset, x, y, width, height);
2944
2945   if (ctx->NewState & NEW_COPY_TEX_STATE)
2946      _mesa_update_state(ctx);
2947
2948   if (copytexsubimage_error_check1(ctx, 3, target, level))
2949      return;
2950
2951   texObj = _mesa_get_current_tex_object(ctx, target);
2952
2953   _mesa_lock_texture(ctx, texObj);
2954   {
2955      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2956
2957#if FEATURE_convolve
2958      if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2959         _mesa_adjust_image_for_convolution(ctx, 2,
2960                                            &postConvWidth, &postConvHeight);
2961      }
2962#endif
2963
2964      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
2965				       zoffset, postConvWidth, postConvHeight,
2966				       texImage)) {
2967         /* error was recored */
2968      }
2969      else {
2970         /* If we have a border, xoffset=-1 is legal.  Bias by border width */
2971         xoffset += texImage->Border;
2972         yoffset += texImage->Border;
2973         zoffset += texImage->Border;
2974
2975         if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2976                                        &width, &height)) {
2977            ASSERT(ctx->Driver.CopyTexSubImage3D);
2978            ctx->Driver.CopyTexSubImage3D(ctx, target, level,
2979                                          xoffset, yoffset, zoffset,
2980                                          x, y, width, height);
2981
2982            check_gen_mipmap(ctx, target, texObj, level);
2983
2984            ctx->NewState |= _NEW_TEXTURE;
2985         }
2986      }
2987   }
2988   _mesa_unlock_texture(ctx, texObj);
2989}
2990
2991
2992
2993
2994/**********************************************************************/
2995/******                   Compressed Textures                    ******/
2996/**********************************************************************/
2997
2998
2999/**
3000 * Return expected size of a compressed texture.
3001 */
3002static GLuint
3003compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
3004                    GLenum glformat)
3005{
3006   gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
3007   return _mesa_format_image_size(mesaFormat, width, height, depth);
3008}
3009
3010
3011/*
3012 * Return compressed texture block size, in pixels.
3013 */
3014static void
3015get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
3016{
3017   gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
3018   _mesa_get_format_block_size(mesaFormat, bw, bh);
3019}
3020
3021
3022/**
3023 * Error checking for glCompressedTexImage[123]D().
3024 * \return error code or GL_NO_ERROR.
3025 */
3026static GLenum
3027compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3028                               GLenum target, GLint level,
3029                               GLenum internalFormat, GLsizei width,
3030                               GLsizei height, GLsizei depth, GLint border,
3031                               GLsizei imageSize)
3032{
3033   GLint expectedSize, maxLevels = 0, maxTextureSize;
3034
3035   if (dimensions == 1) {
3036      /* 1D compressed textures not allowed */
3037      return GL_INVALID_ENUM;
3038   }
3039   else if (dimensions == 2) {
3040      if (target == GL_PROXY_TEXTURE_2D) {
3041         maxLevels = ctx->Const.MaxTextureLevels;
3042      }
3043      else if (target == GL_TEXTURE_2D) {
3044         maxLevels = ctx->Const.MaxTextureLevels;
3045      }
3046      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3047         if (!ctx->Extensions.ARB_texture_cube_map)
3048            return GL_INVALID_ENUM; /*target*/
3049         maxLevels = ctx->Const.MaxCubeTextureLevels;
3050      }
3051      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3052               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3053         if (!ctx->Extensions.ARB_texture_cube_map)
3054            return GL_INVALID_ENUM; /*target*/
3055         maxLevels = ctx->Const.MaxCubeTextureLevels;
3056      }
3057      else {
3058         return GL_INVALID_ENUM; /*target*/
3059      }
3060   }
3061   else if (dimensions == 3) {
3062      /* 3D compressed textures not allowed */
3063      return GL_INVALID_ENUM;
3064   }
3065
3066   maxTextureSize = 1 << (maxLevels - 1);
3067
3068   /* This will detect any invalid internalFormat value */
3069   if (!is_compressed_format(ctx, internalFormat))
3070      return GL_INVALID_ENUM;
3071
3072   /* This should really never fail */
3073   if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3074      return GL_INVALID_ENUM;
3075
3076   if (border != 0)
3077      return GL_INVALID_VALUE;
3078
3079   /*
3080    * XXX We should probably use the proxy texture error check function here.
3081    */
3082   if (width < 1 || width > maxTextureSize ||
3083       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
3084      return GL_INVALID_VALUE;
3085
3086   if ((height < 1 || height > maxTextureSize ||
3087       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
3088       && dimensions > 1)
3089      return GL_INVALID_VALUE;
3090
3091   if ((depth < 1 || depth > maxTextureSize ||
3092       (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
3093       && dimensions > 2)
3094      return GL_INVALID_VALUE;
3095
3096   /* For cube map, width must equal height */
3097   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3098       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3099      return GL_INVALID_VALUE;
3100
3101   if (level < 0 || level >= maxLevels)
3102      return GL_INVALID_VALUE;
3103
3104   expectedSize = compressed_tex_size(width, height, depth, internalFormat);
3105   if (expectedSize != imageSize)
3106      return GL_INVALID_VALUE;
3107
3108#if FEATURE_EXT_texture_sRGB
3109   if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3110        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3111        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3112        internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3113       && border != 0) {
3114      return GL_INVALID_OPERATION;
3115   }
3116#endif
3117
3118   return GL_NO_ERROR;
3119}
3120
3121
3122/**
3123 * Error checking for glCompressedTexSubImage[123]D().
3124 * \warning  There are some bad assumptions here about the size of compressed
3125 *           texture tiles (multiple of 4) used to test the validity of the
3126 *           offset and size parameters.
3127 * \return error code or GL_NO_ERROR.
3128 */
3129static GLenum
3130compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3131                                  GLenum target, GLint level,
3132                                  GLint xoffset, GLint yoffset, GLint zoffset,
3133                                  GLsizei width, GLsizei height, GLsizei depth,
3134                                  GLenum format, GLsizei imageSize)
3135{
3136   GLint expectedSize, maxLevels = 0, maxTextureSize;
3137   GLuint bw, bh;
3138   (void) zoffset;
3139
3140   if (dimensions == 1) {
3141      /* 1D compressed textures not allowed */
3142      return GL_INVALID_ENUM;
3143   }
3144   else if (dimensions == 2) {
3145      if (target == GL_PROXY_TEXTURE_2D) {
3146         maxLevels = ctx->Const.MaxTextureLevels;
3147      }
3148      else if (target == GL_TEXTURE_2D) {
3149         maxLevels = ctx->Const.MaxTextureLevels;
3150      }
3151      else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3152         if (!ctx->Extensions.ARB_texture_cube_map)
3153            return GL_INVALID_ENUM; /*target*/
3154         maxLevels = ctx->Const.MaxCubeTextureLevels;
3155      }
3156      else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3157               target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3158         if (!ctx->Extensions.ARB_texture_cube_map)
3159            return GL_INVALID_ENUM; /*target*/
3160         maxLevels = ctx->Const.MaxCubeTextureLevels;
3161      }
3162      else {
3163         return GL_INVALID_ENUM; /*target*/
3164      }
3165   }
3166   else if (dimensions == 3) {
3167      /* 3D compressed textures not allowed */
3168      return GL_INVALID_ENUM;
3169   }
3170
3171   maxTextureSize = 1 << (maxLevels - 1);
3172
3173   /* this will catch any invalid compressed format token */
3174   if (!is_compressed_format(ctx, format))
3175      return GL_INVALID_ENUM;
3176
3177   if (width < 1 || width > maxTextureSize)
3178      return GL_INVALID_VALUE;
3179
3180   if ((height < 1 || height > maxTextureSize)
3181       && dimensions > 1)
3182      return GL_INVALID_VALUE;
3183
3184   if (level < 0 || level >= maxLevels)
3185      return GL_INVALID_VALUE;
3186
3187   /*
3188    * do checks which depend on compression block size
3189    */
3190   get_compressed_block_size(format, &bw, &bh);
3191
3192   if ((xoffset % bw != 0) || (yoffset % bh != 0))
3193      return GL_INVALID_VALUE;
3194
3195   if ((width % bw != 0) && width != 2 && width != 1)
3196      return GL_INVALID_VALUE;
3197
3198   if ((height % bh != 0) && height != 2 && height != 1)
3199      return GL_INVALID_VALUE;
3200
3201   expectedSize = compressed_tex_size(width, height, depth, format);
3202   if (expectedSize != imageSize)
3203      return GL_INVALID_VALUE;
3204
3205   return GL_NO_ERROR;
3206}
3207
3208
3209/**
3210 * Do second part of glCompressedTexSubImage error checking.
3211 * \return GL_TRUE if error found, GL_FALSE otherwise.
3212 */
3213static GLboolean
3214compressed_subtexture_error_check2(GLcontext *ctx, GLuint dims,
3215                                   GLsizei width, GLsizei height,
3216                                   GLsizei depth, GLenum format,
3217                                   struct gl_texture_image *texImage)
3218{
3219
3220   if ((GLint) format != texImage->InternalFormat) {
3221      _mesa_error(ctx, GL_INVALID_OPERATION,
3222                  "glCompressedTexSubImage%uD(format=0x%x)", dims, format);
3223      return GL_TRUE;
3224   }
3225
3226   if (((width == 1 || width == 2) &&
3227        (GLuint) width != texImage->Width) ||
3228       (width > texImage->Width)) {
3229      _mesa_error(ctx, GL_INVALID_VALUE,
3230                  "glCompressedTexSubImage%uD(width=%d)", dims, width);
3231      return GL_TRUE;
3232   }
3233
3234   if (dims >= 2) {
3235      if (((height == 1 || height == 2) &&
3236           (GLuint) height != texImage->Height) ||
3237          (height > texImage->Height)) {
3238         _mesa_error(ctx, GL_INVALID_VALUE,
3239                     "glCompressedTexSubImage%uD(height=%d)", dims, height);
3240         return GL_TRUE;
3241      }
3242   }
3243
3244   if (dims >= 3) {
3245      if (((depth == 1 || depth == 2) &&
3246           (GLuint) depth != texImage->Depth) ||
3247          (depth > texImage->Depth)) {
3248         _mesa_error(ctx, GL_INVALID_VALUE,
3249                     "glCompressedTexSubImage%uD(depth=%d)", dims, depth);
3250         return GL_TRUE;
3251      }
3252   }
3253
3254   return GL_FALSE;
3255}
3256
3257
3258
3259void GLAPIENTRY
3260_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3261                              GLenum internalFormat, GLsizei width,
3262                              GLint border, GLsizei imageSize,
3263                              const GLvoid *data)
3264{
3265   GET_CURRENT_CONTEXT(ctx);
3266   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3267
3268   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3269      _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n",
3270                  _mesa_lookup_enum_by_nr(target), level,
3271                  _mesa_lookup_enum_by_nr(internalFormat),
3272                  width, border, imageSize, data);
3273
3274   if (target == GL_TEXTURE_1D) {
3275      /* non-proxy target */
3276      struct gl_texture_object *texObj;
3277      struct gl_texture_image *texImage;
3278      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3279                               internalFormat, width, 1, 1, border, imageSize);
3280      if (error) {
3281         _mesa_error(ctx, error, "glCompressedTexImage1D");
3282         return;
3283      }
3284
3285      texObj = _mesa_get_current_tex_object(ctx, target);
3286
3287      _mesa_lock_texture(ctx, texObj);
3288      {
3289	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3290	 if (!texImage) {
3291	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3292	 }
3293         else {
3294            if (texImage->Data) {
3295               ctx->Driver.FreeTexImageData( ctx, texImage );
3296            }
3297            ASSERT(texImage->Data == NULL);
3298
3299            _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3300                                       border, internalFormat);
3301
3302            /* Choose actual texture format */
3303            texImage->TexFormat =
3304               ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
3305                                               GL_NONE, GL_NONE);
3306            ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
3307
3308            ASSERT(ctx->Driver.CompressedTexImage1D);
3309            ctx->Driver.CompressedTexImage1D(ctx, target, level,
3310                                             internalFormat, width, border,
3311                                             imageSize, data,
3312                                             texObj, texImage);
3313
3314            _mesa_set_fetch_functions(texImage, 1);
3315
3316            check_gen_mipmap(ctx, target, texObj, level);
3317
3318            /* state update */
3319            texObj->_Complete = GL_FALSE;
3320            ctx->NewState |= _NEW_TEXTURE;
3321         }
3322      }
3323      _mesa_unlock_texture(ctx, texObj);
3324   }
3325   else if (target == GL_PROXY_TEXTURE_1D) {
3326      /* Proxy texture: check for errors and update proxy state */
3327      GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3328                               internalFormat, width, 1, 1, border, imageSize);
3329      if (!error) {
3330         ASSERT(ctx->Driver.TestProxyTexImage);
3331         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3332                                             internalFormat, GL_NONE, GL_NONE,
3333                                             width, 1, 1, border);
3334      }
3335      if (error) {
3336         /* if error, clear all proxy texture image parameters */
3337         struct gl_texture_image *texImage;
3338         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3339         if (texImage)
3340            clear_teximage_fields(texImage);
3341      }
3342      else {
3343         /* store the teximage parameters */
3344         struct gl_texture_object *texObj;
3345         struct gl_texture_image *texImage;
3346
3347         texObj = _mesa_get_current_tex_object(ctx, target);
3348
3349	 _mesa_lock_texture(ctx, texObj);
3350	 {
3351	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3352	    _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3353				       border, internalFormat);
3354	 }
3355	 _mesa_unlock_texture(ctx, texObj);
3356      }
3357   }
3358   else {
3359      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3360      return;
3361   }
3362}
3363
3364
3365void GLAPIENTRY
3366_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3367                              GLenum internalFormat, GLsizei width,
3368                              GLsizei height, GLint border, GLsizei imageSize,
3369                              const GLvoid *data)
3370{
3371   GET_CURRENT_CONTEXT(ctx);
3372   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3373
3374   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3375      _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n",
3376                  _mesa_lookup_enum_by_nr(target), level,
3377                  _mesa_lookup_enum_by_nr(internalFormat),
3378                  width, height, border, imageSize, data);
3379
3380   if (target == GL_TEXTURE_2D ||
3381       (ctx->Extensions.ARB_texture_cube_map &&
3382        target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3383        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3384      /* non-proxy target */
3385      struct gl_texture_object *texObj;
3386      struct gl_texture_image *texImage;
3387
3388      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3389                          internalFormat, width, height, 1, border, imageSize);
3390      if (error) {
3391         _mesa_error(ctx, error, "glCompressedTexImage2D");
3392         return;
3393      }
3394
3395      texObj = _mesa_get_current_tex_object(ctx, target);
3396
3397      _mesa_lock_texture(ctx, texObj);
3398      {
3399	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3400	 if (!texImage) {
3401	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3402	 }
3403         else {
3404            if (texImage->Data) {
3405               ctx->Driver.FreeTexImageData( ctx, texImage );
3406            }
3407            ASSERT(texImage->Data == NULL);
3408
3409            _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3410                                       border, internalFormat);
3411
3412            /* Choose actual texture format */
3413            texImage->TexFormat =
3414               ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
3415                                               GL_NONE, GL_NONE);
3416            ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
3417
3418            ASSERT(ctx->Driver.CompressedTexImage2D);
3419            ctx->Driver.CompressedTexImage2D(ctx, target, level,
3420                                             internalFormat, width, height,
3421                                             border, imageSize, data,
3422                                             texObj, texImage);
3423
3424            _mesa_set_fetch_functions(texImage, 2);
3425
3426            check_gen_mipmap(ctx, target, texObj, level);
3427
3428            /* state update */
3429            texObj->_Complete = GL_FALSE;
3430            ctx->NewState |= _NEW_TEXTURE;
3431         }
3432      }
3433      _mesa_unlock_texture(ctx, texObj);
3434   }
3435   else if (target == GL_PROXY_TEXTURE_2D ||
3436            (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3437             ctx->Extensions.ARB_texture_cube_map)) {
3438      /* Proxy texture: check for errors and update proxy state */
3439      GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3440                          internalFormat, width, height, 1, border, imageSize);
3441      if (!error) {
3442         ASSERT(ctx->Driver.TestProxyTexImage);
3443         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3444                                              internalFormat, GL_NONE, GL_NONE,
3445                                              width, height, 1, border);
3446      }
3447      if (error) {
3448         /* if error, clear all proxy texture image parameters */
3449         struct gl_texture_image *texImage;
3450         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3451         if (texImage)
3452            clear_teximage_fields(texImage);
3453      }
3454      else {
3455         /* store the teximage parameters */
3456         struct gl_texture_object *texObj;
3457         struct gl_texture_image *texImage;
3458
3459         texObj = _mesa_get_current_tex_object(ctx, target);
3460
3461	 _mesa_lock_texture(ctx, texObj);
3462	 {
3463	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3464	    _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3465				       border, internalFormat);
3466	 }
3467	 _mesa_unlock_texture(ctx, texObj);
3468      }
3469   }
3470   else {
3471      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3472      return;
3473   }
3474}
3475
3476
3477void GLAPIENTRY
3478_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3479                              GLenum internalFormat, GLsizei width,
3480                              GLsizei height, GLsizei depth, GLint border,
3481                              GLsizei imageSize, const GLvoid *data)
3482{
3483   GET_CURRENT_CONTEXT(ctx);
3484   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3485
3486   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3487      _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n",
3488                  _mesa_lookup_enum_by_nr(target), level,
3489                  _mesa_lookup_enum_by_nr(internalFormat),
3490                  width, height, depth, border, imageSize, data);
3491
3492   if (target == GL_TEXTURE_3D) {
3493      /* non-proxy target */
3494      struct gl_texture_object *texObj;
3495      struct gl_texture_image *texImage;
3496      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3497                      internalFormat, width, height, depth, border, imageSize);
3498      if (error) {
3499         _mesa_error(ctx, error, "glCompressedTexImage3D");
3500         return;
3501      }
3502
3503      texObj = _mesa_get_current_tex_object(ctx, target);
3504
3505      _mesa_lock_texture(ctx, texObj);
3506      {
3507	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3508	 if (!texImage) {
3509	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3510	 }
3511         else {
3512            if (texImage->Data) {
3513               ctx->Driver.FreeTexImageData( ctx, texImage );
3514            }
3515            ASSERT(texImage->Data == NULL);
3516
3517            _mesa_init_teximage_fields(ctx, target, texImage,
3518                                       width, height, depth,
3519                                       border, internalFormat);
3520
3521            /* Choose actual texture format */
3522            texImage->TexFormat =
3523               ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
3524                                               GL_NONE, GL_NONE);
3525            ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
3526
3527            ASSERT(ctx->Driver.CompressedTexImage3D);
3528            ctx->Driver.CompressedTexImage3D(ctx, target, level,
3529                                             internalFormat,
3530                                             width, height, depth,
3531                                             border, imageSize, data,
3532                                             texObj, texImage);
3533
3534            _mesa_set_fetch_functions(texImage, 3);
3535
3536            check_gen_mipmap(ctx, target, texObj, level);
3537
3538            /* state update */
3539            texObj->_Complete = GL_FALSE;
3540            ctx->NewState |= _NEW_TEXTURE;
3541         }
3542      }
3543      _mesa_unlock_texture(ctx, texObj);
3544   }
3545   else if (target == GL_PROXY_TEXTURE_3D) {
3546      /* Proxy texture: check for errors and update proxy state */
3547      GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3548                      internalFormat, width, height, depth, border, imageSize);
3549      if (!error) {
3550         ASSERT(ctx->Driver.TestProxyTexImage);
3551         error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3552                                             internalFormat, GL_NONE, GL_NONE,
3553                                             width, height, depth, border);
3554      }
3555      if (error) {
3556         /* if error, clear all proxy texture image parameters */
3557         struct gl_texture_image *texImage;
3558         texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3559         if (texImage)
3560            clear_teximage_fields(texImage);
3561      }
3562      else {
3563         /* store the teximage parameters */
3564         struct gl_texture_object *texObj;
3565         struct gl_texture_image *texImage;
3566
3567         texObj = _mesa_get_current_tex_object(ctx, target);
3568
3569	 _mesa_lock_texture(ctx, texObj);
3570	 {
3571	    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3572	    _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3573				       depth, border, internalFormat);
3574	 }
3575	 _mesa_unlock_texture(ctx, texObj);
3576      }
3577   }
3578   else {
3579      _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3580      return;
3581   }
3582}
3583
3584
3585/**
3586 * Common helper for glCompressedTexSubImage1/2/3D().
3587 */
3588static void
3589compressed_tex_sub_image(GLuint dims, GLenum target, GLint level,
3590                         GLint xoffset, GLint yoffset, GLint zoffset,
3591                         GLsizei width, GLsizei height, GLsizei depth,
3592                         GLenum format, GLsizei imageSize, const GLvoid *data)
3593{
3594   struct gl_texture_object *texObj;
3595   struct gl_texture_image *texImage;
3596   GLenum error;
3597   GET_CURRENT_CONTEXT(ctx);
3598   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3599
3600   error = compressed_subtexture_error_check(ctx, dims, target, level,
3601                                             xoffset, 0, 0, /* pos */
3602                                             width, height, depth,   /* size */
3603                                             format, imageSize);
3604   if (error) {
3605      _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims);
3606      return;
3607   }
3608
3609   texObj = _mesa_get_current_tex_object(ctx, target);
3610
3611   _mesa_lock_texture(ctx, texObj);
3612   {
3613      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3614      assert(texImage);
3615
3616      if (compressed_subtexture_error_check2(ctx, dims, width, height, depth,
3617                                             format, texImage)) {
3618         /* error was recorded */
3619      }
3620      else if (width > 0 && height > 0 && depth > 0) {
3621         switch (dims) {
3622         case 1:
3623            if (ctx->Driver.CompressedTexSubImage1D) {
3624               ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
3625                                                   xoffset, width,
3626                                                   format, imageSize, data,
3627                                                   texObj, texImage);
3628            }
3629            break;
3630         case 2:
3631            if (ctx->Driver.CompressedTexSubImage2D) {
3632               ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
3633                                                   xoffset, yoffset,
3634                                                   width, height,
3635                                                   format, imageSize, data,
3636                                                   texObj, texImage);
3637            }
3638            break;
3639         case 3:
3640            if (ctx->Driver.CompressedTexSubImage3D) {
3641               ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
3642                                                   xoffset, yoffset, zoffset,
3643                                                   width, height, depth,
3644                                                   format, imageSize, data,
3645                                                   texObj, texImage);
3646            }
3647            break;
3648         default:
3649            ;
3650         }
3651
3652         check_gen_mipmap(ctx, target, texObj, level);
3653
3654         ctx->NewState |= _NEW_TEXTURE;
3655      }
3656   }
3657   _mesa_unlock_texture(ctx, texObj);
3658}
3659
3660
3661void GLAPIENTRY
3662_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3663                                 GLsizei width, GLenum format,
3664                                 GLsizei imageSize, const GLvoid *data)
3665{
3666   compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1,
3667                            format, imageSize, data);
3668}
3669
3670
3671void GLAPIENTRY
3672_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3673                                 GLint yoffset, GLsizei width, GLsizei height,
3674                                 GLenum format, GLsizei imageSize,
3675                                 const GLvoid *data)
3676{
3677   compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0,
3678                            width, height, 1, format, imageSize, data);
3679}
3680
3681
3682void GLAPIENTRY
3683_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3684                                 GLint yoffset, GLint zoffset, GLsizei width,
3685                                 GLsizei height, GLsizei depth, GLenum format,
3686                                 GLsizei imageSize, const GLvoid *data)
3687{
3688   compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset,
3689                            width, height, depth, format, imageSize, data);
3690}
3691
3692
3693