blob: 2c7f83ca59d4161473587912dd9855a68c350818 [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"
Jamie Madill73a84962016-02-12 09:27:23 -050011#include "libANGLE/validationES3.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/Renderbuffer.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/FramebufferAttachment.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040018
19#include "common/mathutil.h"
20#include "common/utilities.h"
21
22namespace gl
23{
24
Jamie Madillc29968b2016-01-20 11:17:23 -050025namespace
26{
27
28bool IsPartialBlit(gl::Context *context,
29 const FramebufferAttachment *readBuffer,
30 const FramebufferAttachment *writeBuffer,
31 GLint srcX0,
32 GLint srcY0,
33 GLint srcX1,
34 GLint srcY1,
35 GLint dstX0,
36 GLint dstY0,
37 GLint dstX1,
38 GLint dstY1)
39{
40 const Extents &writeSize = writeBuffer->getSize();
41 const Extents &readSize = readBuffer->getSize();
42
43 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
44 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
45 {
46 return true;
47 }
48
49 if (context->getState().isScissorTestEnabled())
50 {
51 const Rectangle &scissor = context->getState().getScissor();
52 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
53 scissor.height < writeSize.height;
54 }
55
56 return false;
57}
58
59} // anonymous namespace
60
Geoff Langb1196682014-07-23 13:47:29 -040061bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040062 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
63 GLint border, GLenum format, GLenum type, const GLvoid *pixels)
64{
Jamie Madill6f38f822014-06-06 17:12:20 -040065 if (!ValidTexture2DDestinationTarget(context, target))
66 {
Geoff Langb1196682014-07-23 13:47:29 -040067 context->recordError(Error(GL_INVALID_ENUM));
68 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -040069 }
70
Austin Kinross08528e12015-10-07 16:24:40 -070071 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040072 {
Geoff Langb1196682014-07-23 13:47:29 -040073 context->recordError(Error(GL_INVALID_VALUE));
74 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040075 }
76
Geoff Lange8ebe7f2013-08-05 15:03:13 -040077 if (level < 0 || xoffset < 0 ||
78 std::numeric_limits<GLsizei>::max() - xoffset < width ||
79 std::numeric_limits<GLsizei>::max() - yoffset < height)
80 {
Geoff Langb1196682014-07-23 13:47:29 -040081 context->recordError(Error(GL_INVALID_VALUE));
82 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040083 }
84
Geoff Lang005df412013-10-16 14:12:50 -040085 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040086 {
Geoff Langb1196682014-07-23 13:47:29 -040087 context->recordError(Error(GL_INVALID_OPERATION));
88 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -040089 }
90
Geoff Langaae65a42014-05-26 12:43:44 -040091 const gl::Caps &caps = context->getCaps();
92
Geoff Langa9be0dc2014-12-17 12:34:40 -050093 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -040094 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050095 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
96 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -040097 {
Geoff Langa9be0dc2014-12-17 12:34:40 -050098 context->recordError(Error(GL_INVALID_VALUE));
99 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400100 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500101 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500102 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500103 {
104 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400105 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500106 context->recordError(Error(GL_INVALID_VALUE));
107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400108 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400109
Geoff Langa9be0dc2014-12-17 12:34:40 -0500110 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
111 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
112 {
113 context->recordError(Error(GL_INVALID_VALUE));
114 return false;
115 }
116 }
117 else
118 {
Geoff Langb1196682014-07-23 13:47:29 -0400119 context->recordError(Error(GL_INVALID_ENUM));
120 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400121 }
122
Geoff Lang691e58c2014-12-19 17:03:25 -0500123 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400124 if (!texture)
125 {
Geoff Langb1196682014-07-23 13:47:29 -0400126 context->recordError(Error(GL_INVALID_OPERATION));
127 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400128 }
129
Geoff Langa9be0dc2014-12-17 12:34:40 -0500130 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400131 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500132 if (format != GL_NONE)
133 {
Geoff Lang051dbc72015-01-05 15:48:58 -0500134 if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500135 {
136 context->recordError(Error(GL_INVALID_OPERATION));
137 return false;
138 }
139 }
140
141 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
142 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
143 {
144 context->recordError(Error(GL_INVALID_VALUE));
145 return false;
146 }
147 }
148 else
149 {
Geoff Lang69cce582015-09-17 13:20:36 -0400150 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500151 {
152 context->recordError(Error(GL_INVALID_OPERATION));
153 return false;
154 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400155 }
156
157 // Verify zero border
158 if (border != 0)
159 {
Geoff Langb1196682014-07-23 13:47:29 -0400160 context->recordError(Error(GL_INVALID_VALUE));
161 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400162 }
163
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400164 if (isCompressed)
165 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400166 GLenum actualInternalFormat =
167 isSubImage ? texture->getInternalFormat(target, level) : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400168 switch (actualInternalFormat)
169 {
170 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
171 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400172 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400173 {
Geoff Langb1196682014-07-23 13:47:29 -0400174 context->recordError(Error(GL_INVALID_ENUM));
175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400176 }
177 break;
178 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400179 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400180 {
Geoff Langb1196682014-07-23 13:47:29 -0400181 context->recordError(Error(GL_INVALID_ENUM));
182 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400183 }
184 break;
185 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400186 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400187 {
Geoff Langb1196682014-07-23 13:47:29 -0400188 context->recordError(Error(GL_INVALID_ENUM));
189 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400190 }
191 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400192 case GL_ETC1_RGB8_OES:
193 if (!context->getExtensions().compressedETC1RGB8Texture)
194 {
195 context->recordError(Error(GL_INVALID_ENUM));
196 return false;
197 }
198 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800199 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
200 if (!context->getExtensions().lossyETCDecode)
201 {
202 context->recordError(
203 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
204 return false;
205 }
206 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400207 default:
tmartino0ccd5ae2015-10-01 14:33:14 -0400208 context->recordError(Error(
209 GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
210 return false;
211 }
212 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
213 {
214 context->recordError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400215 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400216 }
217 }
218 else
219 {
220 // validate <type> by itself (used as secondary key below)
221 switch (type)
222 {
223 case GL_UNSIGNED_BYTE:
224 case GL_UNSIGNED_SHORT_5_6_5:
225 case GL_UNSIGNED_SHORT_4_4_4_4:
226 case GL_UNSIGNED_SHORT_5_5_5_1:
227 case GL_UNSIGNED_SHORT:
228 case GL_UNSIGNED_INT:
229 case GL_UNSIGNED_INT_24_8_OES:
230 case GL_HALF_FLOAT_OES:
231 case GL_FLOAT:
232 break;
233 default:
Geoff Langb1196682014-07-23 13:47:29 -0400234 context->recordError(Error(GL_INVALID_ENUM));
235 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400236 }
237
238 // validate <format> + <type> combinations
239 // - invalid <format> -> sets INVALID_ENUM
240 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
241 switch (format)
242 {
243 case GL_ALPHA:
244 case GL_LUMINANCE:
245 case GL_LUMINANCE_ALPHA:
246 switch (type)
247 {
248 case GL_UNSIGNED_BYTE:
249 case GL_FLOAT:
250 case GL_HALF_FLOAT_OES:
251 break;
Geoff Langb1196682014-07-23 13:47:29 -0400252 default:
253 context->recordError(Error(GL_INVALID_OPERATION));
254 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 }
256 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400257 case GL_RED:
Geoff Langcec35902014-04-16 10:52:36 -0400258 case GL_RG:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400259 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400260 {
Geoff Langb1196682014-07-23 13:47:29 -0400261 context->recordError(Error(GL_INVALID_ENUM));
262 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400263 }
264 switch (type)
265 {
266 case GL_UNSIGNED_BYTE:
267 case GL_FLOAT:
268 case GL_HALF_FLOAT_OES:
269 break;
270 default:
Geoff Langb1196682014-07-23 13:47:29 -0400271 context->recordError(Error(GL_INVALID_OPERATION));
272 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400273 }
274 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400275 case GL_RGB:
276 switch (type)
277 {
278 case GL_UNSIGNED_BYTE:
279 case GL_UNSIGNED_SHORT_5_6_5:
280 case GL_FLOAT:
281 case GL_HALF_FLOAT_OES:
282 break;
283 default:
Geoff Langb1196682014-07-23 13:47:29 -0400284 context->recordError(Error(GL_INVALID_OPERATION));
285 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400286 }
287 break;
288 case GL_RGBA:
289 switch (type)
290 {
291 case GL_UNSIGNED_BYTE:
292 case GL_UNSIGNED_SHORT_4_4_4_4:
293 case GL_UNSIGNED_SHORT_5_5_5_1:
294 case GL_FLOAT:
295 case GL_HALF_FLOAT_OES:
296 break;
297 default:
Geoff Langb1196682014-07-23 13:47:29 -0400298 context->recordError(Error(GL_INVALID_OPERATION));
299 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400300 }
301 break;
302 case GL_BGRA_EXT:
303 switch (type)
304 {
305 case GL_UNSIGNED_BYTE:
306 break;
307 default:
Geoff Langb1196682014-07-23 13:47:29 -0400308 context->recordError(Error(GL_INVALID_OPERATION));
309 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400310 }
311 break;
Geoff Lang05b05022014-06-11 15:31:45 -0400312 case GL_SRGB_EXT:
313 case GL_SRGB_ALPHA_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400314 if (!context->getExtensions().sRGB)
Geoff Lang05b05022014-06-11 15:31:45 -0400315 {
Geoff Langb1196682014-07-23 13:47:29 -0400316 context->recordError(Error(GL_INVALID_ENUM));
317 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400318 }
319 switch (type)
320 {
321 case GL_UNSIGNED_BYTE:
322 break;
323 default:
Geoff Langb1196682014-07-23 13:47:29 -0400324 context->recordError(Error(GL_INVALID_OPERATION));
325 return false;
Geoff Lang05b05022014-06-11 15:31:45 -0400326 }
327 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
329 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
330 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
331 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
332 break;
333 case GL_DEPTH_COMPONENT:
334 switch (type)
335 {
336 case GL_UNSIGNED_SHORT:
337 case GL_UNSIGNED_INT:
338 break;
339 default:
Geoff Langb1196682014-07-23 13:47:29 -0400340 context->recordError(Error(GL_INVALID_OPERATION));
341 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400342 }
343 break;
344 case GL_DEPTH_STENCIL_OES:
345 switch (type)
346 {
347 case GL_UNSIGNED_INT_24_8_OES:
348 break;
349 default:
Geoff Langb1196682014-07-23 13:47:29 -0400350 context->recordError(Error(GL_INVALID_OPERATION));
351 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400352 }
353 break;
354 default:
Geoff Langb1196682014-07-23 13:47:29 -0400355 context->recordError(Error(GL_INVALID_ENUM));
356 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400357 }
358
359 switch (format)
360 {
361 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
362 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400363 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400364 {
Geoff Langb1196682014-07-23 13:47:29 -0400365 context->recordError(Error(GL_INVALID_OPERATION));
366 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400367 }
368 else
369 {
Geoff Langb1196682014-07-23 13:47:29 -0400370 context->recordError(Error(GL_INVALID_ENUM));
371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400372 }
373 break;
374 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400375 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400376 {
Geoff Langb1196682014-07-23 13:47:29 -0400377 context->recordError(Error(GL_INVALID_OPERATION));
378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400379 }
380 else
381 {
Geoff Langb1196682014-07-23 13:47:29 -0400382 context->recordError(Error(GL_INVALID_ENUM));
383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400384 }
385 break;
386 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400387 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388 {
Geoff Langb1196682014-07-23 13:47:29 -0400389 context->recordError(Error(GL_INVALID_OPERATION));
390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 }
392 else
393 {
Geoff Langb1196682014-07-23 13:47:29 -0400394 context->recordError(Error(GL_INVALID_ENUM));
395 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 }
397 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400398 case GL_ETC1_RGB8_OES:
399 if (context->getExtensions().compressedETC1RGB8Texture)
400 {
401 context->recordError(Error(GL_INVALID_OPERATION));
402 return false;
403 }
404 else
405 {
406 context->recordError(Error(GL_INVALID_ENUM));
407 return false;
408 }
409 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800410 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
411 if (context->getExtensions().lossyETCDecode)
412 {
413 context->recordError(
414 Error(GL_INVALID_OPERATION,
415 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
416 return false;
417 }
418 else
419 {
420 context->recordError(
421 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
422 return false;
423 }
424 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400425 case GL_DEPTH_COMPONENT:
426 case GL_DEPTH_STENCIL_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400427 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400428 {
Geoff Langb1196682014-07-23 13:47:29 -0400429 context->recordError(Error(GL_INVALID_VALUE));
430 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400431 }
432 if (target != GL_TEXTURE_2D)
433 {
Geoff Langb1196682014-07-23 13:47:29 -0400434 context->recordError(Error(GL_INVALID_OPERATION));
435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400436 }
437 // OES_depth_texture supports loading depth data and multiple levels,
438 // but ANGLE_depth_texture does not
439 if (pixels != NULL || level != 0)
440 {
Geoff Langb1196682014-07-23 13:47:29 -0400441 context->recordError(Error(GL_INVALID_OPERATION));
442 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400443 }
444 break;
445 default:
446 break;
447 }
448
449 if (type == GL_FLOAT)
450 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400451 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400452 {
Geoff Langb1196682014-07-23 13:47:29 -0400453 context->recordError(Error(GL_INVALID_ENUM));
454 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400455 }
456 }
457 else if (type == GL_HALF_FLOAT_OES)
458 {
Geoff Langc0b9ef42014-07-02 10:02:37 -0400459 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400460 {
Geoff Langb1196682014-07-23 13:47:29 -0400461 context->recordError(Error(GL_INVALID_ENUM));
462 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400463 }
464 }
465 }
466
467 return true;
468}
469
Jamie Madillc29968b2016-01-20 11:17:23 -0500470bool ValidateES2CopyTexImageParameters(ValidationContext *context,
471 GLenum target,
472 GLint level,
473 GLenum internalformat,
474 bool isSubImage,
475 GLint xoffset,
476 GLint yoffset,
477 GLint x,
478 GLint y,
479 GLsizei width,
480 GLsizei height,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400481 GLint border)
482{
Jamie Madill560a8d82014-05-21 13:06:20 -0400483 GLenum textureInternalFormat = GL_NONE;
Shannon Woods4dfed832014-03-17 20:03:39 -0400484
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500485 if (!ValidTexture2DDestinationTarget(context, target))
486 {
487 context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
488 return false;
489 }
490
Jamie Madill560a8d82014-05-21 13:06:20 -0400491 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
492 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400493 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400494 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400495 }
496
Jamie Madillc29968b2016-01-20 11:17:23 -0500497 const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400498 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
Jamie Madillbc393df2015-01-29 13:46:07 -0500499 const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
500 GLenum textureFormat = internalFormatInfo.format;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400501
502 // [OpenGL ES 2.0.24] table 3.9
503 if (isSubImage)
504 {
505 switch (textureFormat)
506 {
507 case GL_ALPHA:
508 if (colorbufferFormat != GL_ALPHA8_EXT &&
509 colorbufferFormat != GL_RGBA4 &&
510 colorbufferFormat != GL_RGB5_A1 &&
511 colorbufferFormat != GL_RGBA8_OES)
512 {
Geoff Langb1196682014-07-23 13:47:29 -0400513 context->recordError(Error(GL_INVALID_OPERATION));
514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400515 }
516 break;
517 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400518 if (colorbufferFormat != GL_R8_EXT &&
519 colorbufferFormat != GL_RG8_EXT &&
520 colorbufferFormat != GL_RGB565 &&
521 colorbufferFormat != GL_RGB8_OES &&
522 colorbufferFormat != GL_RGBA4 &&
523 colorbufferFormat != GL_RGB5_A1 &&
524 colorbufferFormat != GL_RGBA8_OES)
525 {
Geoff Langb1196682014-07-23 13:47:29 -0400526 context->recordError(Error(GL_INVALID_OPERATION));
527 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400528 }
529 break;
530 case GL_RED_EXT:
531 if (colorbufferFormat != GL_R8_EXT &&
532 colorbufferFormat != GL_RG8_EXT &&
533 colorbufferFormat != GL_RGB565 &&
534 colorbufferFormat != GL_RGB8_OES &&
535 colorbufferFormat != GL_RGBA4 &&
536 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500537 colorbufferFormat != GL_RGBA8_OES &&
538 colorbufferFormat != GL_R32F &&
539 colorbufferFormat != GL_RG32F &&
540 colorbufferFormat != GL_RGB32F &&
541 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400542 {
Geoff Langb1196682014-07-23 13:47:29 -0400543 context->recordError(Error(GL_INVALID_OPERATION));
544 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400545 }
546 break;
547 case GL_RG_EXT:
548 if (colorbufferFormat != GL_RG8_EXT &&
549 colorbufferFormat != GL_RGB565 &&
550 colorbufferFormat != GL_RGB8_OES &&
551 colorbufferFormat != GL_RGBA4 &&
552 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500553 colorbufferFormat != GL_RGBA8_OES &&
554 colorbufferFormat != GL_RG32F &&
555 colorbufferFormat != GL_RGB32F &&
556 colorbufferFormat != GL_RGBA32F)
Geoff Lang632192d2013-10-04 13:40:46 -0400557 {
Geoff Langb1196682014-07-23 13:47:29 -0400558 context->recordError(Error(GL_INVALID_OPERATION));
559 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400560 }
561 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400562 case GL_RGB:
563 if (colorbufferFormat != GL_RGB565 &&
564 colorbufferFormat != GL_RGB8_OES &&
565 colorbufferFormat != GL_RGBA4 &&
566 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500567 colorbufferFormat != GL_RGBA8_OES &&
568 colorbufferFormat != GL_RGB32F &&
569 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400570 {
Geoff Langb1196682014-07-23 13:47:29 -0400571 context->recordError(Error(GL_INVALID_OPERATION));
572 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400573 }
574 break;
575 case GL_LUMINANCE_ALPHA:
576 case GL_RGBA:
577 if (colorbufferFormat != GL_RGBA4 &&
578 colorbufferFormat != GL_RGB5_A1 &&
Jamie Madillbc393df2015-01-29 13:46:07 -0500579 colorbufferFormat != GL_RGBA8_OES &&
580 colorbufferFormat != GL_RGBA32F)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400581 {
Geoff Langb1196682014-07-23 13:47:29 -0400582 context->recordError(Error(GL_INVALID_OPERATION));
583 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400584 }
585 break;
586 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
587 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
588 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
589 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Lang6ea6f942015-09-11 13:11:22 -0400590 case GL_ETC1_RGB8_OES:
Minmin Gonge3939b92015-12-01 15:36:51 -0800591 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Langb1196682014-07-23 13:47:29 -0400592 context->recordError(Error(GL_INVALID_OPERATION));
593 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400594 case GL_DEPTH_COMPONENT:
595 case GL_DEPTH_STENCIL_OES:
Geoff Langb1196682014-07-23 13:47:29 -0400596 context->recordError(Error(GL_INVALID_OPERATION));
597 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400598 default:
Geoff Langb1196682014-07-23 13:47:29 -0400599 context->recordError(Error(GL_INVALID_OPERATION));
600 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400601 }
Jamie Madillbc393df2015-01-29 13:46:07 -0500602
603 if (internalFormatInfo.type == GL_FLOAT &&
604 !context->getExtensions().textureFloat)
605 {
606 context->recordError(Error(GL_INVALID_OPERATION));
607 return false;
608 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400609 }
610 else
611 {
612 switch (internalformat)
613 {
614 case GL_ALPHA:
615 if (colorbufferFormat != GL_ALPHA8_EXT &&
616 colorbufferFormat != GL_RGBA4 &&
617 colorbufferFormat != GL_RGB5_A1 &&
618 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500619 colorbufferFormat != GL_RGBA8_OES &&
620 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400621 {
Geoff Langb1196682014-07-23 13:47:29 -0400622 context->recordError(Error(GL_INVALID_OPERATION));
623 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624 }
625 break;
626 case GL_LUMINANCE:
Geoff Lang632192d2013-10-04 13:40:46 -0400627 if (colorbufferFormat != GL_R8_EXT &&
628 colorbufferFormat != GL_RG8_EXT &&
629 colorbufferFormat != GL_RGB565 &&
630 colorbufferFormat != GL_RGB8_OES &&
631 colorbufferFormat != GL_RGBA4 &&
632 colorbufferFormat != GL_RGB5_A1 &&
633 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500634 colorbufferFormat != GL_RGBA8_OES &&
635 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400636 {
Geoff Langb1196682014-07-23 13:47:29 -0400637 context->recordError(Error(GL_INVALID_OPERATION));
638 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400639 }
640 break;
641 case GL_RED_EXT:
642 if (colorbufferFormat != GL_R8_EXT &&
643 colorbufferFormat != GL_RG8_EXT &&
644 colorbufferFormat != GL_RGB565 &&
645 colorbufferFormat != GL_RGB8_OES &&
646 colorbufferFormat != GL_RGBA4 &&
647 colorbufferFormat != GL_RGB5_A1 &&
648 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500649 colorbufferFormat != GL_RGBA8_OES &&
650 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400651 {
Geoff Langb1196682014-07-23 13:47:29 -0400652 context->recordError(Error(GL_INVALID_OPERATION));
653 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400654 }
655 break;
656 case GL_RG_EXT:
657 if (colorbufferFormat != GL_RG8_EXT &&
658 colorbufferFormat != GL_RGB565 &&
659 colorbufferFormat != GL_RGB8_OES &&
660 colorbufferFormat != GL_RGBA4 &&
661 colorbufferFormat != GL_RGB5_A1 &&
662 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500663 colorbufferFormat != GL_RGBA8_OES &&
664 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lang632192d2013-10-04 13:40:46 -0400665 {
Geoff Langb1196682014-07-23 13:47:29 -0400666 context->recordError(Error(GL_INVALID_OPERATION));
667 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400668 }
669 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400670 case GL_RGB:
671 if (colorbufferFormat != GL_RGB565 &&
672 colorbufferFormat != GL_RGB8_OES &&
673 colorbufferFormat != GL_RGBA4 &&
674 colorbufferFormat != GL_RGB5_A1 &&
675 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500676 colorbufferFormat != GL_RGBA8_OES &&
677 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400678 {
Geoff Langb1196682014-07-23 13:47:29 -0400679 context->recordError(Error(GL_INVALID_OPERATION));
680 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400681 }
682 break;
683 case GL_LUMINANCE_ALPHA:
684 case GL_RGBA:
685 if (colorbufferFormat != GL_RGBA4 &&
686 colorbufferFormat != GL_RGB5_A1 &&
687 colorbufferFormat != GL_BGRA8_EXT &&
Jamie Madill054369e2015-01-07 10:57:08 -0500688 colorbufferFormat != GL_RGBA8_OES &&
689 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400690 {
Geoff Langb1196682014-07-23 13:47:29 -0400691 context->recordError(Error(GL_INVALID_OPERATION));
692 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400693 }
694 break;
695 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
696 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400697 if (context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400698 {
Geoff Langb1196682014-07-23 13:47:29 -0400699 context->recordError(Error(GL_INVALID_OPERATION));
700 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701 }
702 else
703 {
Geoff Langb1196682014-07-23 13:47:29 -0400704 context->recordError(Error(GL_INVALID_ENUM));
705 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400706 }
707 break;
708 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400709 if (context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400710 {
Geoff Langb1196682014-07-23 13:47:29 -0400711 context->recordError(Error(GL_INVALID_OPERATION));
712 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400713 }
714 else
715 {
Geoff Langb1196682014-07-23 13:47:29 -0400716 context->recordError(Error(GL_INVALID_ENUM));
717 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400718 }
719 break;
720 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400721 if (context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 {
Geoff Langb1196682014-07-23 13:47:29 -0400723 context->recordError(Error(GL_INVALID_OPERATION));
724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725 }
726 else
727 {
Geoff Langb1196682014-07-23 13:47:29 -0400728 context->recordError(Error(GL_INVALID_ENUM));
729 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400730 }
731 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400732 case GL_ETC1_RGB8_OES:
733 if (context->getExtensions().compressedETC1RGB8Texture)
734 {
735 context->recordError(Error(GL_INVALID_OPERATION));
736 return false;
737 }
738 else
739 {
740 context->recordError(Error(GL_INVALID_ENUM));
741 return false;
742 }
743 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800744 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
745 if (context->getExtensions().lossyETCDecode)
746 {
747 context->recordError(Error(GL_INVALID_OPERATION,
748 "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
749 return false;
750 }
751 else
752 {
753 context->recordError(
754 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
755 return false;
756 }
757 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400758 case GL_DEPTH_COMPONENT:
759 case GL_DEPTH_COMPONENT16:
760 case GL_DEPTH_COMPONENT32_OES:
761 case GL_DEPTH_STENCIL_OES:
762 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400763 if (context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 {
Geoff Langb1196682014-07-23 13:47:29 -0400765 context->recordError(Error(GL_INVALID_OPERATION));
766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 }
768 else
769 {
Geoff Langb1196682014-07-23 13:47:29 -0400770 context->recordError(Error(GL_INVALID_ENUM));
771 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 }
773 default:
Geoff Langb1196682014-07-23 13:47:29 -0400774 context->recordError(Error(GL_INVALID_ENUM));
775 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400776 }
777 }
778
Geoff Lang784a8fd2013-09-24 12:33:16 -0400779 // If width or height is zero, it is a no-op. Return false without setting an error.
780 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400781}
782
Geoff Langb1196682014-07-23 13:47:29 -0400783bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784 GLsizei width, GLsizei height)
785{
786 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
787 {
Geoff Langb1196682014-07-23 13:47:29 -0400788 context->recordError(Error(GL_INVALID_ENUM));
789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790 }
791
792 if (width < 1 || height < 1 || levels < 1)
793 {
Geoff Langb1196682014-07-23 13:47:29 -0400794 context->recordError(Error(GL_INVALID_VALUE));
795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797
798 if (target == GL_TEXTURE_CUBE_MAP && width != height)
799 {
Geoff Langb1196682014-07-23 13:47:29 -0400800 context->recordError(Error(GL_INVALID_VALUE));
801 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 }
803
804 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
805 {
Geoff Langb1196682014-07-23 13:47:29 -0400806 context->recordError(Error(GL_INVALID_OPERATION));
807 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400808 }
809
Geoff Lang5d601382014-07-22 15:14:06 -0400810 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
811 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 {
Geoff Langb1196682014-07-23 13:47:29 -0400813 context->recordError(Error(GL_INVALID_ENUM));
814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400815 }
816
Geoff Langaae65a42014-05-26 12:43:44 -0400817 const gl::Caps &caps = context->getCaps();
818
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 switch (target)
820 {
821 case GL_TEXTURE_2D:
Geoff Langaae65a42014-05-26 12:43:44 -0400822 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
823 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400824 {
Geoff Langb1196682014-07-23 13:47:29 -0400825 context->recordError(Error(GL_INVALID_VALUE));
826 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400827 }
828 break;
829 case GL_TEXTURE_CUBE_MAP:
Geoff Langaae65a42014-05-26 12:43:44 -0400830 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
831 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 {
Geoff Langb1196682014-07-23 13:47:29 -0400833 context->recordError(Error(GL_INVALID_VALUE));
834 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 }
836 break;
837 default:
Geoff Langb1196682014-07-23 13:47:29 -0400838 context->recordError(Error(GL_INVALID_ENUM));
839 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400840 }
841
Geoff Langc0b9ef42014-07-02 10:02:37 -0400842 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400843 {
844 if (!gl::isPow2(width) || !gl::isPow2(height))
845 {
Geoff Langb1196682014-07-23 13:47:29 -0400846 context->recordError(Error(GL_INVALID_OPERATION));
847 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848 }
849 }
850
851 switch (internalformat)
852 {
853 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
854 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400855 if (!context->getExtensions().textureCompressionDXT1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400856 {
Geoff Langb1196682014-07-23 13:47:29 -0400857 context->recordError(Error(GL_INVALID_ENUM));
858 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400859 }
860 break;
861 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400862 if (!context->getExtensions().textureCompressionDXT3)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400863 {
Geoff Langb1196682014-07-23 13:47:29 -0400864 context->recordError(Error(GL_INVALID_ENUM));
865 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400866 }
867 break;
868 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400869 if (!context->getExtensions().textureCompressionDXT5)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400870 {
Geoff Langb1196682014-07-23 13:47:29 -0400871 context->recordError(Error(GL_INVALID_ENUM));
872 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400873 }
874 break;
Geoff Lang6ea6f942015-09-11 13:11:22 -0400875 case GL_ETC1_RGB8_OES:
876 if (!context->getExtensions().compressedETC1RGB8Texture)
877 {
878 context->recordError(Error(GL_INVALID_ENUM));
879 return false;
880 }
881 break;
Minmin Gonge3939b92015-12-01 15:36:51 -0800882 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
883 if (!context->getExtensions().lossyETCDecode)
884 {
885 context->recordError(
886 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
887 return false;
888 }
889 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400890 case GL_RGBA32F_EXT:
891 case GL_RGB32F_EXT:
892 case GL_ALPHA32F_EXT:
893 case GL_LUMINANCE32F_EXT:
894 case GL_LUMINANCE_ALPHA32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400895 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400896 {
Geoff Langb1196682014-07-23 13:47:29 -0400897 context->recordError(Error(GL_INVALID_ENUM));
898 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400899 }
900 break;
901 case GL_RGBA16F_EXT:
902 case GL_RGB16F_EXT:
903 case GL_ALPHA16F_EXT:
904 case GL_LUMINANCE16F_EXT:
905 case GL_LUMINANCE_ALPHA16F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400906 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 {
Geoff Langb1196682014-07-23 13:47:29 -0400908 context->recordError(Error(GL_INVALID_ENUM));
909 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 }
911 break;
Geoff Lang632192d2013-10-04 13:40:46 -0400912 case GL_R8_EXT:
913 case GL_RG8_EXT:
914 case GL_R16F_EXT:
915 case GL_RG16F_EXT:
916 case GL_R32F_EXT:
917 case GL_RG32F_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400918 if (!context->getExtensions().textureRG)
Geoff Lang632192d2013-10-04 13:40:46 -0400919 {
Geoff Langb1196682014-07-23 13:47:29 -0400920 context->recordError(Error(GL_INVALID_ENUM));
921 return false;
Geoff Lang632192d2013-10-04 13:40:46 -0400922 }
923 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 case GL_DEPTH_COMPONENT16:
925 case GL_DEPTH_COMPONENT32_OES:
926 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400927 if (!context->getExtensions().depthTextures)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928 {
Geoff Langb1196682014-07-23 13:47:29 -0400929 context->recordError(Error(GL_INVALID_ENUM));
930 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400931 }
932 if (target != GL_TEXTURE_2D)
933 {
Geoff Langb1196682014-07-23 13:47:29 -0400934 context->recordError(Error(GL_INVALID_OPERATION));
935 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400936 }
937 // ANGLE_depth_texture only supports 1-level textures
938 if (levels != 1)
939 {
Geoff Langb1196682014-07-23 13:47:29 -0400940 context->recordError(Error(GL_INVALID_OPERATION));
941 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 }
943 break;
944 default:
945 break;
946 }
947
Geoff Lang691e58c2014-12-19 17:03:25 -0500948 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400949 if (!texture || texture->id() == 0)
950 {
Geoff Langb1196682014-07-23 13:47:29 -0400951 context->recordError(Error(GL_INVALID_OPERATION));
952 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 }
954
Geoff Lang69cce582015-09-17 13:20:36 -0400955 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400956 {
Geoff Langb1196682014-07-23 13:47:29 -0400957 context->recordError(Error(GL_INVALID_OPERATION));
958 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 }
960
961 return true;
962}
963
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400964// check for combinations of format and type that are valid for ReadPixels
Geoff Langb1196682014-07-23 13:47:29 -0400965bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966{
967 switch (format)
968 {
969 case GL_RGBA:
970 switch (type)
971 {
972 case GL_UNSIGNED_BYTE:
973 break;
974 default:
975 return false;
976 }
977 break;
978 case GL_BGRA_EXT:
979 switch (type)
980 {
981 case GL_UNSIGNED_BYTE:
982 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
983 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
984 break;
985 default:
986 return false;
987 }
988 break;
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400989 case GL_RG_EXT:
990 case GL_RED_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400991 if (!context->getExtensions().textureRG)
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400992 {
993 return false;
994 }
995 switch (type)
996 {
997 case GL_UNSIGNED_BYTE:
998 break;
999 default:
1000 return false;
1001 }
1002 break;
1003
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 default:
1005 return false;
1006 }
1007 return true;
1008}
1009
Austin Kinross08332632015-05-05 13:35:47 -07001010bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
1011 const GLenum *attachments)
1012{
Jamie Madillc29968b2016-01-20 11:17:23 -05001013 if (!context->getExtensions().discardFramebuffer)
1014 {
1015 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1016 return false;
1017 }
1018
Austin Kinross08332632015-05-05 13:35:47 -07001019 bool defaultFramebuffer = false;
1020
1021 switch (target)
1022 {
1023 case GL_FRAMEBUFFER:
1024 defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1025 break;
1026 default:
1027 context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1028 return false;
1029 }
1030
1031 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
1032}
1033
Austin Kinrossbc781f32015-10-26 09:27:38 -07001034bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1035{
1036 if (!context->getExtensions().vertexArrayObject)
1037 {
1038 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1039 return false;
1040 }
1041
1042 return ValidateBindVertexArrayBase(context, array);
1043}
1044
1045bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1046{
1047 if (!context->getExtensions().vertexArrayObject)
1048 {
1049 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1050 return false;
1051 }
1052
Olli Etuaho41997e72016-03-10 13:38:39 +02001053 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001054}
1055
1056bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1057{
1058 if (!context->getExtensions().vertexArrayObject)
1059 {
1060 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1061 return false;
1062 }
1063
Olli Etuaho41997e72016-03-10 13:38:39 +02001064 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001065}
1066
1067bool ValidateIsVertexArrayOES(Context *context)
1068{
1069 if (!context->getExtensions().vertexArrayObject)
1070 {
1071 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1072 return false;
1073 }
1074
1075 return true;
1076}
Geoff Langc5629752015-12-07 16:29:04 -05001077
1078bool ValidateProgramBinaryOES(Context *context,
1079 GLuint program,
1080 GLenum binaryFormat,
1081 const void *binary,
1082 GLint length)
1083{
1084 if (!context->getExtensions().getProgramBinary)
1085 {
1086 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1087 return false;
1088 }
1089
1090 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1091}
1092
1093bool ValidateGetProgramBinaryOES(Context *context,
1094 GLuint program,
1095 GLsizei bufSize,
1096 GLsizei *length,
1097 GLenum *binaryFormat,
1098 void *binary)
1099{
1100 if (!context->getExtensions().getProgramBinary)
1101 {
1102 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1103 return false;
1104 }
1105
1106 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1107}
Geoff Lange102fee2015-12-10 11:23:30 -05001108
Geoff Lang70d0f492015-12-10 17:45:46 -05001109static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1110{
1111 switch (source)
1112 {
1113 case GL_DEBUG_SOURCE_API:
1114 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1115 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1116 case GL_DEBUG_SOURCE_OTHER:
1117 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1118 return !mustBeThirdPartyOrApplication;
1119
1120 case GL_DEBUG_SOURCE_THIRD_PARTY:
1121 case GL_DEBUG_SOURCE_APPLICATION:
1122 return true;
1123
1124 default:
1125 return false;
1126 }
1127}
1128
1129static bool ValidDebugType(GLenum type)
1130{
1131 switch (type)
1132 {
1133 case GL_DEBUG_TYPE_ERROR:
1134 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1135 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1136 case GL_DEBUG_TYPE_PERFORMANCE:
1137 case GL_DEBUG_TYPE_PORTABILITY:
1138 case GL_DEBUG_TYPE_OTHER:
1139 case GL_DEBUG_TYPE_MARKER:
1140 case GL_DEBUG_TYPE_PUSH_GROUP:
1141 case GL_DEBUG_TYPE_POP_GROUP:
1142 return true;
1143
1144 default:
1145 return false;
1146 }
1147}
1148
1149static bool ValidDebugSeverity(GLenum severity)
1150{
1151 switch (severity)
1152 {
1153 case GL_DEBUG_SEVERITY_HIGH:
1154 case GL_DEBUG_SEVERITY_MEDIUM:
1155 case GL_DEBUG_SEVERITY_LOW:
1156 case GL_DEBUG_SEVERITY_NOTIFICATION:
1157 return true;
1158
1159 default:
1160 return false;
1161 }
1162}
1163
Geoff Lange102fee2015-12-10 11:23:30 -05001164bool ValidateDebugMessageControlKHR(Context *context,
1165 GLenum source,
1166 GLenum type,
1167 GLenum severity,
1168 GLsizei count,
1169 const GLuint *ids,
1170 GLboolean enabled)
1171{
1172 if (!context->getExtensions().debug)
1173 {
1174 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1175 return false;
1176 }
1177
Geoff Lang70d0f492015-12-10 17:45:46 -05001178 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1179 {
1180 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1181 return false;
1182 }
1183
1184 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1185 {
1186 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1187 return false;
1188 }
1189
1190 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1191 {
1192 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1193 return false;
1194 }
1195
1196 if (count > 0)
1197 {
1198 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1199 {
1200 context->recordError(Error(
1201 GL_INVALID_OPERATION,
1202 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1203 return false;
1204 }
1205
1206 if (severity != GL_DONT_CARE)
1207 {
1208 context->recordError(
1209 Error(GL_INVALID_OPERATION,
1210 "If count is greater than zero, severity must be GL_DONT_CARE."));
1211 return false;
1212 }
1213 }
1214
Geoff Lange102fee2015-12-10 11:23:30 -05001215 return true;
1216}
1217
1218bool ValidateDebugMessageInsertKHR(Context *context,
1219 GLenum source,
1220 GLenum type,
1221 GLuint id,
1222 GLenum severity,
1223 GLsizei length,
1224 const GLchar *buf)
1225{
1226 if (!context->getExtensions().debug)
1227 {
1228 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1229 return false;
1230 }
1231
Geoff Lang70d0f492015-12-10 17:45:46 -05001232 if (!context->getState().getDebug().isOutputEnabled())
1233 {
1234 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1235 // not generate an error.
1236 return false;
1237 }
1238
1239 if (!ValidDebugSeverity(severity))
1240 {
1241 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
1242 return false;
1243 }
1244
1245 if (!ValidDebugType(type))
1246 {
1247 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
1248 return false;
1249 }
1250
1251 if (!ValidDebugSource(source, true))
1252 {
1253 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1254 return false;
1255 }
1256
1257 size_t messageLength = (length < 0) ? strlen(buf) : length;
1258 if (messageLength > context->getExtensions().maxDebugMessageLength)
1259 {
1260 context->recordError(
1261 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1262 return false;
1263 }
1264
Geoff Lange102fee2015-12-10 11:23:30 -05001265 return true;
1266}
1267
1268bool ValidateDebugMessageCallbackKHR(Context *context,
1269 GLDEBUGPROCKHR callback,
1270 const void *userParam)
1271{
1272 if (!context->getExtensions().debug)
1273 {
1274 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1275 return false;
1276 }
1277
Geoff Lange102fee2015-12-10 11:23:30 -05001278 return true;
1279}
1280
1281bool ValidateGetDebugMessageLogKHR(Context *context,
1282 GLuint count,
1283 GLsizei bufSize,
1284 GLenum *sources,
1285 GLenum *types,
1286 GLuint *ids,
1287 GLenum *severities,
1288 GLsizei *lengths,
1289 GLchar *messageLog)
1290{
1291 if (!context->getExtensions().debug)
1292 {
1293 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1294 return false;
1295 }
1296
Geoff Lang70d0f492015-12-10 17:45:46 -05001297 if (bufSize < 0 && messageLog != nullptr)
1298 {
1299 context->recordError(
1300 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1301 return false;
1302 }
1303
Geoff Lange102fee2015-12-10 11:23:30 -05001304 return true;
1305}
1306
1307bool ValidatePushDebugGroupKHR(Context *context,
1308 GLenum source,
1309 GLuint id,
1310 GLsizei length,
1311 const GLchar *message)
1312{
1313 if (!context->getExtensions().debug)
1314 {
1315 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1316 return false;
1317 }
1318
Geoff Lang70d0f492015-12-10 17:45:46 -05001319 if (!ValidDebugSource(source, true))
1320 {
1321 context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
1322 return false;
1323 }
1324
1325 size_t messageLength = (length < 0) ? strlen(message) : length;
1326 if (messageLength > context->getExtensions().maxDebugMessageLength)
1327 {
1328 context->recordError(
1329 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1330 return false;
1331 }
1332
1333 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1334 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1335 {
1336 context->recordError(
1337 Error(GL_STACK_OVERFLOW,
1338 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1339 return false;
1340 }
1341
Geoff Lange102fee2015-12-10 11:23:30 -05001342 return true;
1343}
1344
1345bool ValidatePopDebugGroupKHR(Context *context)
1346{
1347 if (!context->getExtensions().debug)
1348 {
1349 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1350 return false;
1351 }
1352
Geoff Lang70d0f492015-12-10 17:45:46 -05001353 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
1354 if (currentStackSize <= 1)
1355 {
1356 context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
1357 return false;
1358 }
1359
1360 return true;
1361}
1362
1363static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1364{
1365 switch (identifier)
1366 {
1367 case GL_BUFFER:
1368 if (context->getBuffer(name) == nullptr)
1369 {
1370 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
1371 return false;
1372 }
1373 return true;
1374
1375 case GL_SHADER:
1376 if (context->getShader(name) == nullptr)
1377 {
1378 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
1379 return false;
1380 }
1381 return true;
1382
1383 case GL_PROGRAM:
1384 if (context->getProgram(name) == nullptr)
1385 {
1386 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
1387 return false;
1388 }
1389 return true;
1390
1391 case GL_VERTEX_ARRAY:
1392 if (context->getVertexArray(name) == nullptr)
1393 {
1394 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
1395 return false;
1396 }
1397 return true;
1398
1399 case GL_QUERY:
1400 if (context->getQuery(name) == nullptr)
1401 {
1402 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
1403 return false;
1404 }
1405 return true;
1406
1407 case GL_TRANSFORM_FEEDBACK:
1408 if (context->getTransformFeedback(name) == nullptr)
1409 {
1410 context->recordError(
1411 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1412 return false;
1413 }
1414 return true;
1415
1416 case GL_SAMPLER:
1417 if (context->getSampler(name) == nullptr)
1418 {
1419 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
1420 return false;
1421 }
1422 return true;
1423
1424 case GL_TEXTURE:
1425 if (context->getTexture(name) == nullptr)
1426 {
1427 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
1428 return false;
1429 }
1430 return true;
1431
1432 case GL_RENDERBUFFER:
1433 if (context->getRenderbuffer(name) == nullptr)
1434 {
1435 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
1436 return false;
1437 }
1438 return true;
1439
1440 case GL_FRAMEBUFFER:
1441 if (context->getFramebuffer(name) == nullptr)
1442 {
1443 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
1444 return false;
1445 }
1446 return true;
1447
1448 default:
1449 context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
1450 return false;
1451 }
1452
Geoff Lange102fee2015-12-10 11:23:30 -05001453 return true;
1454}
1455
1456bool ValidateObjectLabelKHR(Context *context,
1457 GLenum identifier,
1458 GLuint name,
1459 GLsizei length,
1460 const GLchar *label)
1461{
1462 if (!context->getExtensions().debug)
1463 {
1464 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1465 return false;
1466 }
1467
Geoff Lang70d0f492015-12-10 17:45:46 -05001468 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1469 {
1470 return false;
1471 }
1472
1473 size_t labelLength = (length < 0) ? strlen(label) : length;
1474 if (labelLength > context->getExtensions().maxLabelLength)
1475 {
1476 context->recordError(
1477 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1478 return false;
1479 }
1480
Geoff Lange102fee2015-12-10 11:23:30 -05001481 return true;
1482}
1483
1484bool ValidateGetObjectLabelKHR(Context *context,
1485 GLenum identifier,
1486 GLuint name,
1487 GLsizei bufSize,
1488 GLsizei *length,
1489 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 (bufSize < 0)
1498 {
1499 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1500 return false;
1501 }
1502
1503 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1504 {
1505 return false;
1506 }
1507
1508 // Can no-op if bufSize is zero.
1509 return bufSize > 0;
1510}
1511
1512static bool ValidateObjectPtrName(Context *context, const void *ptr)
1513{
1514 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1515 {
1516 context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
1517 return false;
1518 }
1519
Geoff Lange102fee2015-12-10 11:23:30 -05001520 return true;
1521}
1522
1523bool ValidateObjectPtrLabelKHR(Context *context,
1524 const void *ptr,
1525 GLsizei length,
1526 const GLchar *label)
1527{
1528 if (!context->getExtensions().debug)
1529 {
1530 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1531 return false;
1532 }
1533
Geoff Lang70d0f492015-12-10 17:45:46 -05001534 if (!ValidateObjectPtrName(context, ptr))
1535 {
1536 return false;
1537 }
1538
1539 size_t labelLength = (length < 0) ? strlen(label) : length;
1540 if (labelLength > context->getExtensions().maxLabelLength)
1541 {
1542 context->recordError(
1543 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1544 return false;
1545 }
1546
Geoff Lange102fee2015-12-10 11:23:30 -05001547 return true;
1548}
1549
1550bool ValidateGetObjectPtrLabelKHR(Context *context,
1551 const void *ptr,
1552 GLsizei bufSize,
1553 GLsizei *length,
1554 GLchar *label)
1555{
1556 if (!context->getExtensions().debug)
1557 {
1558 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1559 return false;
1560 }
1561
Geoff Lang70d0f492015-12-10 17:45:46 -05001562 if (bufSize < 0)
1563 {
1564 context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1565 return false;
1566 }
1567
1568 if (!ValidateObjectPtrName(context, ptr))
1569 {
1570 return false;
1571 }
1572
1573 // Can no-op if bufSize is zero.
1574 return bufSize > 0;
Geoff Lange102fee2015-12-10 11:23:30 -05001575}
1576
1577bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1578{
1579 if (!context->getExtensions().debug)
1580 {
1581 context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
1582 return false;
1583 }
1584
Geoff Lang70d0f492015-12-10 17:45:46 -05001585 // TODO: represent this in Context::getQueryParameterInfo.
1586 switch (pname)
1587 {
1588 case GL_DEBUG_CALLBACK_FUNCTION:
1589 case GL_DEBUG_CALLBACK_USER_PARAM:
1590 break;
1591
1592 default:
1593 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
1594 return false;
1595 }
1596
Geoff Lange102fee2015-12-10 11:23:30 -05001597 return true;
1598}
Jamie Madillc29968b2016-01-20 11:17:23 -05001599
1600bool ValidateBlitFramebufferANGLE(Context *context,
1601 GLint srcX0,
1602 GLint srcY0,
1603 GLint srcX1,
1604 GLint srcY1,
1605 GLint dstX0,
1606 GLint dstY0,
1607 GLint dstX1,
1608 GLint dstY1,
1609 GLbitfield mask,
1610 GLenum filter)
1611{
1612 if (!context->getExtensions().framebufferBlit)
1613 {
1614 context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
1615 return false;
1616 }
1617
1618 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1619 {
1620 // TODO(jmadill): Determine if this should be available on other implementations.
1621 context->recordError(Error(
1622 GL_INVALID_OPERATION,
1623 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1624 return false;
1625 }
1626
1627 if (filter == GL_LINEAR)
1628 {
1629 context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
1630 return false;
1631 }
1632
1633 const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
1634 const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
1635
1636 if (mask & GL_COLOR_BUFFER_BIT)
1637 {
1638 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1639 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1640
1641 if (readColorAttachment && drawColorAttachment)
1642 {
1643 if (!(readColorAttachment->type() == GL_TEXTURE &&
1644 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1645 readColorAttachment->type() != GL_RENDERBUFFER &&
1646 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
1647 {
1648 context->recordError(Error(GL_INVALID_OPERATION));
1649 return false;
1650 }
1651
Geoff Langa15472a2015-08-11 11:48:03 -04001652 for (size_t drawbufferIdx = 0;
1653 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05001654 {
Geoff Langa15472a2015-08-11 11:48:03 -04001655 const FramebufferAttachment *attachment =
1656 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1657 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05001658 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001659 if (!(attachment->type() == GL_TEXTURE &&
1660 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1661 attachment->type() != GL_RENDERBUFFER &&
1662 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
1663 {
1664 context->recordError(Error(GL_INVALID_OPERATION));
1665 return false;
1666 }
1667
1668 // Return an error if the destination formats do not match
1669 if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
1670 {
1671 context->recordError(Error(GL_INVALID_OPERATION));
1672 return false;
1673 }
1674 }
1675 }
1676
1677 int readSamples = readFramebuffer->getSamples(context->getData());
1678
1679 if (readSamples != 0 &&
1680 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
1681 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
1682 {
1683 context->recordError(Error(GL_INVALID_OPERATION));
1684 return false;
1685 }
1686 }
1687 }
1688
1689 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1690 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1691 for (size_t i = 0; i < 2; i++)
1692 {
1693 if (mask & masks[i])
1694 {
1695 const FramebufferAttachment *readBuffer =
1696 readFramebuffer->getAttachment(attachments[i]);
1697 const FramebufferAttachment *drawBuffer =
1698 drawFramebuffer->getAttachment(attachments[i]);
1699
1700 if (readBuffer && drawBuffer)
1701 {
1702 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
1703 dstX0, dstY0, dstX1, dstY1))
1704 {
1705 // only whole-buffer copies are permitted
1706 ERR(
1707 "Only whole-buffer depth and stencil blits are supported by this "
1708 "implementation.");
1709 context->recordError(Error(GL_INVALID_OPERATION));
1710 return false;
1711 }
1712
1713 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
1714 {
1715 context->recordError(Error(GL_INVALID_OPERATION));
1716 return false;
1717 }
1718 }
1719 }
1720 }
1721
1722 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1723 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724}
Jamie Madillc29968b2016-01-20 11:17:23 -05001725
1726bool ValidateClear(ValidationContext *context, GLbitfield mask)
1727{
1728 const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
1729 ASSERT(framebufferObject);
1730
1731 if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
1732 {
1733 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1734 return false;
1735 }
1736
1737 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
1738 {
1739 context->recordError(Error(GL_INVALID_VALUE));
1740 return false;
1741 }
1742
1743 return true;
1744}
1745
1746bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
1747{
1748 if (!context->getExtensions().drawBuffers)
1749 {
1750 context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
1751 return false;
1752 }
1753
1754 return ValidateDrawBuffersBase(context, n, bufs);
1755}
1756
Jamie Madill73a84962016-02-12 09:27:23 -05001757bool ValidateTexImage2D(Context *context,
1758 GLenum target,
1759 GLint level,
1760 GLint internalformat,
1761 GLsizei width,
1762 GLsizei height,
1763 GLint border,
1764 GLenum format,
1765 GLenum type,
1766 const GLvoid *pixels)
1767{
1768 if (context->getClientVersion() < 3)
1769 {
1770 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
1771 0, 0, width, height, border, format, type, pixels);
1772 }
1773
1774 ASSERT(context->getClientVersion() >= 3);
1775 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
1776 0, 0, width, height, 1, border, format, type, pixels);
1777}
1778
1779bool ValidateTexSubImage2D(Context *context,
1780 GLenum target,
1781 GLint level,
1782 GLint xoffset,
1783 GLint yoffset,
1784 GLsizei width,
1785 GLsizei height,
1786 GLenum format,
1787 GLenum type,
1788 const GLvoid *pixels)
1789{
1790
1791 if (context->getClientVersion() < 3)
1792 {
1793 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
1794 yoffset, width, height, 0, format, type, pixels);
1795 }
1796
1797 ASSERT(context->getClientVersion() >= 3);
1798 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
1799 yoffset, 0, width, height, 1, 0, format, type, pixels);
1800}
1801
1802bool ValidateCompressedTexImage2D(Context *context,
1803 GLenum target,
1804 GLint level,
1805 GLenum internalformat,
1806 GLsizei width,
1807 GLsizei height,
1808 GLint border,
1809 GLsizei imageSize,
1810 const GLvoid *data)
1811{
1812 if (context->getClientVersion() < 3)
1813 {
1814 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
1815 0, width, height, border, GL_NONE, GL_NONE, data))
1816 {
1817 return false;
1818 }
1819 }
1820 else
1821 {
1822 ASSERT(context->getClientVersion() >= 3);
1823 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
1824 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
1825 data))
1826 {
1827 return false;
1828 }
1829 }
1830
1831 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
1832 if (imageSize < 0 ||
1833 static_cast<GLuint>(imageSize) !=
1834 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1835 {
1836 context->recordError(Error(GL_INVALID_VALUE));
1837 return false;
1838 }
1839
1840 return true;
1841}
1842
1843bool ValidateCompressedTexSubImage2D(Context *context,
1844 GLenum target,
1845 GLint level,
1846 GLint xoffset,
1847 GLint yoffset,
1848 GLsizei width,
1849 GLsizei height,
1850 GLenum format,
1851 GLsizei imageSize,
1852 const GLvoid *data)
1853{
1854 if (context->getClientVersion() < 3)
1855 {
1856 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
1857 yoffset, width, height, 0, GL_NONE, GL_NONE, data))
1858 {
1859 return false;
1860 }
1861 }
1862 else
1863 {
1864 ASSERT(context->getClientVersion() >= 3);
1865 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
1866 yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
1867 data))
1868 {
1869 return false;
1870 }
1871 }
1872
1873 const InternalFormat &formatInfo = GetInternalFormatInfo(format);
1874 if (imageSize < 0 ||
1875 static_cast<GLuint>(imageSize) !=
1876 formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
1877 {
1878 context->recordError(Error(GL_INVALID_VALUE));
1879 return false;
1880 }
1881
1882 return true;
1883}
1884
Olli Etuaho4f667482016-03-30 15:56:35 +03001885bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
1886{
1887 if (!context->getExtensions().mapBuffer)
1888 {
1889 context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
1890 return false;
1891 }
1892
1893 return ValidateGetBufferPointervBase(context, target, pname, params);
1894}
1895
1896bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
1897{
1898 if (!context->getExtensions().mapBuffer)
1899 {
1900 context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
1901 return false;
1902 }
1903
1904 if (!ValidBufferTarget(context, target))
1905 {
1906 context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1907 return false;
1908 }
1909
1910 Buffer *buffer = context->getState().getTargetBuffer(target);
1911
1912 if (buffer == nullptr)
1913 {
1914 context->recordError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
1915 return false;
1916 }
1917
1918 if (access != GL_WRITE_ONLY_OES)
1919 {
1920 context->recordError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
1921 return false;
1922 }
1923
1924 if (buffer->isMapped())
1925 {
1926 context->recordError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
1927 return false;
1928 }
1929
1930 return true;
1931}
1932
1933bool ValidateUnmapBufferOES(Context *context, GLenum target)
1934{
1935 if (!context->getExtensions().mapBuffer)
1936 {
1937 context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
1938 return false;
1939 }
1940
1941 return ValidateUnmapBufferBase(context, target);
1942}
1943
1944bool ValidateMapBufferRangeEXT(Context *context,
1945 GLenum target,
1946 GLintptr offset,
1947 GLsizeiptr length,
1948 GLbitfield access)
1949{
1950 if (!context->getExtensions().mapBufferRange)
1951 {
1952 context->recordError(
1953 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
1954 return false;
1955 }
1956
1957 return ValidateMapBufferRangeBase(context, target, offset, length, access);
1958}
1959
1960bool ValidateFlushMappedBufferRangeEXT(Context *context,
1961 GLenum target,
1962 GLintptr offset,
1963 GLsizeiptr length)
1964{
1965 if (!context->getExtensions().mapBufferRange)
1966 {
1967 context->recordError(
1968 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
1969 return false;
1970 }
1971
1972 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
1973}
1974
Jamie Madillc29968b2016-01-20 11:17:23 -05001975} // namespace gl