798201a60b0703376ddf46e4c4cdea19628b0fd1
[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 /**
2251  * Common code to implement all the glTexImage1D/2D/3D functions.
2252  */
2253 static void
2254 teximage(struct gl_context *ctx, GLuint dims,
2255          GLenum target, GLint level, GLint internalFormat,
2256          GLsizei width, GLsizei height, GLsizei depth,
2257          GLint border, GLenum format, GLenum type,
2258          const GLvoid *pixels)
2259 {
2260    GLboolean error;
2261
2262    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2263
2264    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2265       _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n",
2266                   dims,
2267                   _mesa_lookup_enum_by_nr(target), level,
2268                   _mesa_lookup_enum_by_nr(internalFormat),
2269                   width, height, depth, border,
2270                   _mesa_lookup_enum_by_nr(format),
2271                   _mesa_lookup_enum_by_nr(type), pixels);
2272
2273    internalFormat = override_internal_format(internalFormat, width, height);
2274
2275    /* target error checking */
2276    if (!legal_teximage_target(ctx, dims, target)) {
2277       _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)",
2278                   dims, _mesa_lookup_enum_by_nr(target));
2279       return;
2280    }
2281
2282    /* general error checking */
2283    error = texture_error_check(ctx, dims, target, level, internalFormat,
2284                                format, type, width, height, depth, border);
2285
2286    if (_mesa_is_proxy_texture(target)) {
2287       /* Proxy texture: just clear or set state depending on error checking */
2288       struct gl_texture_image *texImage =
2289          _mesa_get_proxy_tex_image(ctx, target, level);
2290
2291       if (error) {
2292          /* when error, clear all proxy texture image parameters */
2293          if (texImage)
2294             clear_teximage_fields(texImage);
2295       }
2296       else {
2297          /* no error, set the tex image parameters */
2298          struct gl_texture_object *texObj =
2299             _mesa_get_current_tex_object(ctx, target);
2300          gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
2301                                                            target, level,
2302                                                            internalFormat,
2303                                                            format, type);
2304
2305          if (legal_texture_size(ctx, texFormat, width, height, depth)) {
2306             _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2307                                        depth, border, internalFormat,
2308                                        texFormat);
2309          }
2310          else if (texImage) {
2311             clear_teximage_fields(texImage);
2312          }
2313       }
2314    }
2315    else {
2316       /* non-proxy target */
2317       const GLuint face = _mesa_tex_target_to_face(target);
2318       struct gl_texture_object *texObj;
2319       struct gl_texture_image *texImage;
2320
2321       if (error) {
2322          return;   /* error was recorded */
2323       }
2324
2325       if (ctx->NewState & _NEW_PIXEL)
2326          _mesa_update_state(ctx);
2327
2328       texObj = _mesa_get_current_tex_object(ctx, target);
2329
2330       _mesa_lock_texture(ctx, texObj);
2331       {
2332          texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2333
2334          if (!texImage) {
2335             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
2336          }
2337          else {
2338             gl_format texFormat;
2339
2340             ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
2341
2342             texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
2343                                                     internalFormat, format,
2344                                                     type);
2345
2346             if (legal_texture_size(ctx, texFormat, width, height, depth)) {
2347                _mesa_init_teximage_fields(ctx, target, texImage,
2348                                           width, height, depth,
2349                                           border, internalFormat, texFormat);
2350
2351                /* Give the texture to the driver.  <pixels> may be null. */
2352                ASSERT(ctx->Driver.TexImage3D);
2353                switch (dims) {
2354                case 1:
2355                   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
2356                                          width, border, format,
2357                                          type, pixels, &ctx->Unpack, texObj,
2358                                          texImage);
2359                   break;
2360                case 2:
2361                   ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
2362                                          width, height, border, format,
2363                                          type, pixels, &ctx->Unpack, texObj,
2364                                          texImage);
2365                   break;
2366                case 3:
2367                   ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
2368                                          width, height, depth, border, format,
2369                                          type, pixels, &ctx->Unpack, texObj,
2370                                          texImage);
2371                   break;
2372                default:
2373                   _mesa_problem(ctx, "invalid dims=%u in teximage()", dims);
2374                }
2375
2376                check_gen_mipmap(ctx, target, texObj, level);
2377
2378                update_fbo_texture(ctx, texObj, face, level);
2379
2380                /* state update */
2381                texObj->_Complete = GL_FALSE;
2382                ctx->NewState |= _NEW_TEXTURE;
2383             }
2384             else {
2385                _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
2386             }
2387          }
2388       }
2389       _mesa_unlock_texture(ctx, texObj);
2390    }
2391 }
2392
2393
2394 /*
2395  * Called from the API.  Note that width includes the border.
2396  */
2397 void GLAPIENTRY
2398 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2399                   GLsizei width, GLint border, GLenum format,
2400                   GLenum type, const GLvoid *pixels )
2401 {
2402    GET_CURRENT_CONTEXT(ctx);
2403    teximage(ctx, 1, target, level, internalFormat, width, 1, 1,
2404             border, format, type, pixels);
2405 }
2406
2407
2408 void GLAPIENTRY
2409 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2410                   GLsizei width, GLsizei height, GLint border,
2411                   GLenum format, GLenum type,
2412                   const GLvoid *pixels )
2413 {
2414    GET_CURRENT_CONTEXT(ctx);
2415    teximage(ctx, 2, target, level, internalFormat, width, height, 1,
2416             border, format, type, pixels);
2417 }
2418
2419
2420 /*
2421  * Called by the API or display list executor.
2422  * Note that width and height include the border.
2423  */
2424 void GLAPIENTRY
2425 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2426                   GLsizei width, GLsizei height, GLsizei depth,
2427                   GLint border, GLenum format, GLenum type,
2428                   const GLvoid *pixels )
2429 {
2430    GET_CURRENT_CONTEXT(ctx);
2431    teximage(ctx, 3, target, level, internalFormat, width, height, depth,
2432             border, format, type, pixels);
2433 }
2434
2435
2436 void GLAPIENTRY
2437 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2438                      GLsizei width, GLsizei height, GLsizei depth,
2439                      GLint border, GLenum format, GLenum type,
2440                      const GLvoid *pixels )
2441 {
2442    _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2443                     depth, border, format, type, pixels);
2444 }
2445
2446
2447 #if FEATURE_OES_EGL_image
2448 void GLAPIENTRY
2449 _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
2450 {
2451    struct gl_texture_object *texObj;
2452    struct gl_texture_image *texImage;
2453    GET_CURRENT_CONTEXT(ctx);
2454    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2455
2456    if (!ctx->Extensions.OES_EGL_image) {
2457       _mesa_error(ctx, GL_INVALID_OPERATION,
2458                   "glEGLImageTargetTexture2DOES(unsupported)");
2459       return;
2460    }
2461
2462    if (target != GL_TEXTURE_2D) {
2463       _mesa_error(ctx, GL_INVALID_ENUM,
2464                   "glEGLImageTargetTexture2D(target=%d)", target);
2465       return;
2466    }
2467
2468    if (ctx->NewState & _NEW_PIXEL)
2469       _mesa_update_state(ctx);
2470
2471    texObj = _mesa_get_current_tex_object(ctx, target);
2472    _mesa_lock_texture(ctx, texObj);
2473
2474    texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
2475    if (!texImage) {
2476       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D");
2477    } else {
2478       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
2479
2480       ctx->Driver.EGLImageTargetTexture2D(ctx, target,
2481                                           texObj, texImage, image);
2482
2483       /* state update */
2484       texObj->_Complete = GL_FALSE;
2485       ctx->NewState |= _NEW_TEXTURE;
2486    }
2487    _mesa_unlock_texture(ctx, texObj);
2488
2489 }
2490 #endif
2491
2492
2493
2494 /**
2495  * Implement all the glTexSubImage1/2/3D() functions.
2496  */
2497 static void
2498 texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
2499             GLint xoffset, GLint yoffset, GLint zoffset,
2500             GLsizei width, GLsizei height, GLsizei depth,
2501             GLenum format, GLenum type, const GLvoid *pixels )
2502 {
2503    struct gl_texture_object *texObj;
2504    struct gl_texture_image *texImage;
2505
2506    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2507
2508    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2509       _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n",
2510                   dims,
2511                   _mesa_lookup_enum_by_nr(target), level,
2512                   xoffset, yoffset, zoffset, width, height, depth,
2513                   _mesa_lookup_enum_by_nr(format),
2514                   _mesa_lookup_enum_by_nr(type), pixels);
2515
2516    /* check target (proxies not allowed) */
2517    if (!legal_texsubimage_target(ctx, dims, target)) {
2518       _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
2519                   dims, _mesa_lookup_enum_by_nr(target));
2520       return;
2521    }       
2522
2523    if (ctx->NewState & _NEW_PIXEL)
2524       _mesa_update_state(ctx);
2525
2526    if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset,
2527                               width, height, depth, format, type)) {
2528       return;   /* error was detected */
2529    }
2530
2531    texObj = _mesa_get_current_tex_object(ctx, target);
2532
2533    _mesa_lock_texture(ctx, texObj);
2534    {
2535       texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2536
2537       if (subtexture_error_check2(ctx, dims, target, level,
2538                                   xoffset, yoffset, zoffset,
2539                                   width, height, depth,
2540                                   format, type, texImage)) {
2541          /* error was recorded */
2542       }
2543       else if (width > 0 && height > 0 && depth > 0) {
2544          /* If we have a border, offset=-1 is legal.  Bias by border width. */
2545          switch (dims) {
2546          case 3:
2547             zoffset += texImage->Border;
2548             /* fall-through */
2549          case 2:
2550             yoffset += texImage->Border;
2551             /* fall-through */
2552          case 1:
2553             xoffset += texImage->Border;
2554          }
2555
2556          switch (dims) {
2557          case 1:
2558             ctx->Driver.TexSubImage1D(ctx, target, level,
2559                                       xoffset, width,
2560                                       format, type, pixels,
2561                                       &ctx->Unpack, texObj, texImage );
2562             break;
2563          case 2:
2564             ctx->Driver.TexSubImage2D(ctx, target, level,
2565                                       xoffset, yoffset, width, height,
2566                                       format, type, pixels,
2567                                       &ctx->Unpack, texObj, texImage );
2568             break;
2569          case 3:
2570             ctx->Driver.TexSubImage3D(ctx, target, level,
2571                                       xoffset, yoffset, zoffset,
2572                                       width, height, depth,
2573                                       format, type, pixels,
2574                                       &ctx->Unpack, texObj, texImage );
2575             break;
2576          default:
2577             _mesa_problem(ctx, "unexpected dims in subteximage()");
2578          }
2579
2580          check_gen_mipmap(ctx, target, texObj, level);
2581
2582          ctx->NewState |= _NEW_TEXTURE;
2583       }
2584    }
2585    _mesa_unlock_texture(ctx, texObj);
2586 }
2587
2588
2589 void GLAPIENTRY
2590 _mesa_TexSubImage1D( GLenum target, GLint level,
2591                      GLint xoffset, GLsizei width,
2592                      GLenum format, GLenum type,
2593                      const GLvoid *pixels )
2594 {
2595    GET_CURRENT_CONTEXT(ctx);
2596    texsubimage(ctx, 1, target, level,
2597                xoffset, 0, 0,
2598                width, 1, 1,
2599                format, type, pixels);
2600 }
2601
2602
2603 void GLAPIENTRY
2604 _mesa_TexSubImage2D( GLenum target, GLint level,
2605                      GLint xoffset, GLint yoffset,
2606                      GLsizei width, GLsizei height,
2607                      GLenum format, GLenum type,
2608                      const GLvoid *pixels )
2609 {
2610    GET_CURRENT_CONTEXT(ctx);
2611    texsubimage(ctx, 2, target, level,
2612                xoffset, yoffset, 0,
2613                width, height, 1,
2614                format, type, pixels);
2615 }
2616
2617
2618
2619 void GLAPIENTRY
2620 _mesa_TexSubImage3D( GLenum target, GLint level,
2621                      GLint xoffset, GLint yoffset, GLint zoffset,
2622                      GLsizei width, GLsizei height, GLsizei depth,
2623                      GLenum format, GLenum type,
2624                      const GLvoid *pixels )
2625 {
2626    GET_CURRENT_CONTEXT(ctx);
2627    texsubimage(ctx, 3, target, level,
2628                xoffset, yoffset, zoffset,
2629                width, height, depth,
2630                format, type, pixels);
2631 }
2632
2633
2634
2635 /**
2636  * Implement the glCopyTexImage1/2D() functions.
2637  */
2638 static void
2639 copyteximage(struct gl_context *ctx, GLuint dims,
2640              GLenum target, GLint level, GLenum internalFormat,
2641              GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
2642 {
2643    struct gl_texture_object *texObj;
2644    struct gl_texture_image *texImage;
2645    const GLuint face = _mesa_tex_target_to_face(target);
2646
2647    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2648
2649    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2650       _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n",
2651                   dims,
2652                   _mesa_lookup_enum_by_nr(target), level,
2653                   _mesa_lookup_enum_by_nr(internalFormat),
2654                   x, y, width, height, border);
2655
2656    if (ctx->NewState & NEW_COPY_TEX_STATE)
2657       _mesa_update_state(ctx);
2658
2659    if (copytexture_error_check(ctx, dims, target, level, internalFormat,
2660                                width, height, border))
2661       return;
2662
2663    texObj = _mesa_get_current_tex_object(ctx, target);
2664
2665    _mesa_lock_texture(ctx, texObj);
2666    {
2667       texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2668
2669       if (!texImage) {
2670          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
2671       }
2672       else {
2673          /* choose actual hw format */
2674          gl_format texFormat = _mesa_choose_texture_format(ctx, texObj,
2675                                                            target, level,
2676                                                            internalFormat,
2677                                                            GL_NONE, GL_NONE);
2678
2679          if (legal_texture_size(ctx, texFormat, width, height, 1)) {
2680             GLint srcX = x, srcY = y, dstX = 0, dstY = 0;
2681
2682             /* Free old texture image */
2683             ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
2684
2685             _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
2686                                        border, internalFormat, texFormat);
2687
2688             /* Allocate texture memory (no pixel data yet) */
2689             if (dims == 1) {
2690                ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
2691                                       width, border, GL_NONE, GL_NONE, NULL,
2692                                       &ctx->Unpack, texObj, texImage);
2693             }
2694             else {
2695                ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
2696                                       width, height, border, GL_NONE, GL_NONE,
2697                                       NULL, &ctx->Unpack, texObj, texImage);
2698             }
2699
2700             if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY,
2701                                            &width, &height)) {
2702                if (dims == 1)
2703                   ctx->Driver.CopyTexSubImage1D(ctx, target, level, dstX,
2704                                                 srcX, srcY, width);
2705                                                 
2706                else
2707                   ctx->Driver.CopyTexSubImage2D(ctx, target, level, dstX, dstY,
2708                                                 srcX, srcY, width, height);
2709             }
2710
2711             check_gen_mipmap(ctx, target, texObj, level);
2712
2713             update_fbo_texture(ctx, texObj, face, level);
2714
2715             /* state update */
2716             texObj->_Complete = GL_FALSE;
2717             ctx->NewState |= _NEW_TEXTURE;
2718          }
2719          else {
2720             /* probably too large of image */
2721             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
2722          }
2723       }
2724    }
2725    _mesa_unlock_texture(ctx, texObj);
2726 }
2727
2728
2729
2730 void GLAPIENTRY
2731 _mesa_CopyTexImage1D( GLenum target, GLint level,
2732                       GLenum internalFormat,
2733                       GLint x, GLint y,
2734                       GLsizei width, GLint border )
2735 {
2736    GET_CURRENT_CONTEXT(ctx);
2737    copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border);
2738 }
2739
2740
2741
2742 void GLAPIENTRY
2743 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2744                       GLint x, GLint y, GLsizei width, GLsizei height,
2745                       GLint border )
2746 {
2747    GET_CURRENT_CONTEXT(ctx);
2748    copyteximage(ctx, 2, target, level, internalFormat,
2749                 x, y, width, height, border);
2750 }
2751
2752
2753
2754 /**
2755  * Implementation for glCopyTexSubImage1/2/3D() functions.
2756  */
2757 static void
2758 copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
2759                 GLint xoffset, GLint yoffset, GLint zoffset,
2760                 GLint x, GLint y, GLsizei width, GLsizei height)
2761 {
2762    struct gl_texture_object *texObj;
2763    struct gl_texture_image *texImage;
2764
2765    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2766
2767    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2768       _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n",
2769                   dims,
2770                   _mesa_lookup_enum_by_nr(target),
2771                   level, xoffset, yoffset, zoffset, x, y, width, height);
2772
2773    if (ctx->NewState & NEW_COPY_TEX_STATE)
2774       _mesa_update_state(ctx);
2775
2776    if (copytexsubimage_error_check1(ctx, dims, target, level))
2777       return;
2778
2779    texObj = _mesa_get_current_tex_object(ctx, target);
2780
2781    _mesa_lock_texture(ctx, texObj);
2782    {
2783       texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2784
2785       if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset,
2786                                        zoffset, width, height, texImage)) {
2787          /* error was recored */
2788       }
2789       else {
2790          /* If we have a border, offset=-1 is legal.  Bias by border width. */
2791          switch (dims) {
2792          case 3:
2793             zoffset += texImage->Border;
2794             /* fall-through */
2795          case 2:
2796             yoffset += texImage->Border;
2797             /* fall-through */
2798          case 1:
2799             xoffset += texImage->Border;
2800          }
2801
2802          if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2803                                         &width, &height)) {
2804             switch (dims) {
2805             case 1:
2806                ctx->Driver.CopyTexSubImage1D(ctx, target, level,
2807                                              xoffset, x, y, width);
2808                break;
2809             case 2:
2810                ctx->Driver.CopyTexSubImage2D(ctx, target, level,
2811                                              xoffset, yoffset,
2812                                              x, y, width, height);
2813                break;
2814             case 3:
2815                ctx->Driver.CopyTexSubImage3D(ctx, target, level,
2816                                              xoffset, yoffset, zoffset,
2817                                              x, y, width, height);
2818                break;
2819             default:
2820                _mesa_problem(ctx, "bad dims in copytexsubimage()");
2821             }
2822
2823             check_gen_mipmap(ctx, target, texObj, level);
2824
2825             ctx->NewState |= _NEW_TEXTURE;
2826          }
2827       }
2828    }
2829    _mesa_unlock_texture(ctx, texObj);
2830 }
2831
2832
2833 void GLAPIENTRY
2834 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2835                          GLint xoffset, GLint x, GLint y, GLsizei width )
2836 {
2837    GET_CURRENT_CONTEXT(ctx);
2838    copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1);
2839 }
2840
2841
2842
2843 void GLAPIENTRY
2844 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2845                          GLint xoffset, GLint yoffset,
2846                          GLint x, GLint y, GLsizei width, GLsizei height )
2847 {
2848    GET_CURRENT_CONTEXT(ctx);
2849    copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y,
2850                    width, height);
2851 }
2852
2853
2854
2855 void GLAPIENTRY
2856 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2857                          GLint xoffset, GLint yoffset, GLint zoffset,
2858                          GLint x, GLint y, GLsizei width, GLsizei height )
2859 {
2860    GET_CURRENT_CONTEXT(ctx);
2861    copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
2862                    x, y, width, height);
2863 }
2864
2865
2866
2867
2868 /**********************************************************************/
2869 /******                   Compressed Textures                    ******/
2870 /**********************************************************************/
2871
2872
2873 /**
2874  * Return expected size of a compressed texture.
2875  */
2876 static GLuint
2877 compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
2878                     GLenum glformat)
2879 {
2880    gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
2881    return _mesa_format_image_size(mesaFormat, width, height, depth);
2882 }
2883
2884
2885 /*
2886  * Return compressed texture block size, in pixels.
2887  */
2888 static void
2889 get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
2890 {
2891    gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
2892    _mesa_get_format_block_size(mesaFormat, bw, bh);
2893 }
2894
2895
2896 /**
2897  * Error checking for glCompressedTexImage[123]D().
2898  * \param reason  returns reason for error, if any
2899  * \return error code or GL_NO_ERROR.
2900  */
2901 static GLenum
2902 compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
2903                                GLenum target, GLint level,
2904                                GLenum internalFormat, GLsizei width,
2905                                GLsizei height, GLsizei depth, GLint border,
2906                                GLsizei imageSize, char **reason)
2907 {
2908    const GLenum proxyTarget = get_proxy_target(target);
2909    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
2910    GLint expectedSize;
2911    GLenum choose_format;
2912    GLenum choose_type;
2913    GLenum proxy_format;
2914
2915    *reason = ""; /* no error */
2916
2917    if (!target_can_be_compressed(ctx, target, internalFormat)) {
2918       *reason = "target";
2919       return GL_INVALID_ENUM;
2920    }
2921
2922    /* This will detect any invalid internalFormat value */
2923    if (!_mesa_is_compressed_format(ctx, internalFormat)) {
2924       *reason = "internalFormat";
2925       return GL_INVALID_ENUM;
2926    }
2927
2928    switch (internalFormat) {
2929 #if FEATURE_ES
2930    case GL_PALETTE4_RGB8_OES:
2931    case GL_PALETTE4_RGBA8_OES:
2932    case GL_PALETTE4_R5_G6_B5_OES:
2933    case GL_PALETTE4_RGBA4_OES:
2934    case GL_PALETTE4_RGB5_A1_OES:
2935    case GL_PALETTE8_RGB8_OES:
2936    case GL_PALETTE8_RGBA8_OES:
2937    case GL_PALETTE8_R5_G6_B5_OES:
2938    case GL_PALETTE8_RGBA4_OES:
2939    case GL_PALETTE8_RGB5_A1_OES:
2940       _mesa_cpal_compressed_format_type(internalFormat, &choose_format,
2941                                         &choose_type);
2942       proxy_format = choose_format;
2943
2944       /* check level */
2945       if (level > 0 || level < -maxLevels) {
2946          *reason = "level";
2947          return GL_INVALID_VALUE;
2948       }
2949
2950       if (dimensions != 2) {
2951          *reason = "compressed paletted textures must be 2D";
2952          return GL_INVALID_OPERATION;
2953       }
2954
2955       /* Figure out the expected texture size (in bytes).  This will be
2956        * checked against the actual size later.
2957        */
2958       expectedSize = _mesa_cpal_compressed_size(level, internalFormat,
2959                                                 width, height);
2960
2961       /* This is for the benefit of the TestProxyTexImage below.  It expects
2962        * level to be non-negative.  OES_compressed_paletted_texture uses a
2963        * weird mechanism where the level specified to glCompressedTexImage2D
2964        * is -(n-1) number of levels in the texture, and the data specifies the
2965        * complete mipmap stack.  This is done to ensure the palette is the
2966        * same for all levels.
2967        */
2968       level = -level;
2969       break;
2970 #endif
2971
2972    default:
2973       choose_format = GL_NONE;
2974       choose_type = GL_NONE;
2975       proxy_format = internalFormat;
2976
2977       /* check level */
2978       if (level < 0 || level >= maxLevels) {
2979          *reason = "level";
2980          return GL_INVALID_VALUE;
2981       }
2982
2983       /* Figure out the expected texture size (in bytes).  This will be
2984        * checked against the actual size later.
2985        */
2986       expectedSize = compressed_tex_size(width, height, depth, internalFormat);
2987       break;
2988    }
2989
2990    /* This should really never fail */
2991    if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
2992       *reason = "internalFormat";
2993       return GL_INVALID_ENUM;
2994    }
2995
2996    /* No compressed formats support borders at this time */
2997    if (border != 0) {
2998       *reason = "border != 0";
2999       return GL_INVALID_VALUE;
3000    }
3001
3002    /* For cube map, width must equal height */
3003    if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3004        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) {
3005       *reason = "width != height";
3006       return GL_INVALID_VALUE;
3007    }
3008
3009    /* check image size against compression block size */
3010    {
3011       gl_format texFormat =
3012          ctx->Driver.ChooseTextureFormat(ctx, proxy_format,
3013                                          choose_format, choose_type);
3014       GLuint bw, bh;
3015
3016       _mesa_get_format_block_size(texFormat, &bw, &bh);
3017       if ((width > bw && width % bw > 0) ||
3018           (height > bh && height % bh > 0)) {
3019          /*
3020           * Per GL_ARB_texture_compression:  GL_INVALID_OPERATION is
3021           * generated [...] if any parameter combinations are not
3022           * supported by the specific compressed internal format. 
3023           */
3024          *reason = "invalid width or height for compression format";
3025          return GL_INVALID_OPERATION;
3026       }
3027    }
3028
3029    /* check image sizes */
3030    if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level,
3031                                       proxy_format, choose_format,
3032                                       choose_type,
3033                                       width, height, depth, border)) {
3034       /* See error comment above */
3035       *reason = "invalid width, height or format";
3036       return GL_INVALID_OPERATION;
3037    }
3038
3039    /* check image size in bytes */
3040    if (expectedSize != imageSize) {
3041       /* Per GL_ARB_texture_compression:  GL_INVALID_VALUE is generated [...]
3042        * if <imageSize> is not consistent with the format, dimensions, and
3043        * contents of the specified image.
3044        */
3045       *reason = "imageSize inconsistant with width/height/format";
3046       return GL_INVALID_VALUE;
3047    }
3048
3049    return GL_NO_ERROR;
3050 }
3051
3052
3053 /**
3054  * Error checking for glCompressedTexSubImage[123]D().
3055  * \warning  There are some bad assumptions here about the size of compressed
3056  *           texture tiles (multiple of 4) used to test the validity of the
3057  *           offset and size parameters.
3058  * \return error code or GL_NO_ERROR.
3059  */
3060 static GLenum
3061 compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions,
3062                                   GLenum target, GLint level,
3063                                   GLint xoffset, GLint yoffset, GLint zoffset,
3064                                   GLsizei width, GLsizei height, GLsizei depth,
3065                                   GLenum format, GLsizei imageSize)
3066 {
3067    GLint expectedSize, maxLevels = 0, maxTextureSize;
3068    GLuint bw, bh;
3069    (void) zoffset;
3070
3071    if (dimensions == 1) {
3072       /* 1D compressed textures not allowed */
3073       return GL_INVALID_ENUM;
3074    }
3075    else if (dimensions == 2) {
3076       if (target == GL_PROXY_TEXTURE_2D) {
3077          maxLevels = ctx->Const.MaxTextureLevels;
3078       }
3079       else if (target == GL_TEXTURE_2D) {
3080          maxLevels = ctx->Const.MaxTextureLevels;
3081       }
3082       else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3083          if (!ctx->Extensions.ARB_texture_cube_map)
3084             return GL_INVALID_ENUM; /*target*/
3085          maxLevels = ctx->Const.MaxCubeTextureLevels;
3086       }
3087       else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3088                target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3089          if (!ctx->Extensions.ARB_texture_cube_map)
3090             return GL_INVALID_ENUM; /*target*/
3091          maxLevels = ctx->Const.MaxCubeTextureLevels;
3092       }
3093       else {
3094          return GL_INVALID_ENUM; /*target*/
3095       }
3096    }
3097    else if (dimensions == 3) {
3098       /* 3D compressed textures not allowed */
3099       return GL_INVALID_ENUM;
3100    }
3101
3102    maxTextureSize = 1 << (maxLevels - 1);
3103
3104    /* this will catch any invalid compressed format token */
3105    if (!_mesa_is_compressed_format(ctx, format))
3106       return GL_INVALID_ENUM;
3107
3108    if (width < 1 || width > maxTextureSize)
3109       return GL_INVALID_VALUE;
3110
3111    if ((height < 1 || height > maxTextureSize)
3112        && dimensions > 1)
3113       return GL_INVALID_VALUE;
3114
3115    if (level < 0 || level >= maxLevels)
3116       return GL_INVALID_VALUE;
3117
3118    /*
3119     * do checks which depend on compression block size
3120     */
3121    get_compressed_block_size(format, &bw, &bh);
3122
3123    if ((xoffset % bw != 0) || (yoffset % bh != 0))
3124       return GL_INVALID_VALUE;
3125
3126    if ((width % bw != 0) && width != 2 && width != 1)
3127       return GL_INVALID_VALUE;
3128
3129    if ((height % bh != 0) && height != 2 && height != 1)
3130       return GL_INVALID_VALUE;
3131
3132    expectedSize = compressed_tex_size(width, height, depth, format);
3133    if (expectedSize != imageSize)
3134       return GL_INVALID_VALUE;
3135
3136    return GL_NO_ERROR;
3137 }
3138
3139
3140 /**
3141  * Do second part of glCompressedTexSubImage error checking.
3142  * \return GL_TRUE if error found, GL_FALSE otherwise.
3143  */
3144 static GLboolean
3145 compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims,
3146                                    GLsizei width, GLsizei height,
3147                                    GLsizei depth, GLenum format,
3148                                    struct gl_texture_image *texImage)
3149 {
3150
3151    if ((GLint) format != texImage->InternalFormat) {
3152       _mesa_error(ctx, GL_INVALID_OPERATION,
3153                   "glCompressedTexSubImage%uD(format=0x%x)", dims, format);
3154       return GL_TRUE;
3155    }
3156
3157    if (((width == 1 || width == 2) &&
3158         width != (GLsizei) texImage->Width) ||
3159        (width > (GLsizei) texImage->Width)) {
3160       _mesa_error(ctx, GL_INVALID_VALUE,
3161                   "glCompressedTexSubImage%uD(width=%d)", dims, width);
3162       return GL_TRUE;
3163    }
3164
3165    if (dims >= 2) {
3166       if (((height == 1 || height == 2) &&
3167            height != (GLsizei) texImage->Height) ||
3168           (height > (GLsizei) texImage->Height)) {
3169          _mesa_error(ctx, GL_INVALID_VALUE,
3170                      "glCompressedTexSubImage%uD(height=%d)", dims, height);
3171          return GL_TRUE;
3172       }
3173    }
3174
3175    if (dims >= 3) {
3176       if (((depth == 1 || depth == 2) &&
3177            depth != (GLsizei) texImage->Depth) ||
3178           (depth > (GLsizei) texImage->Depth)) {
3179          _mesa_error(ctx, GL_INVALID_VALUE,
3180                      "glCompressedTexSubImage%uD(depth=%d)", dims, depth);
3181          return GL_TRUE;
3182       }
3183    }
3184
3185    return GL_FALSE;
3186 }
3187
3188
3189 /**
3190  * Implementation of the glCompressedTexImage1/2/3D() functions.
3191  */
3192 static void
3193 compressedteximage(struct gl_context *ctx, GLuint dims,
3194                    GLenum target, GLint level,
3195                    GLenum internalFormat, GLsizei width,
3196                    GLsizei height, GLsizei depth, GLint border,
3197                    GLsizei imageSize, const GLvoid *data)
3198 {
3199    GLenum error;
3200    char *reason = "";
3201
3202    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3203
3204    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3205       _mesa_debug(ctx,
3206                   "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n",
3207                   dims,
3208                   _mesa_lookup_enum_by_nr(target), level,
3209                   _mesa_lookup_enum_by_nr(internalFormat),
3210                   width, height, depth, border, imageSize, data);
3211
3212    /* check target */
3213    if (!legal_teximage_target(ctx, dims, target)) {
3214       _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)",
3215                   dims, _mesa_lookup_enum_by_nr(target));
3216       return;
3217    }
3218
3219    error = compressed_texture_error_check(ctx, dims, target, level,
3220                                           internalFormat, width, height, depth,
3221                                           border, imageSize, &reason);
3222
3223    if (error) {
3224       _mesa_error(ctx, error, "glCompressedTexImage%uD(%s)", dims, reason);
3225       return;
3226    }
3227
3228 #if FEATURE_ES
3229    /* XXX this is kind of a hack */
3230    if (dims == 2) {
3231       switch (internalFormat) {
3232       case GL_PALETTE4_RGB8_OES:
3233       case GL_PALETTE4_RGBA8_OES:
3234       case GL_PALETTE4_R5_G6_B5_OES:
3235       case GL_PALETTE4_RGBA4_OES:
3236       case GL_PALETTE4_RGB5_A1_OES:
3237       case GL_PALETTE8_RGB8_OES:
3238       case GL_PALETTE8_RGBA8_OES:
3239       case GL_PALETTE8_R5_G6_B5_OES:
3240       case GL_PALETTE8_RGBA4_OES:
3241       case GL_PALETTE8_RGB5_A1_OES:
3242          _mesa_cpal_compressed_teximage2d(target, level, internalFormat,
3243                                           width, height, imageSize, data);
3244          return;
3245       }
3246    }
3247 #endif
3248
3249    if (_mesa_is_proxy_texture(target)) {
3250       /* Proxy texture: just check for errors and update proxy state */
3251       struct gl_texture_image *texImage;
3252
3253       if (!error) {
3254          struct gl_texture_object *texObj =
3255             _mesa_get_current_tex_object(ctx, target);
3256          gl_format texFormat =
3257             _mesa_choose_texture_format(ctx, texObj, target, level,
3258                                         internalFormat, GL_NONE, GL_NONE);
3259          if (!legal_texture_size(ctx, texFormat, width, height, depth)) {
3260             error = GL_OUT_OF_MEMORY;
3261          }
3262       }
3263
3264       texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3265       if (texImage) {
3266          if (error) {
3267             /* if error, clear all proxy texture image parameters */
3268             clear_teximage_fields(texImage);
3269          }
3270          else {
3271             /* no error: store the teximage parameters */
3272             _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3273                                        depth, border, internalFormat,
3274                                        MESA_FORMAT_NONE);
3275          }
3276       }
3277    }
3278    else {
3279       /* non-proxy target */
3280       struct gl_texture_object *texObj;
3281       struct gl_texture_image *texImage;
3282
3283       if (error) {
3284          _mesa_error(ctx, error, "glCompressedTexImage%uD", dims);
3285          return;
3286       }
3287
3288       texObj = _mesa_get_current_tex_object(ctx, target);
3289
3290       _mesa_lock_texture(ctx, texObj);
3291       {
3292          texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3293          if (!texImage) {
3294             _mesa_error(ctx, GL_OUT_OF_MEMORY,
3295                         "glCompressedTexImage%uD", dims);
3296          }
3297          else {
3298             gl_format texFormat;
3299
3300             ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
3301
3302             texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
3303                                                     internalFormat, GL_NONE,
3304                                                     GL_NONE);
3305
3306             if (legal_texture_size(ctx, texFormat, width, height, depth)) {
3307                _mesa_init_teximage_fields(ctx, target, texImage,
3308                                           width, height, depth,
3309                                           border, internalFormat, texFormat);
3310
3311                switch (dims) {
3312                case 1:
3313                   ASSERT(ctx->Driver.CompressedTexImage1D);
3314                   ctx->Driver.CompressedTexImage1D(ctx, target, level,
3315                                                    internalFormat,
3316                                                    width,
3317                                                    border, imageSize, data,
3318                                                    texObj, texImage);
3319                   break;
3320                case 2:
3321                   ASSERT(ctx->Driver.CompressedTexImage2D);
3322                   ctx->Driver.CompressedTexImage2D(ctx, target, level,
3323                                                    internalFormat,
3324                                                    width, height,
3325                                                    border, imageSize, data,
3326                                                    texObj, texImage);
3327                   break;
3328                case 3:
3329                   ASSERT(ctx->Driver.CompressedTexImage3D);
3330                   ctx->Driver.CompressedTexImage3D(ctx, target, level,
3331                                                    internalFormat,
3332                                                    width, height, depth,
3333                                                    border, imageSize, data,
3334                                                    texObj, texImage);
3335                   break;
3336                default:
3337                   _mesa_problem(ctx, "bad dims in compressedteximage");
3338                }
3339
3340                check_gen_mipmap(ctx, target, texObj, level);
3341
3342                /* state update */
3343                texObj->_Complete = GL_FALSE;
3344                ctx->NewState |= _NEW_TEXTURE;
3345             }
3346             else {
3347                _mesa_error(ctx, GL_OUT_OF_MEMORY,
3348                            "glCompressedTexImage%uD", dims);
3349             }
3350          }
3351       }
3352       _mesa_unlock_texture(ctx, texObj);
3353    }
3354 }
3355
3356
3357 void GLAPIENTRY
3358 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3359                               GLenum internalFormat, GLsizei width,
3360                               GLint border, GLsizei imageSize,
3361                               const GLvoid *data)
3362 {
3363    GET_CURRENT_CONTEXT(ctx);
3364    compressedteximage(ctx, 1, target, level, internalFormat,
3365                       width, 1, 1, border, imageSize, data);
3366 }
3367
3368
3369 void GLAPIENTRY
3370 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3371                               GLenum internalFormat, GLsizei width,
3372                               GLsizei height, GLint border, GLsizei imageSize,
3373                               const GLvoid *data)
3374 {
3375    GET_CURRENT_CONTEXT(ctx);
3376    compressedteximage(ctx, 2, target, level, internalFormat,
3377                       width, height, 1, border, imageSize, data);
3378 }
3379
3380
3381 void GLAPIENTRY
3382 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3383                               GLenum internalFormat, GLsizei width,
3384                               GLsizei height, GLsizei depth, GLint border,
3385                               GLsizei imageSize, const GLvoid *data)
3386 {
3387    GET_CURRENT_CONTEXT(ctx);
3388    compressedteximage(ctx, 3, target, level, internalFormat,
3389                       width, height, depth, border, imageSize, data);
3390 }
3391
3392
3393 /**
3394  * Common helper for glCompressedTexSubImage1/2/3D().
3395  */
3396 static void
3397 compressed_tex_sub_image(GLuint dims, GLenum target, GLint level,
3398                          GLint xoffset, GLint yoffset, GLint zoffset,
3399                          GLsizei width, GLsizei height, GLsizei depth,
3400                          GLenum format, GLsizei imageSize, const GLvoid *data)
3401 {
3402    struct gl_texture_object *texObj;
3403    struct gl_texture_image *texImage;
3404    GLenum error;
3405    GET_CURRENT_CONTEXT(ctx);
3406    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3407
3408    error = compressed_subtexture_error_check(ctx, dims, target, level,
3409                                              xoffset, 0, 0, /* pos */
3410                                              width, height, depth,   /* size */
3411                                              format, imageSize);
3412    if (error) {
3413       _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims);
3414       return;
3415    }
3416
3417    texObj = _mesa_get_current_tex_object(ctx, target);
3418
3419    _mesa_lock_texture(ctx, texObj);
3420    {
3421       texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3422       assert(texImage);
3423
3424       if (compressed_subtexture_error_check2(ctx, dims, width, height, depth,
3425                                              format, texImage)) {
3426          /* error was recorded */
3427       }
3428       else if (width > 0 && height > 0 && depth > 0) {
3429          switch (dims) {
3430          case 1:
3431             if (ctx->Driver.CompressedTexSubImage1D) {
3432                ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
3433                                                    xoffset, width,
3434                                                    format, imageSize, data,
3435                                                    texObj, texImage);
3436             }
3437             break;
3438          case 2:
3439             if (ctx->Driver.CompressedTexSubImage2D) {
3440                ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
3441                                                    xoffset, yoffset,
3442                                                    width, height,
3443                                                    format, imageSize, data,
3444                                                    texObj, texImage);
3445             }
3446             break;
3447          case 3:
3448             if (ctx->Driver.CompressedTexSubImage3D) {
3449                ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
3450                                                    xoffset, yoffset, zoffset,
3451                                                    width, height, depth,
3452                                                    format, imageSize, data,
3453                                                    texObj, texImage);
3454             }
3455             break;
3456          default:
3457             ;
3458          }
3459
3460          check_gen_mipmap(ctx, target, texObj, level);
3461
3462          ctx->NewState |= _NEW_TEXTURE;
3463       }
3464    }
3465    _mesa_unlock_texture(ctx, texObj);
3466 }
3467
3468
3469 void GLAPIENTRY
3470 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3471                                  GLsizei width, GLenum format,
3472                                  GLsizei imageSize, const GLvoid *data)
3473 {
3474    compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1,
3475                             format, imageSize, data);
3476 }
3477
3478
3479 void GLAPIENTRY
3480 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3481                                  GLint yoffset, GLsizei width, GLsizei height,
3482                                  GLenum format, GLsizei imageSize,
3483                                  const GLvoid *data)
3484 {
3485    compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0,
3486                             width, height, 1, format, imageSize, data);
3487 }
3488
3489
3490 void GLAPIENTRY
3491 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3492                                  GLint yoffset, GLint zoffset, GLsizei width,
3493                                  GLsizei height, GLsizei depth, GLenum format,
3494                                  GLsizei imageSize, const GLvoid *data)
3495 {
3496    compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset,
3497                             width, height, depth, format, imageSize, data);
3498 }
3499
3500
3501 /**
3502  * Helper for glTexBuffer().  Check if internalFormat is legal.  If so,
3503  * return the basic data type and number of components for the format.
3504  * \param return  GL_TRUE if internalFormat is legal, GL_FALSE otherwise
3505  */
3506 static GLboolean
3507 get_sized_format_info(const struct gl_context *ctx, GLenum internalFormat,
3508                       GLenum *datatype, GLuint *components)
3509 {
3510    switch (internalFormat) {
3511    case GL_ALPHA8:
3512       *datatype = GL_UNSIGNED_BYTE;
3513       *components = 1;
3514       break;
3515    case GL_ALPHA16:
3516       *datatype = GL_UNSIGNED_SHORT;
3517       *components = 1;
3518       break;
3519    case GL_ALPHA16F_ARB:
3520       *datatype = GL_HALF_FLOAT;
3521       *components = 1;
3522       break;
3523    case GL_ALPHA32F_ARB:
3524       *datatype = GL_FLOAT;
3525       *components = 1;
3526       break;
3527    case GL_ALPHA8I_EXT:
3528       *datatype = GL_BYTE;
3529       *components = 1;
3530       break;
3531    case GL_ALPHA16I_EXT:
3532       *datatype = GL_SHORT;
3533       *components = 1;
3534       break;
3535    case GL_ALPHA32I_EXT:
3536       *datatype = GL_INT;
3537       *components = 1;
3538       break;
3539    case GL_ALPHA8UI_EXT:
3540       *datatype = GL_UNSIGNED_BYTE;
3541       *components = 1;
3542       break;
3543    case GL_ALPHA16UI_EXT:
3544       *datatype = GL_UNSIGNED_SHORT;
3545       *components = 1;
3546       break;
3547    case GL_ALPHA32UI_EXT:
3548       *datatype = GL_UNSIGNED_INT;
3549       *components = 1;
3550       break;
3551    case GL_LUMINANCE8:
3552       *datatype = GL_UNSIGNED_BYTE;
3553       *components = 1;
3554       break;
3555    case GL_LUMINANCE16:
3556       *datatype = GL_UNSIGNED_SHORT;
3557       *components = 1;
3558       break;
3559    case GL_LUMINANCE16F_ARB:
3560       *datatype = GL_HALF_FLOAT;
3561       *components = 1;
3562       break;
3563    case GL_LUMINANCE32F_ARB:
3564       *datatype = GL_FLOAT;
3565       *components = 1;
3566       break;
3567    case GL_LUMINANCE8I_EXT:
3568       *datatype = GL_BYTE;
3569       *components = 1;
3570       break;
3571    case GL_LUMINANCE16I_EXT:
3572       *datatype = GL_SHORT;
3573       *components = 1;
3574       break;
3575    case GL_LUMINANCE32I_EXT:
3576       *datatype = GL_INT;
3577       *components = 1;
3578       break;
3579    case GL_LUMINANCE8UI_EXT:
3580       *datatype = GL_UNSIGNED_BYTE;
3581       *components = 1;
3582       break;
3583    case GL_LUMINANCE16UI_EXT:
3584       *datatype = GL_UNSIGNED_SHORT;
3585       *components = 1;
3586       break;
3587    case GL_LUMINANCE32UI_EXT:
3588       *datatype = GL_UNSIGNED_INT;
3589       *components = 1;
3590       break;
3591    case GL_LUMINANCE8_ALPHA8:
3592       *datatype = GL_UNSIGNED_BYTE;
3593       *components = 2;
3594       break;
3595    case GL_LUMINANCE16_ALPHA16:
3596       *datatype = GL_UNSIGNED_SHORT;
3597       *components = 2;
3598       break;
3599    case GL_LUMINANCE_ALPHA16F_ARB:
3600       *datatype = GL_HALF_FLOAT;
3601       *components = 2;
3602       break;
3603    case GL_LUMINANCE_ALPHA32F_ARB:
3604       *datatype = GL_FLOAT;
3605       *components = 2;
3606       break;
3607    case GL_LUMINANCE_ALPHA8I_EXT:
3608       *datatype = GL_BYTE;
3609       *components = 2;
3610       break;
3611    case GL_LUMINANCE_ALPHA16I_EXT:
3612       *datatype = GL_SHORT;
3613       *components = 2;
3614       break;
3615    case GL_LUMINANCE_ALPHA32I_EXT:
3616       *datatype = GL_INT;
3617       *components = 2;
3618       break;
3619    case GL_LUMINANCE_ALPHA8UI_EXT:
3620       *datatype = GL_UNSIGNED_BYTE;
3621       *components = 2;
3622       break;
3623    case GL_LUMINANCE_ALPHA16UI_EXT:
3624       *datatype = GL_UNSIGNED_SHORT;
3625       *components = 2;
3626       break;
3627    case GL_LUMINANCE_ALPHA32UI_EXT:
3628       *datatype = GL_UNSIGNED_INT;
3629       *components = 2;
3630       break;
3631    case GL_INTENSITY8:
3632       *datatype = GL_UNSIGNED_BYTE;
3633       *components = 1;
3634       break;
3635    case GL_INTENSITY16:
3636       *datatype = GL_UNSIGNED_SHORT;
3637       *components = 1;
3638       break;
3639    case GL_INTENSITY16F_ARB:
3640       *datatype = GL_HALF_FLOAT;
3641       *components = 1;
3642       break;
3643    case GL_INTENSITY32F_ARB:
3644       *datatype = GL_FLOAT;
3645       *components = 1;
3646       break;
3647    case GL_INTENSITY8I_EXT:
3648       *datatype = GL_BYTE;
3649       *components = 1;
3650       break;
3651    case GL_INTENSITY16I_EXT:
3652       *datatype = GL_SHORT;
3653       *components = 1;
3654       break;
3655    case GL_INTENSITY32I_EXT:
3656       *datatype = GL_INT;
3657       *components = 1;
3658       break;
3659    case GL_INTENSITY8UI_EXT:
3660       *datatype = GL_UNSIGNED_BYTE;
3661       *components = 1;
3662       break;
3663    case GL_INTENSITY16UI_EXT:
3664       *datatype = GL_UNSIGNED_SHORT;
3665       *components = 1;
3666       break;
3667    case GL_INTENSITY32UI_EXT:
3668       *datatype = GL_UNSIGNED_INT;
3669       *components = 1;
3670       break;
3671    case GL_RGBA8:
3672       *datatype = GL_UNSIGNED_BYTE;
3673       *components = 4;
3674       break;
3675    case GL_RGBA16:
3676       *datatype = GL_UNSIGNED_SHORT;
3677       *components = 4;
3678       break;
3679    case GL_RGBA16F_ARB:
3680       *datatype = GL_HALF_FLOAT;
3681       *components = 4;
3682       break;
3683    case GL_RGBA32F_ARB:
3684       *datatype = GL_FLOAT;
3685       *components = 4;
3686       break;
3687    case GL_RGBA8I_EXT:
3688       *datatype = GL_BYTE;
3689       *components = 4;
3690       break;
3691    case GL_RGBA16I_EXT:
3692       *datatype = GL_SHORT;
3693       *components = 4;
3694       break;
3695    case GL_RGBA32I_EXT:
3696       *datatype = GL_INT;
3697       *components = 4;
3698       break;
3699    case GL_RGBA8UI_EXT:
3700       *datatype = GL_UNSIGNED_BYTE;
3701       *components = 4;
3702       break;
3703    case GL_RGBA16UI_EXT:
3704       *datatype = GL_UNSIGNED_SHORT;
3705       *components = 4;
3706       break;
3707    case GL_RGBA32UI_EXT:
3708       *datatype = GL_UNSIGNED_INT;
3709       *components = 4;
3710       break;
3711    default:
3712       return GL_FALSE;
3713    }
3714
3715    if (*datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float)
3716       return GL_FALSE;
3717
3718    if (*datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel)
3719       return GL_FALSE;
3720
3721    return GL_TRUE;
3722 }
3723
3724
3725 /** GL_ARB_texture_buffer_object */
3726 void GLAPIENTRY
3727 _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
3728 {
3729    struct gl_texture_object *texObj;
3730    struct gl_buffer_object *bufObj;
3731    GLenum dataType;
3732    GLuint comps;
3733
3734    GET_CURRENT_CONTEXT(ctx);
3735    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3736
3737    if (!ctx->Extensions.ARB_texture_buffer_object) {
3738       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer");
3739       return;
3740    }
3741
3742    if (target != GL_TEXTURE_BUFFER_ARB) {
3743       _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(target)");
3744       return;
3745    }
3746
3747    if (!get_sized_format_info(ctx, internalFormat, &dataType, &comps)) {
3748       _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)",
3749                   internalFormat);
3750       return;
3751    }
3752
3753    bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3754    if (buffer && !bufObj) {
3755       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer(buffer %u)", buffer);
3756       return;
3757    }
3758
3759    texObj = _mesa_get_current_tex_object(ctx, target);
3760
3761    _mesa_lock_texture(ctx, texObj);
3762    {
3763       _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj);
3764       texObj->BufferObjectFormat = internalFormat;
3765    }
3766    _mesa_unlock_texture(ctx, texObj);
3767 }