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