blob: b92907847a88dcb5f38a67e3b59fec269e2947f0 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
10#include "libANGLE/validationES.h"
11#include "libANGLE/Context.h"
12#include "libANGLE/Texture.h"
13#include "libANGLE/Framebuffer.h"
14#include "libANGLE/Renderbuffer.h"
15#include "libANGLE/formatutils.h"
16#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040017
18#include "common/mathutil.h"
19#include "common/utilities.h"
20
21namespace gl
22{
23
Geoff Langb1196682014-07-23 13:47:29 -040024bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
26 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
27{
Jamie Madill6f38f822014-06-06 17:12:20 -040028 if (!ValidTexture2DDestinationTarget(context, target))
29 {
Geoff Langb1196682014-07-23 13:47:29 -040030 context->recordError(Error(GL_INVALID_ENUM));
31 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040032 }
33
Austin Kinross08528e12015-10-07 16:24:40 -070034 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040035 {
Geoff Langb1196682014-07-23 13:47:29 -040036 context->recordError(Error(GL_INVALID_VALUE));
37 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040038 }
39
Geoff Lange8ebe7f2013-08-05 15:03:13 -040040 if (level < 0 || xoffset < 0 ||
41 std::numeric_limits<GLsizei>::max() - xoffset < width ||
42 std::numeric_limits<GLsizei>::max() - yoffset < height)
43 {
Geoff Langb1196682014-07-23 13:47:29 -040044 context->recordError(Error(GL_INVALID_VALUE));
45 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040046 }
47
Geoff Lang005df412013-10-16 14:12:50 -040048 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040049 {
Geoff Langb1196682014-07-23 13:47:29 -040050 context->recordError(Error(GL_INVALID_OPERATION));
51 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040052 }
53
Geoff Langaae65a42014-05-26 12:43:44 -040054 const gl::Caps &caps = context->getCaps();
55
Geoff Langa9be0dc2014-12-17 12:34:40 -050056 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040057 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050058 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
59 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040060 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050061 context->recordError(Error(GL_INVALID_VALUE));
62 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040063 }
Geoff Langa9be0dc2014-12-17 12:34:40 -050064 }
Geoff Lang691e58c2014-12-19 17:03:25 -050065 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -050066 {
67 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040068 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050069 context->recordError(Error(GL_INVALID_VALUE));
70 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040071 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -040072
Geoff Langa9be0dc2014-12-17 12:34:40 -050073 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
74 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
75 {
76 context->recordError(Error(GL_INVALID_VALUE));
77 return false;
78 }
79 }
80 else
81 {
Geoff Langb1196682014-07-23 13:47:29 -040082 context->recordError(Error(GL_INVALID_ENUM));
83 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040084 }
85
Geoff Lang691e58c2014-12-19 17:03:25 -050086 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -040087 if (!texture)
88 {
Geoff Langb1196682014-07-23 13:47:29 -040089 context->recordError(Error(GL_INVALID_OPERATION));
90 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040091 }
92
Geoff Langa9be0dc2014-12-17 12:34:40 -050093 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040094 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050095 if (format != GL_NONE)
96 {
Geoff Lang051dbc72015-01-05 15:48:58 -050097 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -050098 {
99 context->recordError(Error(GL_INVALID_OPERATION));
100 return false;
101 }
102 }
103
104 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
105 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
106 {
107 context->recordError(Error(GL_INVALID_VALUE));
108 return false;
109 }
110 }
111 else
112 {
Geoff Lang69cce582015-09-17 13:20:36 -0400113 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500114 {
115 context->recordError(Error(GL_INVALID_OPERATION));
116 return false;
117 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400118 }
119
120 // Verify zero border
121 if (border != 0)
122 {
Geoff Langb1196682014-07-23 13:47:29 -0400123 context->recordError(Error(GL_INVALID_VALUE));
124 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400125 }
126
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400127 if (isCompressed)
128 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400129 GLenum actualInternalFormat =
130 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400131 switch (actualInternalFormat)
132 {
133 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
134 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400135 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400136 {
Geoff Langb1196682014-07-23 13:47:29 -0400137 context->recordError(Error(GL_INVALID_ENUM));
138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400139 }
140 break;
141 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400142 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400143 {
Geoff Langb1196682014-07-23 13:47:29 -0400144 context->recordError(Error(GL_INVALID_ENUM));
145 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400146 }
147 break;
148 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400149 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400150 {
Geoff Langb1196682014-07-23 13:47:29 -0400151 context->recordError(Error(GL_INVALID_ENUM));
152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400153 }
154 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400155 case GL_ETC1_RGB8_OES:
156 if (!context->getExtensions().compressedETC1RGB8Texture)
157 {
158 context->recordError(Error(GL_INVALID_ENUM));
159 return false;
160 }
161 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400162 default:
tmartino0ccd5ae2015-10-01 14:33:14 -0400163 context->recordError(Error(
164 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
165 return false;
166 }
167 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
168 {
169 context->recordError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400171 }
172 }
173 else
174 {
175 // validate <type> by itself (used as secondary key below)
176 switch (type)
177 {
178 case GL_UNSIGNED_BYTE:
179 case GL_UNSIGNED_SHORT_5_6_5:
180 case GL_UNSIGNED_SHORT_4_4_4_4:
181 case GL_UNSIGNED_SHORT_5_5_5_1:
182 case GL_UNSIGNED_SHORT:
183 case GL_UNSIGNED_INT:
184 case GL_UNSIGNED_INT_24_8_OES:
185 case GL_HALF_FLOAT_OES:
186 case GL_FLOAT:
187 break;
188 default:
Geoff Langb1196682014-07-23 13:47:29 -0400189 context->recordError(Error(GL_INVALID_ENUM));
190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400191 }
192
193 // validate <format> + <type> combinations
194 // - invalid <format> -> sets INVALID_ENUM
195 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
196 switch (format)
197 {
198 case GL_ALPHA:
199 case GL_LUMINANCE:
200 case GL_LUMINANCE_ALPHA:
201 switch (type)
202 {
203 case GL_UNSIGNED_BYTE:
204 case GL_FLOAT:
205 case GL_HALF_FLOAT_OES:
206 break;
Geoff Langb1196682014-07-23 13:47:29 -0400207 default:
208 context->recordError(Error(GL_INVALID_OPERATION));
209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400210 }
211 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400212 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400213 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400214 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400215 {
Geoff Langb1196682014-07-23 13:47:29 -0400216 context->recordError(Error(GL_INVALID_ENUM));
217 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400218 }
219 switch (type)
220 {
221 case GL_UNSIGNED_BYTE:
222 case GL_FLOAT:
223 case GL_HALF_FLOAT_OES:
224 break;
225 default:
Geoff Langb1196682014-07-23 13:47:29 -0400226 context->recordError(Error(GL_INVALID_OPERATION));
227 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400228 }
229 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400230 case GL_RGB:
231 switch (type)
232 {
233 case GL_UNSIGNED_BYTE:
234 case GL_UNSIGNED_SHORT_5_6_5:
235 case GL_FLOAT:
236 case GL_HALF_FLOAT_OES:
237 break;
238 default:
Geoff Langb1196682014-07-23 13:47:29 -0400239 context->recordError(Error(GL_INVALID_OPERATION));
240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400241 }
242 break;
243 case GL_RGBA:
244 switch (type)
245 {
246 case GL_UNSIGNED_BYTE:
247 case GL_UNSIGNED_SHORT_4_4_4_4:
248 case GL_UNSIGNED_SHORT_5_5_5_1:
249 case GL_FLOAT:
250 case GL_HALF_FLOAT_OES:
251 break;
252 default:
Geoff Langb1196682014-07-23 13:47:29 -0400253 context->recordError(Error(GL_INVALID_OPERATION));
254 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 }
256 break;
257 case GL_BGRA_EXT:
258 switch (type)
259 {
260 case GL_UNSIGNED_BYTE:
261 break;
262 default:
Geoff Langb1196682014-07-23 13:47:29 -0400263 context->recordError(Error(GL_INVALID_OPERATION));
264 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400265 }
266 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400267 case GL_SRGB_EXT:
268 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400269 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400270 {
Geoff Langb1196682014-07-23 13:47:29 -0400271 context->recordError(Error(GL_INVALID_ENUM));
272 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400273 }
274 switch (type)
275 {
276 case GL_UNSIGNED_BYTE:
277 break;
278 default:
Geoff Langb1196682014-07-23 13:47:29 -0400279 context->recordError(Error(GL_INVALID_OPERATION));
280 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400281 }
282 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400283 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
284 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
285 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
286 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
287 break;
288 case GL_DEPTH_COMPONENT:
289 switch (type)
290 {
291 case GL_UNSIGNED_SHORT:
292 case GL_UNSIGNED_INT:
293 break;
294 default:
Geoff Langb1196682014-07-23 13:47:29 -0400295 context->recordError(Error(GL_INVALID_OPERATION));
296 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 }
298 break;
299 case GL_DEPTH_STENCIL_OES:
300 switch (type)
301 {
302 case GL_UNSIGNED_INT_24_8_OES:
303 break;
304 default:
Geoff Langb1196682014-07-23 13:47:29 -0400305 context->recordError(Error(GL_INVALID_OPERATION));
306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400307 }
308 break;
309 default:
Geoff Langb1196682014-07-23 13:47:29 -0400310 context->recordError(Error(GL_INVALID_ENUM));
311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
314 switch (format)
315 {
316 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
317 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400318 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Geoff Langb1196682014-07-23 13:47:29 -0400320 context->recordError(Error(GL_INVALID_OPERATION));
321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323 else
324 {
Geoff Langb1196682014-07-23 13:47:29 -0400325 context->recordError(Error(GL_INVALID_ENUM));
326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400327 }
328 break;
329 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400330 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 {
Geoff Langb1196682014-07-23 13:47:29 -0400332 context->recordError(Error(GL_INVALID_OPERATION));
333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400334 }
335 else
336 {
Geoff Langb1196682014-07-23 13:47:29 -0400337 context->recordError(Error(GL_INVALID_ENUM));
338 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339 }
340 break;
341 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400342 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400343 {
Geoff Langb1196682014-07-23 13:47:29 -0400344 context->recordError(Error(GL_INVALID_OPERATION));
345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400346 }
347 else
348 {
Geoff Langb1196682014-07-23 13:47:29 -0400349 context->recordError(Error(GL_INVALID_ENUM));
350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 }
352 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400353 case GL_ETC1_RGB8_OES:
354 if (context->getExtensions().compressedETC1RGB8Texture)
355 {
356 context->recordError(Error(GL_INVALID_OPERATION));
357 return false;
358 }
359 else
360 {
361 context->recordError(Error(GL_INVALID_ENUM));
362 return false;
363 }
364 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400365 case GL_DEPTH_COMPONENT:
366 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400367 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 {
Geoff Langb1196682014-07-23 13:47:29 -0400369 context->recordError(Error(GL_INVALID_VALUE));
370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371 }
372 if (target != GL_TEXTURE_2D)
373 {
Geoff Langb1196682014-07-23 13:47:29 -0400374 context->recordError(Error(GL_INVALID_OPERATION));
375 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376 }
377 // OES_depth_texture supports loading depth data and multiple levels,
378 // but ANGLE_depth_texture does not
379 if (pixels != NULL || level != 0)
380 {
Geoff Langb1196682014-07-23 13:47:29 -0400381 context->recordError(Error(GL_INVALID_OPERATION));
382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400383 }
384 break;
385 default:
386 break;
387 }
388
389 if (type == GL_FLOAT)
390 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400391 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400392 {
Geoff Langb1196682014-07-23 13:47:29 -0400393 context->recordError(Error(GL_INVALID_ENUM));
394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 }
396 }
397 else if (type == GL_HALF_FLOAT_OES)
398 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400399 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400400 {
Geoff Langb1196682014-07-23 13:47:29 -0400401 context->recordError(Error(GL_INVALID_ENUM));
402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400403 }
404 }
405 }
406
407 return true;
408}
409
410
411
Geoff Langb1196682014-07-23 13:47:29 -0400412bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400413 GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
414 GLint border)
415{
Jamie Madill560a8d82014-05-21 13:06:20 -0400416 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400417
Jamie Madill560a8d82014-05-21 13:06:20 -0400418 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
419 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400420 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400422 }
423
Shannon Woods53a94a82014-06-24 15:20:36 -0400424 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400425 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500426 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
427 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400428
429 // [OpenGL ES 2.0.24] table 3.9
430 if (isSubImage)
431 {
432 switch (textureFormat)
433 {
434 case GL_ALPHA:
435 if (colorbufferFormat != GL_ALPHA8_EXT &&
436 colorbufferFormat != GL_RGBA4 &&
437 colorbufferFormat != GL_RGB5_A1 &&
438 colorbufferFormat != GL_RGBA8_OES)
439 {
Geoff Langb1196682014-07-23 13:47:29 -0400440 context->recordError(Error(GL_INVALID_OPERATION));
441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400442 }
443 break;
444 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400445 if (colorbufferFormat != GL_R8_EXT &&
446 colorbufferFormat != GL_RG8_EXT &&
447 colorbufferFormat != GL_RGB565 &&
448 colorbufferFormat != GL_RGB8_OES &&
449 colorbufferFormat != GL_RGBA4 &&
450 colorbufferFormat != GL_RGB5_A1 &&
451 colorbufferFormat != GL_RGBA8_OES)
452 {
Geoff Langb1196682014-07-23 13:47:29 -0400453 context->recordError(Error(GL_INVALID_OPERATION));
454 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400455 }
456 break;
457 case GL_RED_EXT:
458 if (colorbufferFormat != GL_R8_EXT &&
459 colorbufferFormat != GL_RG8_EXT &&
460 colorbufferFormat != GL_RGB565 &&
461 colorbufferFormat != GL_RGB8_OES &&
462 colorbufferFormat != GL_RGBA4 &&
463 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500464 colorbufferFormat != GL_RGBA8_OES &&
465 colorbufferFormat != GL_R32F &&
466 colorbufferFormat != GL_RG32F &&
467 colorbufferFormat != GL_RGB32F &&
468 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400469 {
Geoff Langb1196682014-07-23 13:47:29 -0400470 context->recordError(Error(GL_INVALID_OPERATION));
471 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400472 }
473 break;
474 case GL_RG_EXT:
475 if (colorbufferFormat != GL_RG8_EXT &&
476 colorbufferFormat != GL_RGB565 &&
477 colorbufferFormat != GL_RGB8_OES &&
478 colorbufferFormat != GL_RGBA4 &&
479 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500480 colorbufferFormat != GL_RGBA8_OES &&
481 colorbufferFormat != GL_RG32F &&
482 colorbufferFormat != GL_RGB32F &&
483 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400484 {
Geoff Langb1196682014-07-23 13:47:29 -0400485 context->recordError(Error(GL_INVALID_OPERATION));
486 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400487 }
488 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400489 case GL_RGB:
490 if (colorbufferFormat != GL_RGB565 &&
491 colorbufferFormat != GL_RGB8_OES &&
492 colorbufferFormat != GL_RGBA4 &&
493 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500494 colorbufferFormat != GL_RGBA8_OES &&
495 colorbufferFormat != GL_RGB32F &&
496 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400497 {
Geoff Langb1196682014-07-23 13:47:29 -0400498 context->recordError(Error(GL_INVALID_OPERATION));
499 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400500 }
501 break;
502 case GL_LUMINANCE_ALPHA:
503 case GL_RGBA:
504 if (colorbufferFormat != GL_RGBA4 &&
505 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500506 colorbufferFormat != GL_RGBA8_OES &&
507 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400508 {
Geoff Langb1196682014-07-23 13:47:29 -0400509 context->recordError(Error(GL_INVALID_OPERATION));
510 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400511 }
512 break;
513 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
514 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
515 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
516 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400517 case GL_ETC1_RGB8_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400518 context->recordError(Error(GL_INVALID_OPERATION));
519 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400520 case GL_DEPTH_COMPONENT:
521 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400522 context->recordError(Error(GL_INVALID_OPERATION));
523 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400524 default:
Geoff Langb1196682014-07-23 13:47:29 -0400525 context->recordError(Error(GL_INVALID_OPERATION));
526 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400527 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500528
529 if (internalFormatInfo.type == GL_FLOAT &&
530 !context->getExtensions().textureFloat)
531 {
532 context->recordError(Error(GL_INVALID_OPERATION));
533 return false;
534 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400535 }
536 else
537 {
538 switch (internalformat)
539 {
540 case GL_ALPHA:
541 if (colorbufferFormat != GL_ALPHA8_EXT &&
542 colorbufferFormat != GL_RGBA4 &&
543 colorbufferFormat != GL_RGB5_A1 &&
544 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500545 colorbufferFormat != GL_RGBA8_OES &&
546 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400547 {
Geoff Langb1196682014-07-23 13:47:29 -0400548 context->recordError(Error(GL_INVALID_OPERATION));
549 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400550 }
551 break;
552 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400553 if (colorbufferFormat != GL_R8_EXT &&
554 colorbufferFormat != GL_RG8_EXT &&
555 colorbufferFormat != GL_RGB565 &&
556 colorbufferFormat != GL_RGB8_OES &&
557 colorbufferFormat != GL_RGBA4 &&
558 colorbufferFormat != GL_RGB5_A1 &&
559 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500560 colorbufferFormat != GL_RGBA8_OES &&
561 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400562 {
Geoff Langb1196682014-07-23 13:47:29 -0400563 context->recordError(Error(GL_INVALID_OPERATION));
564 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400565 }
566 break;
567 case GL_RED_EXT:
568 if (colorbufferFormat != GL_R8_EXT &&
569 colorbufferFormat != GL_RG8_EXT &&
570 colorbufferFormat != GL_RGB565 &&
571 colorbufferFormat != GL_RGB8_OES &&
572 colorbufferFormat != GL_RGBA4 &&
573 colorbufferFormat != GL_RGB5_A1 &&
574 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500575 colorbufferFormat != GL_RGBA8_OES &&
576 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400577 {
Geoff Langb1196682014-07-23 13:47:29 -0400578 context->recordError(Error(GL_INVALID_OPERATION));
579 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400580 }
581 break;
582 case GL_RG_EXT:
583 if (colorbufferFormat != GL_RG8_EXT &&
584 colorbufferFormat != GL_RGB565 &&
585 colorbufferFormat != GL_RGB8_OES &&
586 colorbufferFormat != GL_RGBA4 &&
587 colorbufferFormat != GL_RGB5_A1 &&
588 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500589 colorbufferFormat != GL_RGBA8_OES &&
590 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400591 {
Geoff Langb1196682014-07-23 13:47:29 -0400592 context->recordError(Error(GL_INVALID_OPERATION));
593 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400594 }
595 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400596 case GL_RGB:
597 if (colorbufferFormat != GL_RGB565 &&
598 colorbufferFormat != GL_RGB8_OES &&
599 colorbufferFormat != GL_RGBA4 &&
600 colorbufferFormat != GL_RGB5_A1 &&
601 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500602 colorbufferFormat != GL_RGBA8_OES &&
603 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 {
Geoff Langb1196682014-07-23 13:47:29 -0400605 context->recordError(Error(GL_INVALID_OPERATION));
606 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400607 }
608 break;
609 case GL_LUMINANCE_ALPHA:
610 case GL_RGBA:
611 if (colorbufferFormat != GL_RGBA4 &&
612 colorbufferFormat != GL_RGB5_A1 &&
613 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500614 colorbufferFormat != GL_RGBA8_OES &&
615 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 {
Geoff Langb1196682014-07-23 13:47:29 -0400617 context->recordError(Error(GL_INVALID_OPERATION));
618 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400619 }
620 break;
621 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
622 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400623 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624 {
Geoff Langb1196682014-07-23 13:47:29 -0400625 context->recordError(Error(GL_INVALID_OPERATION));
626 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400627 }
628 else
629 {
Geoff Langb1196682014-07-23 13:47:29 -0400630 context->recordError(Error(GL_INVALID_ENUM));
631 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400632 }
633 break;
634 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400635 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400636 {
Geoff Langb1196682014-07-23 13:47:29 -0400637 context->recordError(Error(GL_INVALID_OPERATION));
638 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400639 }
640 else
641 {
Geoff Langb1196682014-07-23 13:47:29 -0400642 context->recordError(Error(GL_INVALID_ENUM));
643 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400644 }
645 break;
646 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400647 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400648 {
Geoff Langb1196682014-07-23 13:47:29 -0400649 context->recordError(Error(GL_INVALID_OPERATION));
650 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400651 }
652 else
653 {
Geoff Langb1196682014-07-23 13:47:29 -0400654 context->recordError(Error(GL_INVALID_ENUM));
655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 }
657 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400658 case GL_ETC1_RGB8_OES:
659 if (context->getExtensions().compressedETC1RGB8Texture)
660 {
661 context->recordError(Error(GL_INVALID_OPERATION));
662 return false;
663 }
664 else
665 {
666 context->recordError(Error(GL_INVALID_ENUM));
667 return false;
668 }
669 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400670 case GL_DEPTH_COMPONENT:
671 case GL_DEPTH_COMPONENT16:
672 case GL_DEPTH_COMPONENT32_OES:
673 case GL_DEPTH_STENCIL_OES:
674 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400675 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400676 {
Geoff Langb1196682014-07-23 13:47:29 -0400677 context->recordError(Error(GL_INVALID_OPERATION));
678 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400679 }
680 else
681 {
Geoff Langb1196682014-07-23 13:47:29 -0400682 context->recordError(Error(GL_INVALID_ENUM));
683 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400684 }
685 default:
Geoff Langb1196682014-07-23 13:47:29 -0400686 context->recordError(Error(GL_INVALID_ENUM));
687 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400688 }
689 }
690
Geoff Lang784a8fd2013-09-24 12:33:16 -0400691 // If width or height is zero, it is a no-op. Return false without setting an error.
692 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400693}
694
Geoff Langb1196682014-07-23 13:47:29 -0400695bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696 GLsizei width, GLsizei height)
697{
698 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
699 {
Geoff Langb1196682014-07-23 13:47:29 -0400700 context->recordError(Error(GL_INVALID_ENUM));
701 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400702 }
703
704 if (width < 1 || height < 1 || levels < 1)
705 {
Geoff Langb1196682014-07-23 13:47:29 -0400706 context->recordError(Error(GL_INVALID_VALUE));
707 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400708 }
709
710 if (target == GL_TEXTURE_CUBE_MAP && width != height)
711 {
Geoff Langb1196682014-07-23 13:47:29 -0400712 context->recordError(Error(GL_INVALID_VALUE));
713 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400714 }
715
716 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
717 {
Geoff Langb1196682014-07-23 13:47:29 -0400718 context->recordError(Error(GL_INVALID_OPERATION));
719 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400720 }
721
Geoff Lang5d601382014-07-22 15:14:06 -0400722 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
723 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400724 {
Geoff Langb1196682014-07-23 13:47:29 -0400725 context->recordError(Error(GL_INVALID_ENUM));
726 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400727 }
728
Geoff Langaae65a42014-05-26 12:43:44 -0400729 const gl::Caps &caps = context->getCaps();
730
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731 switch (target)
732 {
733 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400734 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
735 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400736 {
Geoff Langb1196682014-07-23 13:47:29 -0400737 context->recordError(Error(GL_INVALID_VALUE));
738 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 }
740 break;
741 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400742 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
743 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400744 {
Geoff Langb1196682014-07-23 13:47:29 -0400745 context->recordError(Error(GL_INVALID_VALUE));
746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 }
748 break;
749 default:
Geoff Langb1196682014-07-23 13:47:29 -0400750 context->recordError(Error(GL_INVALID_ENUM));
751 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 }
753
Geoff Langc0b9ef42014-07-02 10:02:37 -0400754 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 {
756 if (!gl::isPow2(width) || !gl::isPow2(height))
757 {
Geoff Langb1196682014-07-23 13:47:29 -0400758 context->recordError(Error(GL_INVALID_OPERATION));
759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 }
761 }
762
763 switch (internalformat)
764 {
765 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
766 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400767 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 {
Geoff Langb1196682014-07-23 13:47:29 -0400769 context->recordError(Error(GL_INVALID_ENUM));
770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 }
772 break;
773 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400774 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 {
Geoff Langb1196682014-07-23 13:47:29 -0400776 context->recordError(Error(GL_INVALID_ENUM));
777 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400778 }
779 break;
780 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400781 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 {
Geoff Langb1196682014-07-23 13:47:29 -0400783 context->recordError(Error(GL_INVALID_ENUM));
784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 }
786 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400787 case GL_ETC1_RGB8_OES:
788 if (!context->getExtensions().compressedETC1RGB8Texture)
789 {
790 context->recordError(Error(GL_INVALID_ENUM));
791 return false;
792 }
793 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 case GL_RGBA32F_EXT:
795 case GL_RGB32F_EXT:
796 case GL_ALPHA32F_EXT:
797 case GL_LUMINANCE32F_EXT:
798 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400799 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400800 {
Geoff Langb1196682014-07-23 13:47:29 -0400801 context->recordError(Error(GL_INVALID_ENUM));
802 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 }
804 break;
805 case GL_RGBA16F_EXT:
806 case GL_RGB16F_EXT:
807 case GL_ALPHA16F_EXT:
808 case GL_LUMINANCE16F_EXT:
809 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400810 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811 {
Geoff Langb1196682014-07-23 13:47:29 -0400812 context->recordError(Error(GL_INVALID_ENUM));
813 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400814 }
815 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400816 case GL_R8_EXT:
817 case GL_RG8_EXT:
818 case GL_R16F_EXT:
819 case GL_RG16F_EXT:
820 case GL_R32F_EXT:
821 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400822 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400823 {
Geoff Langb1196682014-07-23 13:47:29 -0400824 context->recordError(Error(GL_INVALID_ENUM));
825 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400826 }
827 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828 case GL_DEPTH_COMPONENT16:
829 case GL_DEPTH_COMPONENT32_OES:
830 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400831 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 {
Geoff Langb1196682014-07-23 13:47:29 -0400833 context->recordError(Error(GL_INVALID_ENUM));
834 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 }
836 if (target != GL_TEXTURE_2D)
837 {
Geoff Langb1196682014-07-23 13:47:29 -0400838 context->recordError(Error(GL_INVALID_OPERATION));
839 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 }
841 // ANGLE_depth_texture only supports 1-level textures
842 if (levels != 1)
843 {
Geoff Langb1196682014-07-23 13:47:29 -0400844 context->recordError(Error(GL_INVALID_OPERATION));
845 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400846 }
847 break;
848 default:
849 break;
850 }
851
Geoff Lang691e58c2014-12-19 17:03:25 -0500852 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 if (!texture || texture->id() == 0)
854 {
Geoff Langb1196682014-07-23 13:47:29 -0400855 context->recordError(Error(GL_INVALID_OPERATION));
856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400857 }
858
Geoff Lang69cce582015-09-17 13:20:36 -0400859 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 {
Geoff Langb1196682014-07-23 13:47:29 -0400861 context->recordError(Error(GL_INVALID_OPERATION));
862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 }
864
865 return true;
866}
867
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400868// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400869bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870{
871 switch (format)
872 {
873 case GL_RGBA:
874 switch (type)
875 {
876 case GL_UNSIGNED_BYTE:
877 break;
878 default:
879 return false;
880 }
881 break;
882 case GL_BGRA_EXT:
883 switch (type)
884 {
885 case GL_UNSIGNED_BYTE:
886 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
887 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
888 break;
889 default:
890 return false;
891 }
892 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400893 case GL_RG_EXT:
894 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400895 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400896 {
897 return false;
898 }
899 switch (type)
900 {
901 case GL_UNSIGNED_BYTE:
902 break;
903 default:
904 return false;
905 }
906 break;
907
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400908 default:
909 return false;
910 }
911 return true;
912}
913
Austin Kinross08332632015-05-05 13:35:47 -0700914bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
915 const GLenum *attachments)
916{
917 bool defaultFramebuffer = false;
918
919 switch (target)
920 {
921 case GL_FRAMEBUFFER:
922 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
923 break;
924 default:
925 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
926 return false;
927 }
928
929 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
930}
931
Dian Xiangbf18ed02015-09-11 10:50:04 -0700932bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
933{
934 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
935 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
936 {
937 context->recordError(
938 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
939 return false;
940 }
941
942 ASSERT(context->getState().getDrawFramebuffer());
943 GLuint frameBufferId = context->getState().getDrawFramebuffer()->id();
944 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
945
946 // This should come first before the check for the default frame buffer
947 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
948 // rather than INVALID_OPERATION
949 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
950 {
951 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
952
953 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
954 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0_EXT ||
955 bufs[colorAttachment] >= maxColorAttachment))
956 {
957 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
958 // In the 3.0 specs, the error should return GL_INVALID_OPERATION.
959 // When we move to 3.1 specs, we should change the error to be GL_INVALID_ENUM
960 context->recordError(Error(GL_INVALID_OPERATION, "Invalid buffer value"));
961 return false;
962 }
963 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
964 frameBufferId != 0)
965 {
966 // INVALID_OPERATION-GL is bound to buffer and ith argument
967 // is not COLOR_ATTACHMENTi or NONE
968 context->recordError(
969 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
970 return false;
971 }
972 }
973
974 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
975 // and n is not 1 or bufs is bound to value other than BACK and NONE
976 if (frameBufferId == 0)
977 {
978 if (n != 1)
979 {
980 context->recordError(Error(GL_INVALID_OPERATION,
981 "n must be 1 when GL is bound to the default framebuffer"));
982 return false;
983 }
984
985 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
986 {
987 context->recordError(Error(
988 GL_INVALID_OPERATION,
989 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
990 return false;
991 }
992 }
993
994 return true;
995}
Austin Kinrossbc781f32015-10-26 09:27:38 -0700996
997bool ValidateBindVertexArrayOES(Context *context, GLuint array)
998{
999 if (!context->getExtensions().vertexArrayObject)
1000 {
1001 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1002 return false;
1003 }
1004
1005 return ValidateBindVertexArrayBase(context, array);
1006}
1007
1008bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1009{
1010 if (!context->getExtensions().vertexArrayObject)
1011 {
1012 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1013 return false;
1014 }
1015
1016 return ValidateDeleteVertexArraysBase(context, n);
1017}
1018
1019bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1020{
1021 if (!context->getExtensions().vertexArrayObject)
1022 {
1023 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1024 return false;
1025 }
1026
1027 return ValidateGenVertexArraysBase(context, n);
1028}
1029
1030bool ValidateIsVertexArrayOES(Context *context)
1031{
1032 if (!context->getExtensions().vertexArrayObject)
1033 {
1034 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1035 return false;
1036 }
1037
1038 return true;
1039}
Geoff Langc5629752015-12-07 16:29:04 -05001040
1041bool ValidateProgramBinaryOES(Context *context,
1042 GLuint program,
1043 GLenum binaryFormat,
1044 const void *binary,
1045 GLint length)
1046{
1047 if (!context->getExtensions().getProgramBinary)
1048 {
1049 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1050 return false;
1051 }
1052
1053 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1054}
1055
1056bool ValidateGetProgramBinaryOES(Context *context,
1057 GLuint program,
1058 GLsizei bufSize,
1059 GLsizei *length,
1060 GLenum *binaryFormat,
1061 void *binary)
1062{
1063 if (!context->getExtensions().getProgramBinary)
1064 {
1065 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1066 return false;
1067 }
1068
1069 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1070}
Geoff Lange102fee2015-12-10 11:23:30 -05001071
Geoff Lang70d0f492015-12-10 17:45:46 -05001072static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1073{
1074 switch (source)
1075 {
1076 case GL_DEBUG_SOURCE_API:
1077 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1078 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1079 case GL_DEBUG_SOURCE_OTHER:
1080 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1081 return !mustBeThirdPartyOrApplication;
1082
1083 case GL_DEBUG_SOURCE_THIRD_PARTY:
1084 case GL_DEBUG_SOURCE_APPLICATION:
1085 return true;
1086
1087 default:
1088 return false;
1089 }
1090}
1091
1092static bool ValidDebugType(GLenum type)
1093{
1094 switch (type)
1095 {
1096 case GL_DEBUG_TYPE_ERROR:
1097 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1098 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1099 case GL_DEBUG_TYPE_PERFORMANCE:
1100 case GL_DEBUG_TYPE_PORTABILITY:
1101 case GL_DEBUG_TYPE_OTHER:
1102 case GL_DEBUG_TYPE_MARKER:
1103 case GL_DEBUG_TYPE_PUSH_GROUP:
1104 case GL_DEBUG_TYPE_POP_GROUP:
1105 return true;
1106
1107 default:
1108 return false;
1109 }
1110}
1111
1112static bool ValidDebugSeverity(GLenum severity)
1113{
1114 switch (severity)
1115 {
1116 case GL_DEBUG_SEVERITY_HIGH:
1117 case GL_DEBUG_SEVERITY_MEDIUM:
1118 case GL_DEBUG_SEVERITY_LOW:
1119 case GL_DEBUG_SEVERITY_NOTIFICATION:
1120 return true;
1121
1122 default:
1123 return false;
1124 }
1125}
1126
Geoff Lange102fee2015-12-10 11:23:30 -05001127bool ValidateDebugMessageControlKHR(Context *context,
1128 GLenum source,
1129 GLenum type,
1130 GLenum severity,
1131 GLsizei count,
1132 const GLuint *ids,
1133 GLboolean enabled)
1134{
1135 if (!context->getExtensions().debug)
1136 {
1137 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1138 return false;
1139 }
1140
Geoff Lang70d0f492015-12-10 17:45:46 -05001141 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1142 {
1143 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1144 return false;
1145 }
1146
1147 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1148 {
1149 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1150 return false;
1151 }
1152
1153 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1154 {
1155 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1156 return false;
1157 }
1158
1159 if (count > 0)
1160 {
1161 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1162 {
1163 context->recordError(Error(
1164 GL_INVALID_OPERATION,
1165 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1166 return false;
1167 }
1168
1169 if (severity != GL_DONT_CARE)
1170 {
1171 context->recordError(
1172 Error(GL_INVALID_OPERATION,
1173 "If count is greater than zero, severity must be GL_DONT_CARE."));
1174 return false;
1175 }
1176 }
1177
Geoff Lange102fee2015-12-10 11:23:30 -05001178 return true;
1179}
1180
1181bool ValidateDebugMessageInsertKHR(Context *context,
1182 GLenum source,
1183 GLenum type,
1184 GLuint id,
1185 GLenum severity,
1186 GLsizei length,
1187 const GLchar *buf)
1188{
1189 if (!context->getExtensions().debug)
1190 {
1191 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1192 return false;
1193 }
1194
Geoff Lang70d0f492015-12-10 17:45:46 -05001195 if (!context->getState().getDebug().isOutputEnabled())
1196 {
1197 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1198 // not generate an error.
1199 return false;
1200 }
1201
1202 if (!ValidDebugSeverity(severity))
1203 {
1204 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1205 return false;
1206 }
1207
1208 if (!ValidDebugType(type))
1209 {
1210 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1211 return false;
1212 }
1213
1214 if (!ValidDebugSource(source, true))
1215 {
1216 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1217 return false;
1218 }
1219
1220 size_t messageLength = (length < 0) ? strlen(buf) : length;
1221 if (messageLength > context->getExtensions().maxDebugMessageLength)
1222 {
1223 context->recordError(
1224 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1225 return false;
1226 }
1227
Geoff Lange102fee2015-12-10 11:23:30 -05001228 return true;
1229}
1230
1231bool ValidateDebugMessageCallbackKHR(Context *context,
1232 GLDEBUGPROCKHR callback,
1233 const void *userParam)
1234{
1235 if (!context->getExtensions().debug)
1236 {
1237 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1238 return false;
1239 }
1240
Geoff Lange102fee2015-12-10 11:23:30 -05001241 return true;
1242}
1243
1244bool ValidateGetDebugMessageLogKHR(Context *context,
1245 GLuint count,
1246 GLsizei bufSize,
1247 GLenum *sources,
1248 GLenum *types,
1249 GLuint *ids,
1250 GLenum *severities,
1251 GLsizei *lengths,
1252 GLchar *messageLog)
1253{
1254 if (!context->getExtensions().debug)
1255 {
1256 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1257 return false;
1258 }
1259
Geoff Lang70d0f492015-12-10 17:45:46 -05001260 if (bufSize < 0 && messageLog != nullptr)
1261 {
1262 context->recordError(
1263 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1264 return false;
1265 }
1266
Geoff Lange102fee2015-12-10 11:23:30 -05001267 return true;
1268}
1269
1270bool ValidatePushDebugGroupKHR(Context *context,
1271 GLenum source,
1272 GLuint id,
1273 GLsizei length,
1274 const GLchar *message)
1275{
1276 if (!context->getExtensions().debug)
1277 {
1278 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1279 return false;
1280 }
1281
Geoff Lang70d0f492015-12-10 17:45:46 -05001282 if (!ValidDebugSource(source, true))
1283 {
1284 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1285 return false;
1286 }
1287
1288 size_t messageLength = (length < 0) ? strlen(message) : length;
1289 if (messageLength > context->getExtensions().maxDebugMessageLength)
1290 {
1291 context->recordError(
1292 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1293 return false;
1294 }
1295
1296 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1297 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1298 {
1299 context->recordError(
1300 Error(GL_STACK_OVERFLOW,
1301 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1302 return false;
1303 }
1304
Geoff Lange102fee2015-12-10 11:23:30 -05001305 return true;
1306}
1307
1308bool ValidatePopDebugGroupKHR(Context *context)
1309{
1310 if (!context->getExtensions().debug)
1311 {
1312 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1313 return false;
1314 }
1315
Geoff Lang70d0f492015-12-10 17:45:46 -05001316 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1317 if (currentStackSize <= 1)
1318 {
1319 context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
1320 return false;
1321 }
1322
1323 return true;
1324}
1325
1326static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1327{
1328 switch (identifier)
1329 {
1330 case GL_BUFFER:
1331 if (context->getBuffer(name) == nullptr)
1332 {
1333 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
1334 return false;
1335 }
1336 return true;
1337
1338 case GL_SHADER:
1339 if (context->getShader(name) == nullptr)
1340 {
1341 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
1342 return false;
1343 }
1344 return true;
1345
1346 case GL_PROGRAM:
1347 if (context->getProgram(name) == nullptr)
1348 {
1349 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
1350 return false;
1351 }
1352 return true;
1353
1354 case GL_VERTEX_ARRAY:
1355 if (context->getVertexArray(name) == nullptr)
1356 {
1357 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
1358 return false;
1359 }
1360 return true;
1361
1362 case GL_QUERY:
1363 if (context->getQuery(name) == nullptr)
1364 {
1365 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
1366 return false;
1367 }
1368 return true;
1369
1370 case GL_TRANSFORM_FEEDBACK:
1371 if (context->getTransformFeedback(name) == nullptr)
1372 {
1373 context->recordError(
1374 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1375 return false;
1376 }
1377 return true;
1378
1379 case GL_SAMPLER:
1380 if (context->getSampler(name) == nullptr)
1381 {
1382 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
1383 return false;
1384 }
1385 return true;
1386
1387 case GL_TEXTURE:
1388 if (context->getTexture(name) == nullptr)
1389 {
1390 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
1391 return false;
1392 }
1393 return true;
1394
1395 case GL_RENDERBUFFER:
1396 if (context->getRenderbuffer(name) == nullptr)
1397 {
1398 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
1399 return false;
1400 }
1401 return true;
1402
1403 case GL_FRAMEBUFFER:
1404 if (context->getFramebuffer(name) == nullptr)
1405 {
1406 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
1407 return false;
1408 }
1409 return true;
1410
1411 default:
1412 context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
1413 return false;
1414 }
1415
Geoff Lange102fee2015-12-10 11:23:30 -05001416 return true;
1417}
1418
1419bool ValidateObjectLabelKHR(Context *context,
1420 GLenum identifier,
1421 GLuint name,
1422 GLsizei length,
1423 const GLchar *label)
1424{
1425 if (!context->getExtensions().debug)
1426 {
1427 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1428 return false;
1429 }
1430
Geoff Lang70d0f492015-12-10 17:45:46 -05001431 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1432 {
1433 return false;
1434 }
1435
1436 size_t labelLength = (length < 0) ? strlen(label) : length;
1437 if (labelLength > context->getExtensions().maxLabelLength)
1438 {
1439 context->recordError(
1440 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1441 return false;
1442 }
1443
Geoff Lange102fee2015-12-10 11:23:30 -05001444 return true;
1445}
1446
1447bool ValidateGetObjectLabelKHR(Context *context,
1448 GLenum identifier,
1449 GLuint name,
1450 GLsizei bufSize,
1451 GLsizei *length,
1452 GLchar *label)
1453{
1454 if (!context->getExtensions().debug)
1455 {
1456 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1457 return false;
1458 }
1459
Geoff Lang70d0f492015-12-10 17:45:46 -05001460 if (bufSize < 0)
1461 {
1462 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1463 return false;
1464 }
1465
1466 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1467 {
1468 return false;
1469 }
1470
1471 // Can no-op if bufSize is zero.
1472 return bufSize > 0;
1473}
1474
1475static bool ValidateObjectPtrName(Context *context, const void *ptr)
1476{
1477 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1478 {
1479 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
1480 return false;
1481 }
1482
Geoff Lange102fee2015-12-10 11:23:30 -05001483 return true;
1484}
1485
1486bool ValidateObjectPtrLabelKHR(Context *context,
1487 const void *ptr,
1488 GLsizei length,
1489 const GLchar *label)
1490{
1491 if (!context->getExtensions().debug)
1492 {
1493 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1494 return false;
1495 }
1496
Geoff Lang70d0f492015-12-10 17:45:46 -05001497 if (!ValidateObjectPtrName(context, ptr))
1498 {
1499 return false;
1500 }
1501
1502 size_t labelLength = (length < 0) ? strlen(label) : length;
1503 if (labelLength > context->getExtensions().maxLabelLength)
1504 {
1505 context->recordError(
1506 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1507 return false;
1508 }
1509
Geoff Lange102fee2015-12-10 11:23:30 -05001510 return true;
1511}
1512
1513bool ValidateGetObjectPtrLabelKHR(Context *context,
1514 const void *ptr,
1515 GLsizei bufSize,
1516 GLsizei *length,
1517 GLchar *label)
1518{
1519 if (!context->getExtensions().debug)
1520 {
1521 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1522 return false;
1523 }
1524
Geoff Lang70d0f492015-12-10 17:45:46 -05001525 if (bufSize < 0)
1526 {
1527 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1528 return false;
1529 }
1530
1531 if (!ValidateObjectPtrName(context, ptr))
1532 {
1533 return false;
1534 }
1535
1536 // Can no-op if bufSize is zero.
1537 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001538}
1539
1540bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1541{
1542 if (!context->getExtensions().debug)
1543 {
1544 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1545 return false;
1546 }
1547
Geoff Lang70d0f492015-12-10 17:45:46 -05001548 // TODO: represent this in Context::getQueryParameterInfo.
1549 switch (pname)
1550 {
1551 case GL_DEBUG_CALLBACK_FUNCTION:
1552 case GL_DEBUG_CALLBACK_USER_PARAM:
1553 break;
1554
1555 default:
1556 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
1557 return false;
1558 }
1559
Geoff Lange102fee2015-12-10 11:23:30 -05001560 return true;
1561}
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001562}