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