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