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