1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // 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
9 #include "libANGLE/validationES2_autogen.h"
10
11 #include <cstdint>
12
13 #include "common/mathutil.h"
14 #include "common/string_utils.h"
15 #include "common/utilities.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/ErrorStrings.h"
18 #include "libANGLE/Fence.h"
19 #include "libANGLE/Framebuffer.h"
20 #include "libANGLE/FramebufferAttachment.h"
21 #include "libANGLE/MemoryObject.h"
22 #include "libANGLE/Renderbuffer.h"
23 #include "libANGLE/Shader.h"
24 #include "libANGLE/Texture.h"
25 #include "libANGLE/Uniform.h"
26 #include "libANGLE/VertexArray.h"
27 #include "libANGLE/formatutils.h"
28 #include "libANGLE/validationES.h"
29 #include "libANGLE/validationES2.h"
30 #include "libANGLE/validationES3_autogen.h"
31
32 namespace gl
33 {
34 using namespace err;
35
36 namespace
37 {
38
IsPartialBlit(const Context * context,const FramebufferAttachment * readBuffer,const FramebufferAttachment * writeBuffer,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1)39 bool IsPartialBlit(const Context *context,
40 const FramebufferAttachment *readBuffer,
41 const FramebufferAttachment *writeBuffer,
42 GLint srcX0,
43 GLint srcY0,
44 GLint srcX1,
45 GLint srcY1,
46 GLint dstX0,
47 GLint dstY0,
48 GLint dstX1,
49 GLint dstY1)
50 {
51 const Extents &writeSize = writeBuffer->getSize();
52 const Extents &readSize = readBuffer->getSize();
53
54 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
55 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
56 {
57 return true;
58 }
59
60 if (context->getState().isScissorTestEnabled())
61 {
62 const Rectangle &scissor = context->getState().getScissor();
63 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
64 scissor.height < writeSize.height;
65 }
66
67 return false;
68 }
69
IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)70 bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
71 {
72 // Table 1.1 from the CHROMIUM_copy_texture spec
73 switch (GetUnsizedFormat(internalFormat))
74 {
75 case GL_RED:
76 case GL_ALPHA:
77 case GL_LUMINANCE:
78 case GL_LUMINANCE_ALPHA:
79 case GL_RGB:
80 case GL_RGBA:
81 case GL_RGB8:
82 case GL_RGBA8:
83 case GL_BGRA_EXT:
84 case GL_BGRA8_EXT:
85 return true;
86
87 default:
88 return false;
89 }
90 }
91
IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)92 bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
93 {
94 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
95 }
96
IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)97 bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
98 {
99 // Table 1.0 from the CHROMIUM_copy_texture spec
100 switch (internalFormat)
101 {
102 case GL_RGB:
103 case GL_RGBA:
104 case GL_RGB8:
105 case GL_RGBA8:
106 case GL_BGRA_EXT:
107 case GL_BGRA8_EXT:
108 case GL_SRGB_EXT:
109 case GL_SRGB_ALPHA_EXT:
110 case GL_R8:
111 case GL_R8UI:
112 case GL_RG8:
113 case GL_RG8UI:
114 case GL_SRGB8:
115 case GL_RGB565:
116 case GL_RGB8UI:
117 case GL_RGB10_A2:
118 case GL_SRGB8_ALPHA8:
119 case GL_RGB5_A1:
120 case GL_RGBA4:
121 case GL_RGBA8UI:
122 case GL_RGB9_E5:
123 case GL_R16F:
124 case GL_R32F:
125 case GL_RG16F:
126 case GL_RG32F:
127 case GL_RGB16F:
128 case GL_RGB32F:
129 case GL_RGBA16F:
130 case GL_RGBA32F:
131 case GL_R11F_G11F_B10F:
132 case GL_LUMINANCE:
133 case GL_LUMINANCE_ALPHA:
134 case GL_ALPHA:
135 return true;
136
137 default:
138 return false;
139 }
140 }
141
IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)142 bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
143 {
144 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
145 }
146
IsValidCopyTextureDestinationFormatType(const Context * context,GLint internalFormat,GLenum type)147 bool IsValidCopyTextureDestinationFormatType(const Context *context,
148 GLint internalFormat,
149 GLenum type)
150 {
151 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
152 {
153 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
154 return false;
155 }
156
157 if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
158 {
159 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
160 return false;
161 }
162
163 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
164 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
165 {
166 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
167 return false;
168 }
169
170 return true;
171 }
172
IsValidCopyTextureDestinationTargetEnum(const Context * context,TextureTarget target)173 bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target)
174 {
175 switch (target)
176 {
177 case TextureTarget::_2D:
178 case TextureTarget::CubeMapNegativeX:
179 case TextureTarget::CubeMapNegativeY:
180 case TextureTarget::CubeMapNegativeZ:
181 case TextureTarget::CubeMapPositiveX:
182 case TextureTarget::CubeMapPositiveY:
183 case TextureTarget::CubeMapPositiveZ:
184 return true;
185
186 case TextureTarget::Rectangle:
187 return context->getExtensions().textureRectangle;
188
189 default:
190 return false;
191 }
192 }
193
IsValidCopyTextureDestinationTarget(const Context * context,TextureType textureType,TextureTarget target)194 bool IsValidCopyTextureDestinationTarget(const Context *context,
195 TextureType textureType,
196 TextureTarget target)
197 {
198 return TextureTargetToType(target) == textureType;
199 }
200
IsValidCopyTextureSourceTarget(const Context * context,TextureType type)201 bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type)
202 {
203 switch (type)
204 {
205 case TextureType::_2D:
206 return true;
207 case TextureType::Rectangle:
208 return context->getExtensions().textureRectangle;
209 case TextureType::External:
210 return context->getExtensions().eglImageExternalOES;
211 case TextureType::VideoImage:
212 return context->getExtensions().webglVideoTexture;
213 default:
214 return false;
215 }
216 }
217
IsValidCopyTextureSourceLevel(const Context * context,TextureType type,GLint level)218 bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLint level)
219 {
220 if (!ValidMipLevel(context, type, level))
221 {
222 return false;
223 }
224
225 if (level > 0 && context->getClientVersion() < ES_3_0)
226 {
227 return false;
228 }
229
230 return true;
231 }
232
IsValidCopyTextureDestinationLevel(const Context * context,TextureType type,GLint level,GLsizei width,GLsizei height,bool isSubImage)233 bool IsValidCopyTextureDestinationLevel(const Context *context,
234 TextureType type,
235 GLint level,
236 GLsizei width,
237 GLsizei height,
238 bool isSubImage)
239 {
240 if (!ValidMipLevel(context, type, level))
241 {
242 return false;
243 }
244
245 if (!ValidImageSizeParameters(context, type, level, width, height, 1, isSubImage))
246 {
247 return false;
248 }
249
250 const Caps &caps = context->getCaps();
251 switch (type)
252 {
253 case TextureType::_2D:
254 return width <= (caps.max2DTextureSize >> level) &&
255 height <= (caps.max2DTextureSize >> level);
256 case TextureType::Rectangle:
257 ASSERT(level == 0);
258 return width <= (caps.max2DTextureSize >> level) &&
259 height <= (caps.max2DTextureSize >> level);
260
261 case TextureType::CubeMap:
262 return width <= (caps.maxCubeMapTextureSize >> level) &&
263 height <= (caps.maxCubeMapTextureSize >> level);
264 default:
265 return true;
266 }
267 }
268
IsValidStencilFunc(GLenum func)269 bool IsValidStencilFunc(GLenum func)
270 {
271 switch (func)
272 {
273 case GL_NEVER:
274 case GL_ALWAYS:
275 case GL_LESS:
276 case GL_LEQUAL:
277 case GL_EQUAL:
278 case GL_GEQUAL:
279 case GL_GREATER:
280 case GL_NOTEQUAL:
281 return true;
282
283 default:
284 return false;
285 }
286 }
287
IsValidStencilFace(GLenum face)288 bool IsValidStencilFace(GLenum face)
289 {
290 switch (face)
291 {
292 case GL_FRONT:
293 case GL_BACK:
294 case GL_FRONT_AND_BACK:
295 return true;
296
297 default:
298 return false;
299 }
300 }
301
IsValidStencilOp(GLenum op)302 bool IsValidStencilOp(GLenum op)
303 {
304 switch (op)
305 {
306 case GL_ZERO:
307 case GL_KEEP:
308 case GL_REPLACE:
309 case GL_INCR:
310 case GL_DECR:
311 case GL_INVERT:
312 case GL_INCR_WRAP:
313 case GL_DECR_WRAP:
314 return true;
315
316 default:
317 return false;
318 }
319 }
320
Valid1to4ComponentFloatColorBufferFormat(const Context * context,GLenum format)321 static inline bool Valid1to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
322 {
323 return (context->getExtensions().textureFloatOES &&
324 (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F ||
325 format == GL_R32F)) ||
326 (context->getExtensions().textureHalfFloat &&
327 (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F ||
328 format == GL_R16F));
329 }
330
Valid2to4ComponentFloatColorBufferFormat(const Context * context,GLenum format)331 static inline bool Valid2to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
332 {
333 return (context->getExtensions().textureFloatOES &&
334 (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F)) ||
335 (context->getExtensions().textureHalfFloat &&
336 (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F));
337 }
338
Valid3to4ComponentFloatColorBufferFormat(const Context * context,GLenum format)339 static inline bool Valid3to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
340 {
341 return (context->getExtensions().textureFloatOES &&
342 (format == GL_RGBA32F || format == GL_RGB32F)) ||
343 (context->getExtensions().textureHalfFloat &&
344 (format == GL_RGBA16F || format == GL_RGB16F));
345 }
346
Valid4ComponentFloatColorBufferFormat(const Context * context,GLenum format)347 static inline bool Valid4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
348 {
349 return (context->getExtensions().textureFloatOES && format == GL_RGBA32F) ||
350 (context->getExtensions().textureHalfFloat && format == GL_RGBA16F);
351 }
352
ValidateES2CopyTexImageParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)353 bool ValidateES2CopyTexImageParameters(const Context *context,
354 TextureTarget target,
355 GLint level,
356 GLenum internalformat,
357 bool isSubImage,
358 GLint xoffset,
359 GLint yoffset,
360 GLint x,
361 GLint y,
362 GLsizei width,
363 GLsizei height,
364 GLint border)
365 {
366 if (!ValidTexture2DDestinationTarget(context, target))
367 {
368 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
369 return false;
370 }
371
372 TextureType texType = TextureTargetToType(target);
373 if (!ValidImageSizeParameters(context, texType, level, width, height, 1, isSubImage))
374 {
375 // Error is already handled.
376 return false;
377 }
378
379 Format textureFormat = Format::Invalid();
380 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
381 xoffset, yoffset, 0, x, y, width, height, border,
382 &textureFormat))
383 {
384 return false;
385 }
386
387 const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
388 GLenum colorbufferFormat =
389 framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat;
390 const auto &formatInfo = *textureFormat.info;
391
392 // [OpenGL ES 2.0.24] table 3.9
393 if (isSubImage)
394 {
395 switch (formatInfo.format)
396 {
397 case GL_ALPHA:
398 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
399 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
400 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
401 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
402 {
403 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
404 return false;
405 }
406 break;
407 case GL_LUMINANCE:
408 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
409 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
410 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
411 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
412 colorbufferFormat != GL_BGR5_A1_ANGLEX &&
413 !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
414 {
415 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
416 return false;
417 }
418 break;
419 case GL_RED_EXT:
420 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
421 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
422 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
423 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
424 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
425 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
426 colorbufferFormat != GL_BGR5_A1_ANGLEX &&
427 !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
428 {
429 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
430 return false;
431 }
432 break;
433 case GL_RG_EXT:
434 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
435 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
436 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
437 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
438 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
439 colorbufferFormat != GL_BGR5_A1_ANGLEX &&
440 !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
441 {
442 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
443 return false;
444 }
445 break;
446 case GL_RGB:
447 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
448 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
449 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
450 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
451 colorbufferFormat != GL_BGR5_A1_ANGLEX &&
452 colorbufferFormat != GL_BGRX8_ANGLEX &&
453 !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
454 {
455 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
456 return false;
457 }
458 break;
459 case GL_LUMINANCE_ALPHA:
460 case GL_RGBA:
461 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
462 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
463 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
464 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
465 {
466 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
467 return false;
468 }
469 break;
470 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
471 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
472 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
473 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
474 case GL_ETC1_RGB8_OES:
475 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
476 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
477 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
478 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
479 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
480 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
481 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
482 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
483 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
484 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
485 return false;
486 case GL_DEPTH_COMPONENT:
487 case GL_DEPTH_STENCIL_OES:
488 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
489 return false;
490 default:
491 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
492 return false;
493 }
494
495 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES)
496 {
497 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
498 return false;
499 }
500 }
501 else
502 {
503 switch (internalformat)
504 {
505 case GL_ALPHA:
506 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
507 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
508 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
509 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
510 {
511 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
512 return false;
513 }
514 break;
515 case GL_LUMINANCE:
516 case GL_RED_EXT:
517 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
518 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
519 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
520 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
521 colorbufferFormat != GL_BGR5_A1_ANGLEX &&
522 !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
523 {
524 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
525 return false;
526 }
527 break;
528 case GL_RG_EXT:
529 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
530 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
531 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
532 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
533 !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
534 {
535 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
536 return false;
537 }
538 break;
539 case GL_RGB:
540 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
541 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
542 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
543 colorbufferFormat != GL_BGR5_A1_ANGLEX &&
544 !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
545 {
546 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
547 return false;
548 }
549 break;
550 case GL_LUMINANCE_ALPHA:
551 case GL_RGBA:
552 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
553 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
554 colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_RGBA16F &&
555 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
556 {
557 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
558 return false;
559 }
560 break;
561 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
562 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
563 if (context->getExtensions().textureCompressionDXT1)
564 {
565 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
566 return false;
567 }
568 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
569 return false;
570 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
571 if (context->getExtensions().textureCompressionDXT3)
572 {
573 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
574 return false;
575 }
576 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
577 return false;
578 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
579 if (context->getExtensions().textureCompressionDXT5)
580 {
581 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
582 return false;
583 }
584 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
585 return false;
586 case GL_ETC1_RGB8_OES:
587 if (context->getExtensions().compressedETC1RGB8TextureOES)
588 {
589 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
590 return false;
591 }
592 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
593 return false;
594 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
595 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
596 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
597 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
598 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
599 if (context->getExtensions().lossyETCDecode)
600 {
601 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
602 return false;
603 }
604 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
605 return false;
606 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
607 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
608 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
609 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
610 if (context->getExtensions().compressedTexturePVRTC)
611 {
612 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
613 return false;
614 }
615 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
616 return false;
617 case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
618 case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
619 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
620 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
621 if (context->getExtensions().compressedTexturePVRTCsRGB)
622 {
623 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
624 return false;
625 }
626 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
627 return false;
628 case GL_DEPTH_COMPONENT:
629 case GL_DEPTH_COMPONENT16:
630 case GL_DEPTH_COMPONENT32_OES:
631 if (context->getExtensions().depthTextureAny())
632 {
633 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
634 return false;
635 }
636 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
637 return false;
638 case GL_DEPTH_STENCIL_OES:
639 case GL_DEPTH24_STENCIL8_OES:
640 if (context->getExtensions().depthTextureAny() ||
641 context->getExtensions().packedDepthStencilOES ||
642 context->getExtensions().depthTextureCubeMapOES)
643 {
644 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
645 return false;
646 }
647 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
648 return false;
649 default:
650 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
651 return false;
652 }
653 }
654
655 // If width or height is zero, it is a no-op. Return false without setting an error.
656 return (width > 0 && height > 0);
657 }
658
ValidCap(const Context * context,GLenum cap,bool queryOnly)659 bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
660 {
661 switch (cap)
662 {
663 // EXT_multisample_compatibility
664 case GL_MULTISAMPLE_EXT:
665 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
666 return context->getExtensions().multisampleCompatibility;
667
668 case GL_CULL_FACE:
669 case GL_POLYGON_OFFSET_FILL:
670 case GL_SAMPLE_ALPHA_TO_COVERAGE:
671 case GL_SAMPLE_COVERAGE:
672 case GL_SCISSOR_TEST:
673 case GL_STENCIL_TEST:
674 case GL_DEPTH_TEST:
675 case GL_BLEND:
676 case GL_DITHER:
677 return true;
678
679 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
680 case GL_RASTERIZER_DISCARD:
681 return (context->getClientMajorVersion() >= 3);
682
683 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
684 case GL_DEBUG_OUTPUT:
685 return context->getExtensions().debug;
686
687 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
688 return queryOnly && context->getExtensions().bindGeneratesResource;
689
690 case GL_CLIENT_ARRAYS_ANGLE:
691 return queryOnly && context->getExtensions().clientArrays;
692
693 case GL_FRAMEBUFFER_SRGB_EXT:
694 return context->getExtensions().sRGBWriteControl;
695
696 case GL_SAMPLE_MASK:
697 return context->getClientVersion() >= Version(3, 1);
698
699 case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
700 return queryOnly && context->getExtensions().robustResourceInitialization;
701
702 case GL_TEXTURE_RECTANGLE_ANGLE:
703 return context->getExtensions().webglCompatibility;
704
705 // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
706 case GL_CLIP_DISTANCE0_EXT:
707 case GL_CLIP_DISTANCE1_EXT:
708 case GL_CLIP_DISTANCE2_EXT:
709 case GL_CLIP_DISTANCE3_EXT:
710 case GL_CLIP_DISTANCE4_EXT:
711 case GL_CLIP_DISTANCE5_EXT:
712 case GL_CLIP_DISTANCE6_EXT:
713 case GL_CLIP_DISTANCE7_EXT:
714 if (context->getExtensions().clipDistanceAPPLE ||
715 context->getExtensions().clipCullDistanceEXT)
716 {
717 return true;
718 }
719 break;
720 case GL_SAMPLE_SHADING:
721 return context->getExtensions().sampleShadingOES;
722 }
723
724 // GLES1 emulation: GLES1-specific caps after this point
725 if (context->getClientVersion().major != 1)
726 {
727 return false;
728 }
729
730 switch (cap)
731 {
732 case GL_ALPHA_TEST:
733 case GL_VERTEX_ARRAY:
734 case GL_NORMAL_ARRAY:
735 case GL_COLOR_ARRAY:
736 case GL_TEXTURE_COORD_ARRAY:
737 case GL_TEXTURE_2D:
738 case GL_LIGHTING:
739 case GL_LIGHT0:
740 case GL_LIGHT1:
741 case GL_LIGHT2:
742 case GL_LIGHT3:
743 case GL_LIGHT4:
744 case GL_LIGHT5:
745 case GL_LIGHT6:
746 case GL_LIGHT7:
747 case GL_NORMALIZE:
748 case GL_RESCALE_NORMAL:
749 case GL_COLOR_MATERIAL:
750 case GL_CLIP_PLANE0:
751 case GL_CLIP_PLANE1:
752 case GL_CLIP_PLANE2:
753 case GL_CLIP_PLANE3:
754 case GL_CLIP_PLANE4:
755 case GL_CLIP_PLANE5:
756 case GL_FOG:
757 case GL_POINT_SMOOTH:
758 case GL_LINE_SMOOTH:
759 case GL_COLOR_LOGIC_OP:
760 return context->getClientVersion() < Version(2, 0);
761 case GL_POINT_SIZE_ARRAY_OES:
762 return context->getClientVersion() < Version(2, 0) &&
763 context->getExtensions().pointSizeArrayOES;
764 case GL_TEXTURE_CUBE_MAP:
765 return context->getClientVersion() < Version(2, 0) &&
766 context->getExtensions().textureCubeMapOES;
767 case GL_POINT_SPRITE_OES:
768 return context->getClientVersion() < Version(2, 0) &&
769 context->getExtensions().pointSpriteOES;
770 default:
771 return false;
772 }
773 }
774
775 // Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
776 // 3.1.
IsValidESSLCharacter(unsigned char c)777 bool IsValidESSLCharacter(unsigned char c)
778 {
779 // Printing characters are valid except " $ ` @ \ ' DEL.
780 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
781 c != '\'')
782 {
783 return true;
784 }
785
786 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
787 if (c >= 9 && c <= 13)
788 {
789 return true;
790 }
791
792 return false;
793 }
794
IsValidESSLString(const char * str,size_t len)795 bool IsValidESSLString(const char *str, size_t len)
796 {
797 for (size_t i = 0; i < len; i++)
798 {
799 if (!IsValidESSLCharacter(str[i]))
800 {
801 return false;
802 }
803 }
804
805 return true;
806 }
807
ValidateWebGLNamePrefix(const Context * context,const GLchar * name)808 bool ValidateWebGLNamePrefix(const Context *context, const GLchar *name)
809 {
810 ASSERT(context->isWebGL());
811
812 // WebGL 1.0 [Section 6.16] GLSL Constructs
813 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
814 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
815 {
816 context->validationError(GL_INVALID_OPERATION, kWebglBindAttribLocationReservedPrefix);
817 return false;
818 }
819
820 return true;
821 }
822
ValidateWebGLNameLength(const Context * context,size_t length)823 bool ValidateWebGLNameLength(const Context *context, size_t length)
824 {
825 ASSERT(context->isWebGL());
826
827 if (context->isWebGL1() && length > 256)
828 {
829 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
830 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
831 // locations.
832 context->validationError(GL_INVALID_VALUE, kWebglNameLengthLimitExceeded);
833
834 return false;
835 }
836 else if (length > 1024)
837 {
838 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
839 // uniform and attribute locations.
840 context->validationError(GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded);
841 return false;
842 }
843
844 return true;
845 }
846
ValidBlendFunc(const Context * context,GLenum val)847 bool ValidBlendFunc(const Context *context, GLenum val)
848 {
849 const Extensions &ext = context->getExtensions();
850
851 // these are always valid for src and dst.
852 switch (val)
853 {
854 case GL_ZERO:
855 case GL_ONE:
856 case GL_SRC_COLOR:
857 case GL_ONE_MINUS_SRC_COLOR:
858 case GL_DST_COLOR:
859 case GL_ONE_MINUS_DST_COLOR:
860 case GL_SRC_ALPHA:
861 case GL_ONE_MINUS_SRC_ALPHA:
862 case GL_DST_ALPHA:
863 case GL_ONE_MINUS_DST_ALPHA:
864 case GL_CONSTANT_COLOR:
865 case GL_ONE_MINUS_CONSTANT_COLOR:
866 case GL_CONSTANT_ALPHA:
867 case GL_ONE_MINUS_CONSTANT_ALPHA:
868 return true;
869
870 // EXT_blend_func_extended.
871 case GL_SRC1_COLOR_EXT:
872 case GL_SRC1_ALPHA_EXT:
873 case GL_ONE_MINUS_SRC1_COLOR_EXT:
874 case GL_ONE_MINUS_SRC1_ALPHA_EXT:
875 case GL_SRC_ALPHA_SATURATE_EXT:
876 return ext.blendFuncExtended;
877
878 default:
879 return false;
880 }
881 }
882
ValidSrcBlendFunc(const Context * context,GLenum val)883 bool ValidSrcBlendFunc(const Context *context, GLenum val)
884 {
885 if (ValidBlendFunc(context, val))
886 return true;
887
888 if (val == GL_SRC_ALPHA_SATURATE)
889 return true;
890
891 return false;
892 }
893
ValidDstBlendFunc(const Context * context,GLenum val)894 bool ValidDstBlendFunc(const Context *context, GLenum val)
895 {
896 if (ValidBlendFunc(context, val))
897 return true;
898
899 if (val == GL_SRC_ALPHA_SATURATE)
900 {
901 if (context->getClientMajorVersion() >= 3)
902 return true;
903 }
904
905 return false;
906 }
907
ValidateES2TexImageParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)908 bool ValidateES2TexImageParameters(const Context *context,
909 TextureTarget target,
910 GLint level,
911 GLenum internalformat,
912 bool isCompressed,
913 bool isSubImage,
914 GLint xoffset,
915 GLint yoffset,
916 GLsizei width,
917 GLsizei height,
918 GLint border,
919 GLenum format,
920 GLenum type,
921 GLsizei imageSize,
922 const void *pixels)
923 {
924 if (!ValidTexture2DDestinationTarget(context, target))
925 {
926 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
927 return false;
928 }
929
930 return ValidateES2TexImageParametersBase(context, target, level, internalformat, isCompressed,
931 isSubImage, xoffset, yoffset, width, height, border,
932 format, type, imageSize, pixels);
933 }
934
935 } // anonymous namespace
936
ValidateES2TexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)937 bool ValidateES2TexImageParametersBase(const Context *context,
938 TextureTarget target,
939 GLint level,
940 GLenum internalformat,
941 bool isCompressed,
942 bool isSubImage,
943 GLint xoffset,
944 GLint yoffset,
945 GLsizei width,
946 GLsizei height,
947 GLint border,
948 GLenum format,
949 GLenum type,
950 GLsizei imageSize,
951 const void *pixels)
952 {
953
954 TextureType texType = TextureTargetToType(target);
955 if (!ValidImageSizeParameters(context, texType, level, width, height, 1, isSubImage))
956 {
957 // Error already handled.
958 return false;
959 }
960
961 if (!ValidMipLevel(context, texType, level))
962 {
963 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
964 return false;
965 }
966
967 if ((xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width) ||
968 (yoffset < 0 || std::numeric_limits<GLsizei>::max() - yoffset < height))
969 {
970 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
971 return false;
972 }
973
974 const Caps &caps = context->getCaps();
975
976 switch (texType)
977 {
978 case TextureType::_2D:
979 case TextureType::External:
980 case TextureType::VideoImage:
981 if (width > (caps.max2DTextureSize >> level) ||
982 height > (caps.max2DTextureSize >> level))
983 {
984 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
985 return false;
986 }
987 break;
988
989 case TextureType::Rectangle:
990 ASSERT(level == 0);
991 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
992 {
993 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
994 return false;
995 }
996 if (isCompressed)
997 {
998 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
999 return false;
1000 }
1001 break;
1002
1003 case TextureType::CubeMap:
1004 if (!isSubImage && width != height)
1005 {
1006 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1007 return false;
1008 }
1009
1010 if (width > (caps.maxCubeMapTextureSize >> level) ||
1011 height > (caps.maxCubeMapTextureSize >> level))
1012 {
1013 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1014 return false;
1015 }
1016 break;
1017
1018 default:
1019 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1020 return false;
1021 }
1022
1023 Texture *texture = context->getTextureByType(texType);
1024 if (!texture)
1025 {
1026 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
1027 return false;
1028 }
1029
1030 // Verify zero border
1031 if (border != 0)
1032 {
1033 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
1034 return false;
1035 }
1036
1037 bool nonEqualFormatsAllowed = false;
1038
1039 if (isCompressed)
1040 {
1041 GLenum actualInternalFormat =
1042 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
1043 : internalformat;
1044
1045 const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(actualInternalFormat);
1046
1047 if (!internalFormatInfo.compressed)
1048 {
1049 context->validationError(GL_INVALID_ENUM, kInvalidInternalFormat);
1050 return false;
1051 }
1052
1053 if (!internalFormatInfo.textureSupport(context->getClientVersion(),
1054 context->getExtensions()))
1055 {
1056 context->validationError(GL_INVALID_ENUM, kInvalidInternalFormat);
1057 return false;
1058 }
1059
1060 if (isSubImage)
1061 {
1062 // From the OES_compressed_ETC1_RGB8_texture spec:
1063 //
1064 // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or
1065 // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format
1066 // ETC1_RGB8_OES.
1067 //
1068 // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported.
1069 if (actualInternalFormat == GL_ETC1_RGB8_OES &&
1070 !context->getExtensions().compressedETC1RGB8SubTexture)
1071 {
1072 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
1073 return false;
1074 }
1075
1076 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, 0,
1077 width, height, 1, texture->getWidth(target, level),
1078 texture->getHeight(target, level),
1079 texture->getDepth(target, level)))
1080 {
1081 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1082 return false;
1083 }
1084
1085 if (format != actualInternalFormat)
1086 {
1087 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1088 return false;
1089 }
1090 }
1091 else
1092 {
1093 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height, 1))
1094 {
1095 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1096 return false;
1097 }
1098 }
1099 }
1100 else
1101 {
1102 // validate <type> by itself (used as secondary key below)
1103 switch (type)
1104 {
1105 case GL_UNSIGNED_BYTE:
1106 case GL_UNSIGNED_SHORT_5_6_5:
1107 case GL_UNSIGNED_SHORT_4_4_4_4:
1108 case GL_UNSIGNED_SHORT_5_5_5_1:
1109 case GL_UNSIGNED_SHORT:
1110 case GL_UNSIGNED_INT:
1111 case GL_UNSIGNED_INT_24_8_OES:
1112 case GL_HALF_FLOAT_OES:
1113 case GL_FLOAT:
1114 break;
1115 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1116 if (!context->getExtensions().textureFormat2101010REV)
1117 {
1118 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1119 return false;
1120 }
1121 break;
1122 default:
1123 context->validationError(GL_INVALID_ENUM, kInvalidType);
1124 return false;
1125 }
1126
1127 // validate <format> + <type> combinations
1128 // - invalid <format> -> sets INVALID_ENUM
1129 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1130 switch (format)
1131 {
1132 case GL_ALPHA:
1133 case GL_LUMINANCE:
1134 case GL_LUMINANCE_ALPHA:
1135 switch (type)
1136 {
1137 case GL_UNSIGNED_BYTE:
1138 case GL_FLOAT:
1139 case GL_HALF_FLOAT_OES:
1140 break;
1141 default:
1142 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1143 return false;
1144 }
1145 break;
1146 case GL_RED:
1147 case GL_RG:
1148 if (!context->getExtensions().textureRG)
1149 {
1150 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1151 return false;
1152 }
1153 switch (type)
1154 {
1155 case GL_UNSIGNED_BYTE:
1156 break;
1157 case GL_FLOAT:
1158 if (!context->getExtensions().textureFloatOES)
1159 {
1160 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1161 return false;
1162 }
1163 break;
1164 case GL_HALF_FLOAT_OES:
1165 if (!context->getExtensions().textureFloatOES &&
1166 !context->getExtensions().textureHalfFloat)
1167 {
1168 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1169 return false;
1170 }
1171 break;
1172 case GL_SHORT:
1173 case GL_UNSIGNED_SHORT:
1174 if (!context->getExtensions().textureNorm16)
1175 {
1176 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1177 return false;
1178 }
1179 break;
1180 default:
1181 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1182 return false;
1183 }
1184 break;
1185 case GL_RGB:
1186 switch (type)
1187 {
1188 case GL_UNSIGNED_BYTE:
1189 case GL_UNSIGNED_SHORT_5_6_5:
1190 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1191 case GL_FLOAT:
1192 case GL_HALF_FLOAT_OES:
1193 break;
1194 case GL_SHORT:
1195 case GL_UNSIGNED_SHORT:
1196 if (!context->getExtensions().textureNorm16)
1197 {
1198 context->validationError(GL_INVALID_OPERATION,
1199 kMismatchedTypeAndFormat);
1200 return false;
1201 }
1202 break;
1203 default:
1204 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1205 return false;
1206 }
1207 break;
1208 case GL_RGBA:
1209 switch (type)
1210 {
1211 case GL_UNSIGNED_BYTE:
1212 case GL_UNSIGNED_SHORT_4_4_4_4:
1213 case GL_UNSIGNED_SHORT_5_5_5_1:
1214 case GL_FLOAT:
1215 case GL_HALF_FLOAT_OES:
1216 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1217 break;
1218 case GL_SHORT:
1219 case GL_UNSIGNED_SHORT:
1220 if (!context->getExtensions().textureNorm16)
1221 {
1222 context->validationError(GL_INVALID_OPERATION,
1223 kMismatchedTypeAndFormat);
1224 return false;
1225 }
1226 break;
1227 default:
1228 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1229 return false;
1230 }
1231 break;
1232 case GL_BGRA_EXT:
1233 if (!context->getExtensions().textureFormatBGRA8888)
1234 {
1235 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1236 return false;
1237 }
1238 switch (type)
1239 {
1240 case GL_UNSIGNED_BYTE:
1241 break;
1242 default:
1243 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1244 return false;
1245 }
1246 break;
1247 case GL_SRGB_EXT:
1248 case GL_SRGB_ALPHA_EXT:
1249 if (!context->getExtensions().sRGB)
1250 {
1251 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1252 return false;
1253 }
1254 switch (type)
1255 {
1256 case GL_UNSIGNED_BYTE:
1257 break;
1258 default:
1259 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1260 return false;
1261 }
1262 break;
1263 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1264 // handled below
1265 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1266 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1267 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1268 break;
1269 case GL_DEPTH_COMPONENT:
1270 switch (type)
1271 {
1272 case GL_UNSIGNED_SHORT:
1273 case GL_UNSIGNED_INT:
1274 break;
1275 case GL_FLOAT:
1276 if (!context->getExtensions().depthBufferFloat2NV)
1277 {
1278 context->validationError(GL_INVALID_OPERATION,
1279 kMismatchedTypeAndFormat);
1280 return false;
1281 }
1282 break;
1283 default:
1284 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1285 return false;
1286 }
1287 break;
1288 case GL_DEPTH_STENCIL_OES:
1289 switch (type)
1290 {
1291 case GL_UNSIGNED_INT_24_8_OES:
1292 break;
1293 default:
1294 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1295 return false;
1296 }
1297 break;
1298 case GL_STENCIL_INDEX:
1299 switch (type)
1300 {
1301 case GL_UNSIGNED_BYTE:
1302 break;
1303 default:
1304 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1305 return false;
1306 }
1307 break;
1308 default:
1309 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1310 return false;
1311 }
1312
1313 switch (format)
1314 {
1315 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1316 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1317 if (context->getExtensions().textureCompressionDXT1)
1318 {
1319 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1320 return false;
1321 }
1322 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1323 return false;
1324 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1325 if (context->getExtensions().textureCompressionDXT3)
1326 {
1327 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1328 return false;
1329 }
1330 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1331 return false;
1332 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1333 if (context->getExtensions().textureCompressionDXT5)
1334 {
1335 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1336 return false;
1337 }
1338 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1339 return false;
1340 case GL_ETC1_RGB8_OES:
1341 if (context->getExtensions().compressedETC1RGB8TextureOES)
1342 {
1343 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1344 return false;
1345 }
1346 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1347 return false;
1348 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1349 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1350 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1351 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1352 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1353 if (context->getExtensions().lossyETCDecode)
1354 {
1355 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1356 return false;
1357 }
1358 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1359 return false;
1360 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
1361 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
1362 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
1363 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
1364 if (context->getExtensions().compressedTexturePVRTC)
1365 {
1366 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1367 return false;
1368 }
1369 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1370 return false;
1371 case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
1372 case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
1373 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
1374 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
1375 if (context->getExtensions().compressedTexturePVRTCsRGB)
1376 {
1377 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1378 return false;
1379 }
1380 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1381 return false;
1382 case GL_DEPTH_COMPONENT:
1383 case GL_DEPTH_STENCIL_OES:
1384 if (!context->getExtensions().depthTextureANGLE &&
1385 !((context->getExtensions().packedDepthStencilOES ||
1386 context->getExtensions().depthTextureCubeMapOES) &&
1387 context->getExtensions().depthTextureOES))
1388 {
1389 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1390 return false;
1391 }
1392
1393 switch (target)
1394 {
1395 case TextureTarget::_2D:
1396 break;
1397 case TextureTarget::CubeMapNegativeX:
1398 case TextureTarget::CubeMapNegativeY:
1399 case TextureTarget::CubeMapNegativeZ:
1400 case TextureTarget::CubeMapPositiveX:
1401 case TextureTarget::CubeMapPositiveY:
1402 case TextureTarget::CubeMapPositiveZ:
1403 if (!context->getExtensions().depthTextureCubeMapOES)
1404 {
1405 context->validationError(GL_INVALID_OPERATION,
1406 kMismatchedTargetAndFormat);
1407 return false;
1408 }
1409 break;
1410 default:
1411 context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1412 return false;
1413 }
1414
1415 // OES_depth_texture supports loading depth data and multiple levels,
1416 // but ANGLE_depth_texture does not
1417 if (!context->getExtensions().depthTextureOES)
1418 {
1419 if (pixels != nullptr)
1420 {
1421 context->validationError(GL_INVALID_OPERATION, kPixelDataNotNull);
1422 return false;
1423 }
1424 if (level != 0)
1425 {
1426 context->validationError(GL_INVALID_OPERATION, kLevelNotZero);
1427 return false;
1428 }
1429 }
1430 break;
1431 case GL_STENCIL_INDEX:
1432 if (!context->getExtensions().stencilIndex8)
1433 {
1434 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1435 return false;
1436 }
1437
1438 switch (target)
1439 {
1440 case TextureTarget::_2D:
1441 case TextureTarget::_2DArray:
1442 case TextureTarget::CubeMapNegativeX:
1443 case TextureTarget::CubeMapNegativeY:
1444 case TextureTarget::CubeMapNegativeZ:
1445 case TextureTarget::CubeMapPositiveX:
1446 case TextureTarget::CubeMapPositiveY:
1447 case TextureTarget::CubeMapPositiveZ:
1448 break;
1449 default:
1450 context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1451 return false;
1452 }
1453
1454 if (internalformat != GL_STENCIL_INDEX8)
1455 {
1456 context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1457 return false;
1458 }
1459 break;
1460 default:
1461 break;
1462 }
1463
1464 if (!isSubImage)
1465 {
1466 switch (internalformat)
1467 {
1468 // Core ES 2.0 formats
1469 case GL_ALPHA:
1470 case GL_LUMINANCE:
1471 case GL_LUMINANCE_ALPHA:
1472 case GL_RGB:
1473 case GL_RGBA:
1474 break;
1475
1476 case GL_RGBA32F:
1477 if (!context->getExtensions().colorBufferFloatRGBA)
1478 {
1479 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1480 return false;
1481 }
1482
1483 nonEqualFormatsAllowed = true;
1484
1485 if (type != GL_FLOAT)
1486 {
1487 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1488 return false;
1489 }
1490 if (format != GL_RGBA)
1491 {
1492 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1493 return false;
1494 }
1495 break;
1496
1497 case GL_RGB32F:
1498 if (!context->getExtensions().colorBufferFloatRGB)
1499 {
1500 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1501 return false;
1502 }
1503
1504 nonEqualFormatsAllowed = true;
1505
1506 if (type != GL_FLOAT)
1507 {
1508 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1509 return false;
1510 }
1511 if (format != GL_RGB)
1512 {
1513 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1514 return false;
1515 }
1516 break;
1517
1518 case GL_BGRA_EXT:
1519 if (!context->getExtensions().textureFormatBGRA8888)
1520 {
1521 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1522 return false;
1523 }
1524 break;
1525
1526 case GL_DEPTH_COMPONENT:
1527 if (!(context->getExtensions().depthTextureAny()))
1528 {
1529 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1530 return false;
1531 }
1532 break;
1533
1534 case GL_DEPTH_STENCIL:
1535 if (!(context->getExtensions().depthTextureANGLE ||
1536 context->getExtensions().packedDepthStencilOES ||
1537 context->getExtensions().depthTextureCubeMapOES))
1538 {
1539 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1540 return false;
1541 }
1542 break;
1543
1544 case GL_STENCIL_INDEX8:
1545 if (!context->getExtensions().stencilIndex8)
1546 {
1547 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1548 return false;
1549 }
1550 break;
1551
1552 case GL_RED:
1553 case GL_RG:
1554 if (!context->getExtensions().textureRG)
1555 {
1556 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1557 return false;
1558 }
1559 break;
1560
1561 case GL_SRGB_EXT:
1562 case GL_SRGB_ALPHA_EXT:
1563 if (!context->getExtensions().sRGB)
1564 {
1565 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1566 return false;
1567 }
1568 break;
1569
1570 case GL_RGB10_A2_EXT:
1571 if (!context->getExtensions().textureFormat2101010REV)
1572 {
1573 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1574 return false;
1575 }
1576
1577 if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA)
1578 {
1579 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1580 return false;
1581 }
1582
1583 nonEqualFormatsAllowed = true;
1584
1585 break;
1586
1587 case GL_RGB5_A1:
1588 if (context->getExtensions().textureFormat2101010REV &&
1589 type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA)
1590 {
1591 nonEqualFormatsAllowed = true;
1592 }
1593
1594 break;
1595
1596 case GL_R16_EXT:
1597 case GL_RG16_EXT:
1598 case GL_RGB16_EXT:
1599 case GL_RGBA16_EXT:
1600 case GL_R16_SNORM_EXT:
1601 case GL_RG16_SNORM_EXT:
1602 case GL_RGB16_SNORM_EXT:
1603 case GL_RGBA16_SNORM_EXT:
1604 if (!context->getExtensions().textureNorm16)
1605 {
1606 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1607 return false;
1608 }
1609 break;
1610 default:
1611 context->validationError(GL_INVALID_VALUE, kInvalidInternalFormat);
1612 return false;
1613 }
1614 }
1615
1616 if (type == GL_FLOAT)
1617 {
1618 if (!context->getExtensions().textureFloatOES)
1619 {
1620 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1621 return false;
1622 }
1623 }
1624 else if (type == GL_HALF_FLOAT_OES)
1625 {
1626 if (!context->getExtensions().textureHalfFloat)
1627 {
1628 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1629 return false;
1630 }
1631 }
1632 }
1633
1634 if (isSubImage)
1635 {
1636 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1637 if (textureInternalFormat.internalFormat == GL_NONE)
1638 {
1639 context->validationError(GL_INVALID_OPERATION, kInvalidTextureLevel);
1640 return false;
1641 }
1642
1643 if (format != textureInternalFormat.format)
1644 {
1645 context->validationError(GL_INVALID_OPERATION, err::kTextureFormatMismatch);
1646 return false;
1647 }
1648
1649 if (context->getExtensions().webglCompatibility)
1650 {
1651 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1652 textureInternalFormat.sizedInternalFormat)
1653 {
1654 context->validationError(GL_INVALID_OPERATION, kTextureTypeMismatch);
1655 return false;
1656 }
1657 }
1658
1659 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1660 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1661 {
1662 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
1663 return false;
1664 }
1665
1666 if (width > 0 && height > 0 && pixels == nullptr &&
1667 context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
1668 {
1669 context->validationError(GL_INVALID_VALUE, kPixelDataNull);
1670 return false;
1671 }
1672 }
1673 else
1674 {
1675 if (texture->getImmutableFormat())
1676 {
1677 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
1678 return false;
1679 }
1680 }
1681
1682 // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1683 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1684 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1685 // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1686 // case.
1687 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
1688 {
1689 context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
1690 return false;
1691 }
1692
1693 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1694 return ValidImageDataSize(context, texType, width, height, 1, sizeCheckFormat, type, pixels,
1695 imageSize);
1696 }
1697
ValidateES2TexStorageParametersBase(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)1698 bool ValidateES2TexStorageParametersBase(const Context *context,
1699 TextureType target,
1700 GLsizei levels,
1701 GLenum internalformat,
1702 GLsizei width,
1703 GLsizei height)
1704 {
1705 if (target != TextureType::_2D && target != TextureType::CubeMap &&
1706 target != TextureType::Rectangle)
1707 {
1708 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1709 return false;
1710 }
1711
1712 if (width < 1 || height < 1 || levels < 1)
1713 {
1714 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
1715 return false;
1716 }
1717
1718 if (target == TextureType::CubeMap && width != height)
1719 {
1720 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1721 return false;
1722 }
1723
1724 if (levels != 1 && levels != log2(std::max(width, height)) + 1)
1725 {
1726 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1727 return false;
1728 }
1729
1730 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1731 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
1732 {
1733 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1734 return false;
1735 }
1736
1737 const Caps &caps = context->getCaps();
1738
1739 switch (target)
1740 {
1741 case TextureType::_2D:
1742 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
1743 {
1744 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1745 return false;
1746 }
1747 break;
1748 case TextureType::Rectangle:
1749 if (levels != 1)
1750 {
1751 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
1752 return false;
1753 }
1754
1755 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1756 {
1757 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1758 return false;
1759 }
1760 if (formatInfo.compressed)
1761 {
1762 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
1763 return false;
1764 }
1765 break;
1766 case TextureType::CubeMap:
1767 if (width > caps.maxCubeMapTextureSize || height > caps.maxCubeMapTextureSize)
1768 {
1769 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1770 return false;
1771 }
1772 break;
1773 default:
1774 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1775 return false;
1776 }
1777
1778 if (levels != 1 && !context->getExtensions().textureNPOTOES)
1779 {
1780 if (!isPow2(width) || !isPow2(height))
1781 {
1782 context->validationError(GL_INVALID_OPERATION, kDimensionsMustBePow2);
1783 return false;
1784 }
1785 }
1786
1787 switch (internalformat)
1788 {
1789 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1790 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1791 if (!context->getExtensions().textureCompressionDXT1)
1792 {
1793 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1794 return false;
1795 }
1796 break;
1797 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1798 if (!context->getExtensions().textureCompressionDXT3)
1799 {
1800 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1801 return false;
1802 }
1803 break;
1804 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1805 if (!context->getExtensions().textureCompressionDXT5)
1806 {
1807 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1808 return false;
1809 }
1810 break;
1811 case GL_ETC1_RGB8_OES:
1812 if (!context->getExtensions().compressedETC1RGB8TextureOES)
1813 {
1814 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1815 return false;
1816 }
1817 break;
1818 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1819 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1820 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1821 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1822 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1823 if (!context->getExtensions().lossyETCDecode)
1824 {
1825 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1826 return false;
1827 }
1828 break;
1829 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
1830 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
1831 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
1832 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
1833 if (!context->getExtensions().compressedTexturePVRTC)
1834 {
1835 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1836 return false;
1837 }
1838 break;
1839 case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
1840 case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
1841 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
1842 case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
1843 if (!context->getExtensions().compressedTexturePVRTCsRGB)
1844 {
1845 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1846 return false;
1847 }
1848 break;
1849 case GL_RGBA32F_EXT:
1850 case GL_RGB32F_EXT:
1851 case GL_ALPHA32F_EXT:
1852 case GL_LUMINANCE32F_EXT:
1853 case GL_LUMINANCE_ALPHA32F_EXT:
1854 if (!context->getExtensions().textureFloatOES)
1855 {
1856 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1857 return false;
1858 }
1859 break;
1860 case GL_RGBA16F_EXT:
1861 case GL_RGB16F_EXT:
1862 case GL_ALPHA16F_EXT:
1863 case GL_LUMINANCE16F_EXT:
1864 case GL_LUMINANCE_ALPHA16F_EXT:
1865 if (!context->getExtensions().textureHalfFloat)
1866 {
1867 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1868 return false;
1869 }
1870 break;
1871 case GL_R8_EXT:
1872 case GL_RG8_EXT:
1873 if (!context->getExtensions().textureRG)
1874 {
1875 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1876 return false;
1877 }
1878 break;
1879 case GL_R16F_EXT:
1880 case GL_RG16F_EXT:
1881 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1882 {
1883 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1884 return false;
1885 }
1886 break;
1887 case GL_R32F_EXT:
1888 case GL_RG32F_EXT:
1889 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloatOES)
1890 {
1891 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1892 return false;
1893 }
1894 break;
1895 case GL_DEPTH_COMPONENT16:
1896 case GL_DEPTH_COMPONENT32_OES:
1897 if (!(context->getExtensions().depthTextureAny()))
1898 {
1899 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1900 return false;
1901 }
1902
1903 switch (target)
1904 {
1905 case TextureType::_2D:
1906 break;
1907 case TextureType::CubeMap:
1908 if (!context->getExtensions().depthTextureCubeMapOES)
1909 {
1910 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1911 return false;
1912 }
1913 break;
1914 default:
1915 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1916 return false;
1917 }
1918
1919 // ANGLE_depth_texture only supports 1-level textures
1920 if (!context->getExtensions().depthTextureOES)
1921 {
1922 if (levels != 1)
1923 {
1924 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1925 return false;
1926 }
1927 }
1928 break;
1929 case GL_DEPTH24_STENCIL8_OES:
1930 if (!(context->getExtensions().depthTextureANGLE ||
1931 ((context->getExtensions().packedDepthStencilOES ||
1932 context->getExtensions().depthTextureCubeMapOES) &&
1933 context->getExtensions().textureStorage)))
1934 {
1935 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1936 return false;
1937 }
1938
1939 switch (target)
1940 {
1941 case TextureType::_2D:
1942 break;
1943 case TextureType::CubeMap:
1944 if (!context->getExtensions().depthTextureCubeMapOES)
1945 {
1946 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1947 return false;
1948 }
1949 break;
1950 default:
1951 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1952 return false;
1953 }
1954
1955 if (!context->getExtensions().packedDepthStencilOES &&
1956 !context->getExtensions().depthTextureCubeMapOES)
1957 {
1958 // ANGLE_depth_texture only supports 1-level textures
1959 if (levels != 1)
1960 {
1961 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1962 return false;
1963 }
1964 }
1965 break;
1966
1967 default:
1968 break;
1969 }
1970
1971 Texture *texture = context->getTextureByType(target);
1972 if (!texture || texture->id().value == 0)
1973 {
1974 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
1975 return false;
1976 }
1977
1978 if (texture->getImmutableFormat())
1979 {
1980 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
1981 return false;
1982 }
1983
1984 return true;
1985 }
1986
ValidateDiscardFramebufferEXT(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments)1987 bool ValidateDiscardFramebufferEXT(const Context *context,
1988 GLenum target,
1989 GLsizei numAttachments,
1990 const GLenum *attachments)
1991 {
1992 if (!context->getExtensions().discardFramebuffer)
1993 {
1994 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1995 return false;
1996 }
1997
1998 bool defaultFramebuffer = false;
1999
2000 switch (target)
2001 {
2002 case GL_FRAMEBUFFER:
2003 defaultFramebuffer =
2004 (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault());
2005 break;
2006 default:
2007 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
2008 return false;
2009 }
2010
2011 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
2012 defaultFramebuffer);
2013 }
2014
ValidateBindVertexArrayOES(const Context * context,VertexArrayID array)2015 bool ValidateBindVertexArrayOES(const Context *context, VertexArrayID array)
2016 {
2017 if (!context->getExtensions().vertexArrayObjectOES)
2018 {
2019 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2020 return false;
2021 }
2022
2023 return ValidateBindVertexArrayBase(context, array);
2024 }
2025
ValidateDeleteVertexArraysOES(const Context * context,GLsizei n,const VertexArrayID * arrays)2026 bool ValidateDeleteVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays)
2027 {
2028 if (!context->getExtensions().vertexArrayObjectOES)
2029 {
2030 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2031 return false;
2032 }
2033
2034 return ValidateGenOrDelete(context, n);
2035 }
2036
ValidateGenVertexArraysOES(const Context * context,GLsizei n,const VertexArrayID * arrays)2037 bool ValidateGenVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays)
2038 {
2039 if (!context->getExtensions().vertexArrayObjectOES)
2040 {
2041 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2042 return false;
2043 }
2044
2045 return ValidateGenOrDelete(context, n);
2046 }
2047
ValidateIsVertexArrayOES(const Context * context,VertexArrayID array)2048 bool ValidateIsVertexArrayOES(const Context *context, VertexArrayID array)
2049 {
2050 if (!context->getExtensions().vertexArrayObjectOES)
2051 {
2052 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2053 return false;
2054 }
2055
2056 return true;
2057 }
2058
ValidateProgramBinaryOES(const Context * context,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)2059 bool ValidateProgramBinaryOES(const Context *context,
2060 ShaderProgramID program,
2061 GLenum binaryFormat,
2062 const void *binary,
2063 GLint length)
2064 {
2065 if (!context->getExtensions().getProgramBinaryOES)
2066 {
2067 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2068 return false;
2069 }
2070
2071 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
2072 }
2073
ValidateGetProgramBinaryOES(const Context * context,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)2074 bool ValidateGetProgramBinaryOES(const Context *context,
2075 ShaderProgramID program,
2076 GLsizei bufSize,
2077 const GLsizei *length,
2078 const GLenum *binaryFormat,
2079 const void *binary)
2080 {
2081 if (!context->getExtensions().getProgramBinaryOES)
2082 {
2083 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2084 return false;
2085 }
2086
2087 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
2088 }
2089
ValidDebugSource(GLenum source,bool mustBeThirdPartyOrApplication)2090 static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
2091 {
2092 switch (source)
2093 {
2094 case GL_DEBUG_SOURCE_API:
2095 case GL_DEBUG_SOURCE_SHADER_COMPILER:
2096 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
2097 case GL_DEBUG_SOURCE_OTHER:
2098 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
2099 return !mustBeThirdPartyOrApplication;
2100
2101 case GL_DEBUG_SOURCE_THIRD_PARTY:
2102 case GL_DEBUG_SOURCE_APPLICATION:
2103 return true;
2104
2105 default:
2106 return false;
2107 }
2108 }
2109
ValidDebugType(GLenum type)2110 static bool ValidDebugType(GLenum type)
2111 {
2112 switch (type)
2113 {
2114 case GL_DEBUG_TYPE_ERROR:
2115 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
2116 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
2117 case GL_DEBUG_TYPE_PERFORMANCE:
2118 case GL_DEBUG_TYPE_PORTABILITY:
2119 case GL_DEBUG_TYPE_OTHER:
2120 case GL_DEBUG_TYPE_MARKER:
2121 case GL_DEBUG_TYPE_PUSH_GROUP:
2122 case GL_DEBUG_TYPE_POP_GROUP:
2123 return true;
2124
2125 default:
2126 return false;
2127 }
2128 }
2129
ValidDebugSeverity(GLenum severity)2130 static bool ValidDebugSeverity(GLenum severity)
2131 {
2132 switch (severity)
2133 {
2134 case GL_DEBUG_SEVERITY_HIGH:
2135 case GL_DEBUG_SEVERITY_MEDIUM:
2136 case GL_DEBUG_SEVERITY_LOW:
2137 case GL_DEBUG_SEVERITY_NOTIFICATION:
2138 return true;
2139
2140 default:
2141 return false;
2142 }
2143 }
2144
ValidateDebugMessageControlKHR(const Context * context,GLenum source,GLenum type,GLenum severity,GLsizei count,const GLuint * ids,GLboolean enabled)2145 bool ValidateDebugMessageControlKHR(const Context *context,
2146 GLenum source,
2147 GLenum type,
2148 GLenum severity,
2149 GLsizei count,
2150 const GLuint *ids,
2151 GLboolean enabled)
2152 {
2153 if (!context->getExtensions().debug)
2154 {
2155 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2156 return false;
2157 }
2158
2159 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
2160 {
2161 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2162 return false;
2163 }
2164
2165 if (!ValidDebugType(type) && type != GL_DONT_CARE)
2166 {
2167 context->validationError(GL_INVALID_ENUM, kInvalidDebugType);
2168 return false;
2169 }
2170
2171 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
2172 {
2173 context->validationError(GL_INVALID_ENUM, kInvalidDebugSeverity);
2174 return false;
2175 }
2176
2177 if (count > 0)
2178 {
2179 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
2180 {
2181 context->validationError(GL_INVALID_OPERATION, kInvalidDebugSourceType);
2182 return false;
2183 }
2184
2185 if (severity != GL_DONT_CARE)
2186 {
2187 context->validationError(GL_INVALID_OPERATION, kInvalidDebugSeverity);
2188 return false;
2189 }
2190 }
2191
2192 return true;
2193 }
2194
ValidateDebugMessageInsertKHR(const Context * context,GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * buf)2195 bool ValidateDebugMessageInsertKHR(const Context *context,
2196 GLenum source,
2197 GLenum type,
2198 GLuint id,
2199 GLenum severity,
2200 GLsizei length,
2201 const GLchar *buf)
2202 {
2203 if (!context->getExtensions().debug)
2204 {
2205 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2206 return false;
2207 }
2208
2209 if (!context->getState().getDebug().isOutputEnabled())
2210 {
2211 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2212 // not generate an error.
2213 return false;
2214 }
2215
2216 if (!ValidDebugSeverity(severity))
2217 {
2218 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2219 return false;
2220 }
2221
2222 if (!ValidDebugType(type))
2223 {
2224 context->validationError(GL_INVALID_ENUM, kInvalidDebugType);
2225 return false;
2226 }
2227
2228 if (!ValidDebugSource(source, true))
2229 {
2230 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2231 return false;
2232 }
2233
2234 size_t messageLength = (length < 0) ? strlen(buf) : length;
2235 if (messageLength > context->getExtensions().maxDebugMessageLength)
2236 {
2237 context->validationError(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
2238 return false;
2239 }
2240
2241 return true;
2242 }
2243
ValidateDebugMessageCallbackKHR(const Context * context,GLDEBUGPROCKHR callback,const void * userParam)2244 bool ValidateDebugMessageCallbackKHR(const Context *context,
2245 GLDEBUGPROCKHR callback,
2246 const void *userParam)
2247 {
2248 if (!context->getExtensions().debug)
2249 {
2250 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2251 return false;
2252 }
2253
2254 return true;
2255 }
2256
ValidateGetDebugMessageLogKHR(const Context * context,GLuint count,GLsizei bufSize,const GLenum * sources,const GLenum * types,const GLuint * ids,const GLenum * severities,const GLsizei * lengths,const GLchar * messageLog)2257 bool ValidateGetDebugMessageLogKHR(const Context *context,
2258 GLuint count,
2259 GLsizei bufSize,
2260 const GLenum *sources,
2261 const GLenum *types,
2262 const GLuint *ids,
2263 const GLenum *severities,
2264 const GLsizei *lengths,
2265 const GLchar *messageLog)
2266 {
2267 if (!context->getExtensions().debug)
2268 {
2269 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2270 return false;
2271 }
2272
2273 if (bufSize < 0 && messageLog != nullptr)
2274 {
2275 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2276 return false;
2277 }
2278
2279 return true;
2280 }
2281
ValidatePushDebugGroupKHR(const Context * context,GLenum source,GLuint id,GLsizei length,const GLchar * message)2282 bool ValidatePushDebugGroupKHR(const Context *context,
2283 GLenum source,
2284 GLuint id,
2285 GLsizei length,
2286 const GLchar *message)
2287 {
2288 if (!context->getExtensions().debug)
2289 {
2290 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2291 return false;
2292 }
2293
2294 if (!ValidDebugSource(source, true))
2295 {
2296 context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2297 return false;
2298 }
2299
2300 size_t messageLength = (length < 0) ? strlen(message) : length;
2301 if (messageLength > context->getExtensions().maxDebugMessageLength)
2302 {
2303 context->validationError(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
2304 return false;
2305 }
2306
2307 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
2308 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2309 {
2310 context->validationError(GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth);
2311 return false;
2312 }
2313
2314 return true;
2315 }
2316
ValidatePopDebugGroupKHR(const Context * context)2317 bool ValidatePopDebugGroupKHR(const Context *context)
2318 {
2319 if (!context->getExtensions().debug)
2320 {
2321 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2322 return false;
2323 }
2324
2325 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
2326 if (currentStackSize <= 1)
2327 {
2328 context->validationError(GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup);
2329 return false;
2330 }
2331
2332 return true;
2333 }
2334
ValidateObjectIdentifierAndName(const Context * context,GLenum identifier,GLuint name)2335 static bool ValidateObjectIdentifierAndName(const Context *context, GLenum identifier, GLuint name)
2336 {
2337 switch (identifier)
2338 {
2339 case GL_BUFFER:
2340 if (context->getBuffer({name}) == nullptr)
2341 {
2342 context->validationError(GL_INVALID_VALUE, kInvalidBufferName);
2343 return false;
2344 }
2345 return true;
2346
2347 case GL_SHADER:
2348 if (context->getShader({name}) == nullptr)
2349 {
2350 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
2351 return false;
2352 }
2353 return true;
2354
2355 case GL_PROGRAM:
2356 if (context->getProgramNoResolveLink({name}) == nullptr)
2357 {
2358 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
2359 return false;
2360 }
2361 return true;
2362
2363 case GL_VERTEX_ARRAY:
2364 if (context->getVertexArray({name}) == nullptr)
2365 {
2366 context->validationError(GL_INVALID_VALUE, kInvalidVertexArrayName);
2367 return false;
2368 }
2369 return true;
2370
2371 case GL_QUERY:
2372 if (context->getQuery({name}) == nullptr)
2373 {
2374 context->validationError(GL_INVALID_VALUE, kInvalidQueryName);
2375 return false;
2376 }
2377 return true;
2378
2379 case GL_TRANSFORM_FEEDBACK:
2380 if (context->getTransformFeedback({name}) == nullptr)
2381 {
2382 context->validationError(GL_INVALID_VALUE, kInvalidTransformFeedbackName);
2383 return false;
2384 }
2385 return true;
2386
2387 case GL_SAMPLER:
2388 if (context->getSampler({name}) == nullptr)
2389 {
2390 context->validationError(GL_INVALID_VALUE, kInvalidSamplerName);
2391 return false;
2392 }
2393 return true;
2394
2395 case GL_TEXTURE:
2396 if (context->getTexture({name}) == nullptr)
2397 {
2398 context->validationError(GL_INVALID_VALUE, kInvalidTextureName);
2399 return false;
2400 }
2401 return true;
2402
2403 case GL_RENDERBUFFER:
2404 if (!context->isRenderbuffer({name}))
2405 {
2406 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferName);
2407 return false;
2408 }
2409 return true;
2410
2411 case GL_FRAMEBUFFER:
2412 if (context->getFramebuffer({name}) == nullptr)
2413 {
2414 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferName);
2415 return false;
2416 }
2417 return true;
2418
2419 case GL_PROGRAM_PIPELINE:
2420 if (context->getProgramPipeline({name}) == nullptr)
2421 {
2422 context->validationError(GL_INVALID_VALUE, kInvalidProgramPipelineName);
2423 return false;
2424 }
2425 return true;
2426
2427 default:
2428 context->validationError(GL_INVALID_ENUM, kInvalidIndentifier);
2429 return false;
2430 }
2431 }
2432
ValidateLabelLength(const Context * context,GLsizei length,const GLchar * label)2433 static bool ValidateLabelLength(const Context *context, GLsizei length, const GLchar *label)
2434 {
2435 size_t labelLength = 0;
2436
2437 if (length < 0)
2438 {
2439 if (label != nullptr)
2440 {
2441 labelLength = strlen(label);
2442 }
2443 }
2444 else
2445 {
2446 labelLength = static_cast<size_t>(length);
2447 }
2448
2449 if (labelLength > context->getExtensions().maxLabelLength)
2450 {
2451 context->validationError(GL_INVALID_VALUE, kExceedsMaxLabelLength);
2452 return false;
2453 }
2454
2455 return true;
2456 }
2457
ValidateObjectLabelKHR(const Context * context,GLenum identifier,GLuint name,GLsizei length,const GLchar * label)2458 bool ValidateObjectLabelKHR(const Context *context,
2459 GLenum identifier,
2460 GLuint name,
2461 GLsizei length,
2462 const GLchar *label)
2463 {
2464 if (!context->getExtensions().debug)
2465 {
2466 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2467 return false;
2468 }
2469
2470 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2471 {
2472 return false;
2473 }
2474
2475 if (!ValidateLabelLength(context, length, label))
2476 {
2477 return false;
2478 }
2479
2480 return true;
2481 }
2482
ValidateGetObjectLabelKHR(const Context * context,GLenum identifier,GLuint name,GLsizei bufSize,const GLsizei * length,const GLchar * label)2483 bool ValidateGetObjectLabelKHR(const Context *context,
2484 GLenum identifier,
2485 GLuint name,
2486 GLsizei bufSize,
2487 const GLsizei *length,
2488 const GLchar *label)
2489 {
2490 if (!context->getExtensions().debug)
2491 {
2492 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2493 return false;
2494 }
2495
2496 if (bufSize < 0)
2497 {
2498 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2499 return false;
2500 }
2501
2502 if (!ValidateObjectIdentifierAndName(context, identifier, name))
2503 {
2504 return false;
2505 }
2506
2507 return true;
2508 }
2509
ValidateObjectPtrName(const Context * context,const void * ptr)2510 static bool ValidateObjectPtrName(const Context *context, const void *ptr)
2511 {
2512 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2513 {
2514 context->validationError(GL_INVALID_VALUE, kInvalidSyncPointer);
2515 return false;
2516 }
2517
2518 return true;
2519 }
2520
ValidateObjectPtrLabelKHR(const Context * context,const void * ptr,GLsizei length,const GLchar * label)2521 bool ValidateObjectPtrLabelKHR(const Context *context,
2522 const void *ptr,
2523 GLsizei length,
2524 const GLchar *label)
2525 {
2526 if (!context->getExtensions().debug)
2527 {
2528 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2529 return false;
2530 }
2531
2532 if (!ValidateObjectPtrName(context, ptr))
2533 {
2534 return false;
2535 }
2536
2537 if (!ValidateLabelLength(context, length, label))
2538 {
2539 return false;
2540 }
2541
2542 return true;
2543 }
2544
ValidateGetObjectPtrLabelKHR(const Context * context,const void * ptr,GLsizei bufSize,const GLsizei * length,const GLchar * label)2545 bool ValidateGetObjectPtrLabelKHR(const Context *context,
2546 const void *ptr,
2547 GLsizei bufSize,
2548 const GLsizei *length,
2549 const GLchar *label)
2550 {
2551 if (!context->getExtensions().debug)
2552 {
2553 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2554 return false;
2555 }
2556
2557 if (bufSize < 0)
2558 {
2559 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2560 return false;
2561 }
2562
2563 if (!ValidateObjectPtrName(context, ptr))
2564 {
2565 return false;
2566 }
2567
2568 return true;
2569 }
2570
ValidateGetPointervKHR(const Context * context,GLenum pname,void * const * params)2571 bool ValidateGetPointervKHR(const Context *context, GLenum pname, void *const *params)
2572 {
2573 if (!context->getExtensions().debug)
2574 {
2575 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2576 return false;
2577 }
2578
2579 // TODO: represent this in Context::getQueryParameterInfo.
2580 switch (pname)
2581 {
2582 case GL_DEBUG_CALLBACK_FUNCTION:
2583 case GL_DEBUG_CALLBACK_USER_PARAM:
2584 break;
2585
2586 default:
2587 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2588 return false;
2589 }
2590
2591 return true;
2592 }
2593
ValidateGetPointervRobustANGLERobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)2594 bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context,
2595 GLenum pname,
2596 GLsizei bufSize,
2597 const GLsizei *length,
2598 void *const *params)
2599 {
2600 UNIMPLEMENTED();
2601 return false;
2602 }
2603
ValidateBlitFramebufferANGLE(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2604 bool ValidateBlitFramebufferANGLE(const Context *context,
2605 GLint srcX0,
2606 GLint srcY0,
2607 GLint srcX1,
2608 GLint srcY1,
2609 GLint dstX0,
2610 GLint dstY0,
2611 GLint dstX1,
2612 GLint dstY1,
2613 GLbitfield mask,
2614 GLenum filter)
2615 {
2616 if (!context->getExtensions().framebufferBlitANGLE)
2617 {
2618 context->validationError(GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
2619 return false;
2620 }
2621
2622 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2623 {
2624 // TODO(jmadill): Determine if this should be available on other implementations.
2625 context->validationError(GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip);
2626 return false;
2627 }
2628
2629 if (filter == GL_LINEAR)
2630 {
2631 context->validationError(GL_INVALID_ENUM, kBlitExtensionLinear);
2632 return false;
2633 }
2634
2635 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
2636 Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
2637
2638 if (mask & GL_COLOR_BUFFER_BIT)
2639 {
2640 const FramebufferAttachment *readColorAttachment =
2641 readFramebuffer->getReadColorAttachment();
2642 const FramebufferAttachment *drawColorAttachment =
2643 drawFramebuffer->getFirstColorAttachment();
2644
2645 if (readColorAttachment && drawColorAttachment)
2646 {
2647 if (!(readColorAttachment->type() == GL_TEXTURE &&
2648 (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D ||
2649 readColorAttachment->getTextureImageIndex().getType() ==
2650 TextureType::Rectangle)) &&
2651 readColorAttachment->type() != GL_RENDERBUFFER &&
2652 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2653 {
2654 context->validationError(GL_INVALID_OPERATION,
2655 kBlitExtensionFromInvalidAttachmentType);
2656 return false;
2657 }
2658
2659 for (size_t drawbufferIdx = 0;
2660 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
2661 {
2662 const FramebufferAttachment *attachment =
2663 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2664 if (attachment)
2665 {
2666 if (!(attachment->type() == GL_TEXTURE &&
2667 (attachment->getTextureImageIndex().getType() == TextureType::_2D ||
2668 attachment->getTextureImageIndex().getType() ==
2669 TextureType::Rectangle)) &&
2670 attachment->type() != GL_RENDERBUFFER &&
2671 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2672 {
2673 context->validationError(GL_INVALID_OPERATION,
2674 kBlitExtensionToInvalidAttachmentType);
2675 return false;
2676 }
2677
2678 // Return an error if the destination formats do not match
2679 if (!Format::EquivalentForBlit(attachment->getFormat(),
2680 readColorAttachment->getFormat()))
2681 {
2682 context->validationError(GL_INVALID_OPERATION,
2683 kBlitExtensionFormatMismatch);
2684 return false;
2685 }
2686 }
2687 }
2688
2689 GLint samples = readFramebuffer->getSamples(context);
2690 if (samples != 0 &&
2691 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2692 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2693 {
2694 context->validationError(GL_INVALID_OPERATION,
2695 kBlitExtensionMultisampledWholeBufferBlit);
2696 return false;
2697 }
2698 }
2699 }
2700
2701 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2702 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2703 for (size_t i = 0; i < 2; i++)
2704 {
2705 if (mask & masks[i])
2706 {
2707 const FramebufferAttachment *readBuffer =
2708 readFramebuffer->getAttachment(context, attachments[i]);
2709 const FramebufferAttachment *drawBuffer =
2710 drawFramebuffer->getAttachment(context, attachments[i]);
2711
2712 if (readBuffer && drawBuffer)
2713 {
2714 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2715 dstX0, dstY0, dstX1, dstY1))
2716 {
2717 // only whole-buffer copies are permitted
2718 context->validationError(GL_INVALID_OPERATION,
2719 kBlitExtensionDepthStencilWholeBufferBlit);
2720 return false;
2721 }
2722
2723 if (readBuffer->getResourceSamples() != 0 || drawBuffer->getResourceSamples() != 0)
2724 {
2725 context->validationError(GL_INVALID_OPERATION,
2726 kBlitExtensionMultisampledDepthOrStencil);
2727 return false;
2728 }
2729 }
2730 }
2731 }
2732
2733 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2734 dstX1, dstY1, mask, filter);
2735 }
2736
ValidateBlitFramebufferNV(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2737 bool ValidateBlitFramebufferNV(const Context *context,
2738 GLint srcX0,
2739 GLint srcY0,
2740 GLint srcX1,
2741 GLint srcY1,
2742 GLint dstX0,
2743 GLint dstY0,
2744 GLint dstX1,
2745 GLint dstY1,
2746 GLbitfield mask,
2747 GLenum filter)
2748 {
2749 if (!context->getExtensions().framebufferBlitANGLE)
2750 {
2751 context->validationError(GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
2752 return false;
2753 }
2754
2755 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2756 dstX1, dstY1, mask, filter);
2757 }
2758
ValidateClear(const Context * context,GLbitfield mask)2759 bool ValidateClear(const Context *context, GLbitfield mask)
2760 {
2761 Framebuffer *fbo = context->getState().getDrawFramebuffer();
2762 const Extensions &extensions = context->getExtensions();
2763
2764 if (!ValidateFramebufferComplete(context, fbo))
2765 {
2766 return false;
2767 }
2768
2769 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2770 {
2771 context->validationError(GL_INVALID_VALUE, kInvalidClearMask);
2772 return false;
2773 }
2774
2775 if (extensions.webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2776 {
2777 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2778 GL_SIGNED_NORMALIZED};
2779
2780 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
2781 drawBufferIdx++)
2782 {
2783 if (!ValidateWebGLFramebufferAttachmentClearType(
2784 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2785 {
2786 return false;
2787 }
2788 }
2789 }
2790
2791 if ((extensions.multiview || extensions.multiview2) && extensions.disjointTimerQuery)
2792 {
2793 const State &state = context->getState();
2794 Framebuffer *framebuffer = state.getDrawFramebuffer();
2795 if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed))
2796 {
2797 context->validationError(GL_INVALID_OPERATION, kMultiviewTimerQuery);
2798 return false;
2799 }
2800 }
2801
2802 return true;
2803 }
2804
ValidateDrawBuffersEXT(const Context * context,GLsizei n,const GLenum * bufs)2805 bool ValidateDrawBuffersEXT(const Context *context, GLsizei n, const GLenum *bufs)
2806 {
2807 if (!context->getExtensions().drawBuffers)
2808 {
2809 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2810 return false;
2811 }
2812
2813 return ValidateDrawBuffersBase(context, n, bufs);
2814 }
2815
ValidateTexImage2D(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * pixels)2816 bool ValidateTexImage2D(const Context *context,
2817 TextureTarget target,
2818 GLint level,
2819 GLint internalformat,
2820 GLsizei width,
2821 GLsizei height,
2822 GLint border,
2823 GLenum format,
2824 GLenum type,
2825 const void *pixels)
2826 {
2827 if (context->getClientMajorVersion() < 3)
2828 {
2829 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2830 0, 0, width, height, border, format, type, -1, pixels);
2831 }
2832
2833 ASSERT(context->getClientMajorVersion() >= 3);
2834 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2835 0, 0, width, height, 1, border, format, type, -1,
2836 pixels);
2837 }
2838
ValidateTexImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2839 bool ValidateTexImage2DRobustANGLE(const Context *context,
2840 TextureTarget target,
2841 GLint level,
2842 GLint internalformat,
2843 GLsizei width,
2844 GLsizei height,
2845 GLint border,
2846 GLenum format,
2847 GLenum type,
2848 GLsizei bufSize,
2849 const void *pixels)
2850 {
2851 if (!ValidateRobustEntryPoint(context, bufSize))
2852 {
2853 return false;
2854 }
2855
2856 if (context->getClientMajorVersion() < 3)
2857 {
2858 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2859 0, 0, width, height, border, format, type, bufSize,
2860 pixels);
2861 }
2862
2863 ASSERT(context->getClientMajorVersion() >= 3);
2864 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2865 0, 0, width, height, 1, border, format, type, bufSize,
2866 pixels);
2867 }
2868
ValidateTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)2869 bool ValidateTexSubImage2D(const Context *context,
2870 TextureTarget target,
2871 GLint level,
2872 GLint xoffset,
2873 GLint yoffset,
2874 GLsizei width,
2875 GLsizei height,
2876 GLenum format,
2877 GLenum type,
2878 const void *pixels)
2879 {
2880
2881 if (context->getClientMajorVersion() < 3)
2882 {
2883 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2884 yoffset, width, height, 0, format, type, -1, pixels);
2885 }
2886
2887 ASSERT(context->getClientMajorVersion() >= 3);
2888 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2889 yoffset, 0, width, height, 1, 0, format, type, -1,
2890 pixels);
2891 }
2892
ValidateTexSubImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2893 bool ValidateTexSubImage2DRobustANGLE(const Context *context,
2894 TextureTarget target,
2895 GLint level,
2896 GLint xoffset,
2897 GLint yoffset,
2898 GLsizei width,
2899 GLsizei height,
2900 GLenum format,
2901 GLenum type,
2902 GLsizei bufSize,
2903 const void *pixels)
2904 {
2905 if (!ValidateRobustEntryPoint(context, bufSize))
2906 {
2907 return false;
2908 }
2909
2910 if (context->getClientMajorVersion() < 3)
2911 {
2912 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2913 yoffset, width, height, 0, format, type, bufSize,
2914 pixels);
2915 }
2916
2917 ASSERT(context->getClientMajorVersion() >= 3);
2918 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2919 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2920 pixels);
2921 }
2922
ValidateTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)2923 bool ValidateTexSubImage3DOES(const Context *context,
2924 TextureTarget target,
2925 GLint level,
2926 GLint xoffset,
2927 GLint yoffset,
2928 GLint zoffset,
2929 GLsizei width,
2930 GLsizei height,
2931 GLsizei depth,
2932 GLenum format,
2933 GLenum type,
2934 const void *pixels)
2935 {
2936 return ValidateTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width, height,
2937 depth, format, type, pixels);
2938 }
2939
ValidateCompressedTexImage2D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const void * data)2940 bool ValidateCompressedTexImage2D(const Context *context,
2941 TextureTarget target,
2942 GLint level,
2943 GLenum internalformat,
2944 GLsizei width,
2945 GLsizei height,
2946 GLint border,
2947 GLsizei imageSize,
2948 const void *data)
2949 {
2950 if (context->getClientMajorVersion() < 3)
2951 {
2952 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
2953 0, width, height, border, GL_NONE, GL_NONE, -1, data))
2954 {
2955 return false;
2956 }
2957 }
2958 else
2959 {
2960 ASSERT(context->getClientMajorVersion() >= 3);
2961 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
2962 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
2963 data))
2964 {
2965 return false;
2966 }
2967 }
2968
2969 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
2970
2971 GLuint blockSize = 0;
2972 if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
2973 {
2974 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
2975 return false;
2976 }
2977
2978 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2979 {
2980 context->validationError(GL_INVALID_VALUE, kCompressedTextureDimensionsMustMatchData);
2981 return false;
2982 }
2983
2984 if (target == TextureTarget::Rectangle)
2985 {
2986 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
2987 return false;
2988 }
2989
2990 return true;
2991 }
2992
ValidateCompressedTexImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)2993 bool ValidateCompressedTexImage2DRobustANGLE(const Context *context,
2994 TextureTarget target,
2995 GLint level,
2996 GLenum internalformat,
2997 GLsizei width,
2998 GLsizei height,
2999 GLint border,
3000 GLsizei imageSize,
3001 GLsizei dataSize,
3002 const void *data)
3003 {
3004 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
3005 {
3006 return false;
3007 }
3008
3009 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
3010 border, imageSize, data);
3011 }
3012
ValidateCompressedTexImage3DOES(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)3013 bool ValidateCompressedTexImage3DOES(const Context *context,
3014 TextureTarget target,
3015 GLint level,
3016 GLenum internalformat,
3017 GLsizei width,
3018 GLsizei height,
3019 GLsizei depth,
3020 GLint border,
3021 GLsizei imageSize,
3022 const void *data)
3023 {
3024 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
3025 depth, border, imageSize, data);
3026 }
3027
ValidateCompressedTexSubImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)3028 bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context,
3029 TextureTarget target,
3030 GLint level,
3031 GLint xoffset,
3032 GLint yoffset,
3033 GLsizei width,
3034 GLsizei height,
3035 GLenum format,
3036 GLsizei imageSize,
3037 GLsizei dataSize,
3038 const void *data)
3039 {
3040 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
3041 {
3042 return false;
3043 }
3044
3045 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
3046 format, imageSize, data);
3047 }
3048
ValidateCompressedTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const void * data)3049 bool ValidateCompressedTexSubImage2D(const Context *context,
3050 TextureTarget target,
3051 GLint level,
3052 GLint xoffset,
3053 GLint yoffset,
3054 GLsizei width,
3055 GLsizei height,
3056 GLenum format,
3057 GLsizei imageSize,
3058 const void *data)
3059 {
3060 if (context->getClientMajorVersion() < 3)
3061 {
3062 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
3063 yoffset, width, height, 0, format, GL_NONE, -1, data))
3064 {
3065 return false;
3066 }
3067 }
3068 else
3069 {
3070 ASSERT(context->getClientMajorVersion() >= 3);
3071 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
3072 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
3073 data))
3074 {
3075 return false;
3076 }
3077 }
3078
3079 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
3080 GLuint blockSize = 0;
3081 if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
3082 {
3083 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
3084 return false;
3085 }
3086
3087 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
3088 {
3089 context->validationError(GL_INVALID_VALUE, kInvalidCompressedImageSize);
3090 return false;
3091 }
3092
3093 return true;
3094 }
3095
ValidateCompressedTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)3096 bool ValidateCompressedTexSubImage3DOES(const Context *context,
3097 TextureTarget target,
3098 GLint level,
3099 GLint xoffset,
3100 GLint yoffset,
3101 GLint zoffset,
3102 GLsizei width,
3103 GLsizei height,
3104 GLsizei depth,
3105 GLenum format,
3106 GLsizei imageSize,
3107 const void *data)
3108 {
3109 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
3110 height, depth, format, imageSize, data);
3111 }
3112
ValidateGetBufferPointervOES(const Context * context,BufferBinding target,GLenum pname,void * const * params)3113 bool ValidateGetBufferPointervOES(const Context *context,
3114 BufferBinding target,
3115 GLenum pname,
3116 void *const *params)
3117 {
3118 if (!context->getExtensions().mapBufferOES)
3119 {
3120 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3121 return false;
3122 }
3123
3124 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
3125 }
3126
ValidateMapBufferOES(const Context * context,BufferBinding target,GLenum access)3127 bool ValidateMapBufferOES(const Context *context, BufferBinding target, GLenum access)
3128 {
3129 if (!context->getExtensions().mapBufferOES)
3130 {
3131 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3132 return false;
3133 }
3134
3135 if (!context->isValidBufferBinding(target))
3136 {
3137 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3138 return false;
3139 }
3140
3141 Buffer *buffer = context->getState().getTargetBuffer(target);
3142
3143 if (buffer == nullptr)
3144 {
3145 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
3146 return false;
3147 }
3148
3149 if (access != GL_WRITE_ONLY_OES)
3150 {
3151 context->validationError(GL_INVALID_ENUM, kInvalidAccessBits);
3152 return false;
3153 }
3154
3155 // Though there is no explicit mention of an interaction between GL_EXT_buffer_storage
3156 // and GL_OES_mapbuffer extension, allow it as long as the access type of glMapBufferOES
3157 // is compatible with the buffer's usage flags specified during glBufferStorageEXT
3158 if (buffer->isImmutable() && (buffer->getStorageExtUsageFlags() & GL_MAP_WRITE_BIT) == 0)
3159 {
3160 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
3161 return false;
3162 }
3163
3164 if (buffer->isMapped())
3165 {
3166 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
3167 return false;
3168 }
3169
3170 return ValidateMapBufferBase(context, target);
3171 }
3172
ValidateUnmapBufferOES(const Context * context,BufferBinding target)3173 bool ValidateUnmapBufferOES(const Context *context, BufferBinding target)
3174 {
3175 if (!context->getExtensions().mapBufferOES)
3176 {
3177 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3178 return false;
3179 }
3180
3181 return ValidateUnmapBufferBase(context, target);
3182 }
3183
ValidateMapBufferRangeEXT(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3184 bool ValidateMapBufferRangeEXT(const Context *context,
3185 BufferBinding target,
3186 GLintptr offset,
3187 GLsizeiptr length,
3188 GLbitfield access)
3189 {
3190 if (!context->getExtensions().mapBufferRange)
3191 {
3192 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3193 return false;
3194 }
3195
3196 return ValidateMapBufferRangeBase(context, target, offset, length, access);
3197 }
3198
ValidateMapBufferBase(const Context * context,BufferBinding target)3199 bool ValidateMapBufferBase(const Context *context, BufferBinding target)
3200 {
3201 Buffer *buffer = context->getState().getTargetBuffer(target);
3202 ASSERT(buffer != nullptr);
3203
3204 // Check if this buffer is currently being used as a transform feedback output buffer
3205 if (context->getState().isTransformFeedbackActive())
3206 {
3207 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3208 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
3209 {
3210 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
3211 if (transformFeedbackBuffer.get() == buffer)
3212 {
3213 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3214 return false;
3215 }
3216 }
3217 }
3218
3219 if (context->getExtensions().webglCompatibility &&
3220 buffer->isBoundForTransformFeedbackAndOtherUse())
3221 {
3222 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3223 return false;
3224 }
3225
3226 return true;
3227 }
3228
ValidateFlushMappedBufferRangeEXT(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)3229 bool ValidateFlushMappedBufferRangeEXT(const Context *context,
3230 BufferBinding target,
3231 GLintptr offset,
3232 GLsizeiptr length)
3233 {
3234 if (!context->getExtensions().mapBufferRange)
3235 {
3236 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3237 return false;
3238 }
3239
3240 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
3241 }
3242
ValidateBindUniformLocationCHROMIUM(const Context * context,ShaderProgramID program,UniformLocation location,const GLchar * name)3243 bool ValidateBindUniformLocationCHROMIUM(const Context *context,
3244 ShaderProgramID program,
3245 UniformLocation location,
3246 const GLchar *name)
3247 {
3248 if (!context->getExtensions().bindUniformLocation)
3249 {
3250 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3251 return false;
3252 }
3253
3254 Program *programObject = GetValidProgram(context, program);
3255 if (!programObject)
3256 {
3257 return false;
3258 }
3259
3260 if (location.value < 0)
3261 {
3262 context->validationError(GL_INVALID_VALUE, kNegativeLocation);
3263 return false;
3264 }
3265
3266 const Caps &caps = context->getCaps();
3267 if (static_cast<long>(location.value) >=
3268 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3269 {
3270 context->validationError(GL_INVALID_VALUE, kInvalidBindUniformLocation);
3271 return false;
3272 }
3273
3274 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3275 // shader-related entry points
3276 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
3277 {
3278 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
3279 return false;
3280 }
3281
3282 if (strncmp(name, "gl_", 3) == 0)
3283 {
3284 context->validationError(GL_INVALID_VALUE, kNameBeginsWithGL);
3285 return false;
3286 }
3287
3288 return true;
3289 }
3290
ValidateCoverageModulationCHROMIUM(const Context * context,GLenum components)3291 bool ValidateCoverageModulationCHROMIUM(const Context *context, GLenum components)
3292 {
3293 if (!context->getExtensions().framebufferMixedSamples)
3294 {
3295 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3296 return false;
3297 }
3298 switch (components)
3299 {
3300 case GL_RGB:
3301 case GL_RGBA:
3302 case GL_ALPHA:
3303 case GL_NONE:
3304 break;
3305 default:
3306 context->validationError(GL_INVALID_ENUM, kInvalidCoverageComponents);
3307 return false;
3308 }
3309
3310 return true;
3311 }
3312
ValidateCopyTextureCHROMIUM(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint internalFormat,GLenum destType,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)3313 bool ValidateCopyTextureCHROMIUM(const Context *context,
3314 TextureID sourceId,
3315 GLint sourceLevel,
3316 TextureTarget destTarget,
3317 TextureID destId,
3318 GLint destLevel,
3319 GLint internalFormat,
3320 GLenum destType,
3321 GLboolean unpackFlipY,
3322 GLboolean unpackPremultiplyAlpha,
3323 GLboolean unpackUnmultiplyAlpha)
3324 {
3325 if (!context->getExtensions().copyTexture)
3326 {
3327 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3328 return false;
3329 }
3330
3331 const Texture *source = context->getTexture(sourceId);
3332 if (source == nullptr)
3333 {
3334 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3335 return false;
3336 }
3337
3338 if (!IsValidCopyTextureSourceTarget(context, source->getType()))
3339 {
3340 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3341 return false;
3342 }
3343
3344 TextureType sourceType = source->getType();
3345 ASSERT(sourceType != TextureType::CubeMap);
3346 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
3347
3348 if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
3349 {
3350 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
3351 return false;
3352 }
3353
3354 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3355 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3356 if (sourceWidth == 0 || sourceHeight == 0)
3357 {
3358 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3359 return false;
3360 }
3361
3362 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3363 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
3364 {
3365 context->validationError(GL_INVALID_OPERATION, kInvalidSourceTextureInternalFormat);
3366 return false;
3367 }
3368
3369 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3370 {
3371 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3372 return false;
3373 }
3374
3375 const Texture *dest = context->getTexture(destId);
3376 if (dest == nullptr)
3377 {
3378 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3379 return false;
3380 }
3381
3382 if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
3383 {
3384 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3385 return false;
3386 }
3387
3388 if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, sourceWidth,
3389 sourceHeight, false))
3390 {
3391 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3392 return false;
3393 }
3394
3395 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3396 {
3397 return false;
3398 }
3399
3400 if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight)
3401 {
3402 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
3403 return false;
3404 }
3405
3406 if (dest->getImmutableFormat())
3407 {
3408 context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
3409 return false;
3410 }
3411
3412 return true;
3413 }
3414
ValidateCopySubTextureCHROMIUM(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)3415 bool ValidateCopySubTextureCHROMIUM(const Context *context,
3416 TextureID sourceId,
3417 GLint sourceLevel,
3418 TextureTarget destTarget,
3419 TextureID destId,
3420 GLint destLevel,
3421 GLint xoffset,
3422 GLint yoffset,
3423 GLint x,
3424 GLint y,
3425 GLsizei width,
3426 GLsizei height,
3427 GLboolean unpackFlipY,
3428 GLboolean unpackPremultiplyAlpha,
3429 GLboolean unpackUnmultiplyAlpha)
3430 {
3431 if (!context->getExtensions().copyTexture)
3432 {
3433 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3434 return false;
3435 }
3436
3437 const Texture *source = context->getTexture(sourceId);
3438 if (source == nullptr)
3439 {
3440 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3441 return false;
3442 }
3443
3444 if (!IsValidCopyTextureSourceTarget(context, source->getType()))
3445 {
3446 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureType);
3447 return false;
3448 }
3449
3450 TextureType sourceType = source->getType();
3451 ASSERT(sourceType != TextureType::CubeMap);
3452 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
3453
3454 if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
3455 {
3456 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3457 return false;
3458 }
3459
3460 if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3461 source->getHeight(sourceTarget, sourceLevel) == 0)
3462 {
3463 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
3464 return false;
3465 }
3466
3467 if (x < 0 || y < 0)
3468 {
3469 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3470 return false;
3471 }
3472
3473 if (width < 0 || height < 0)
3474 {
3475 context->validationError(GL_INVALID_VALUE, kNegativeSize);
3476 return false;
3477 }
3478
3479 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3480 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
3481 {
3482 context->validationError(GL_INVALID_VALUE, kSourceTextureTooSmall);
3483 return false;
3484 }
3485
3486 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3487 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
3488 {
3489 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3490 return false;
3491 }
3492
3493 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3494 {
3495 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3496 return false;
3497 }
3498
3499 const Texture *dest = context->getTexture(destId);
3500 if (dest == nullptr)
3501 {
3502 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3503 return false;
3504 }
3505
3506 if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
3507 {
3508 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3509 return false;
3510 }
3511
3512 if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, width, height,
3513 true))
3514 {
3515 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3516 return false;
3517 }
3518
3519 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3520 {
3521 context->validationError(GL_INVALID_OPERATION, kDestinationLevelNotDefined);
3522 return false;
3523 }
3524
3525 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3526 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
3527 {
3528 context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
3529 return false;
3530 }
3531
3532 if (xoffset < 0 || yoffset < 0)
3533 {
3534 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3535 return false;
3536 }
3537
3538 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3539 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
3540 {
3541 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
3542 return false;
3543 }
3544
3545 return true;
3546 }
3547
ValidateCompressedCopyTextureCHROMIUM(const Context * context,TextureID sourceId,TextureID destId)3548 bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
3549 TextureID sourceId,
3550 TextureID destId)
3551 {
3552 if (!context->getExtensions().copyCompressedTexture)
3553 {
3554 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3555 return false;
3556 }
3557
3558 const Texture *source = context->getTexture(sourceId);
3559 if (source == nullptr)
3560 {
3561 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3562 return false;
3563 }
3564
3565 if (source->getType() != TextureType::_2D)
3566 {
3567 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureType);
3568 return false;
3569 }
3570
3571 if (source->getWidth(TextureTarget::_2D, 0) == 0 ||
3572 source->getHeight(TextureTarget::_2D, 0) == 0)
3573 {
3574 context->validationError(GL_INVALID_VALUE, kSourceTextureLevelZeroDefined);
3575 return false;
3576 }
3577
3578 const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0);
3579 if (!sourceFormat.info->compressed)
3580 {
3581 context->validationError(GL_INVALID_OPERATION, kSourceTextureMustBeCompressed);
3582 return false;
3583 }
3584
3585 const Texture *dest = context->getTexture(destId);
3586 if (dest == nullptr)
3587 {
3588 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3589 return false;
3590 }
3591
3592 if (dest->getType() != TextureType::_2D)
3593 {
3594 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3595 return false;
3596 }
3597
3598 if (dest->getImmutableFormat())
3599 {
3600 context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
3601 return false;
3602 }
3603
3604 return true;
3605 }
3606
ValidateCreateShader(const Context * context,ShaderType type)3607 bool ValidateCreateShader(const Context *context, ShaderType type)
3608 {
3609 switch (type)
3610 {
3611 case ShaderType::Vertex:
3612 case ShaderType::Fragment:
3613 break;
3614
3615 case ShaderType::Compute:
3616 if (context->getClientVersion() < ES_3_1)
3617 {
3618 context->validationError(GL_INVALID_ENUM, kES31Required);
3619 return false;
3620 }
3621 break;
3622
3623 case ShaderType::Geometry:
3624 if (!context->getExtensions().geometryShaderAny() &&
3625 context->getClientVersion() < ES_3_2)
3626 {
3627 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3628 return false;
3629 }
3630 break;
3631
3632 case ShaderType::TessControl:
3633 if (!context->getExtensions().tessellationShaderEXT &&
3634 context->getClientVersion() < ES_3_2)
3635 {
3636 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3637 return false;
3638 }
3639 break;
3640
3641 case ShaderType::TessEvaluation:
3642 if (!context->getExtensions().tessellationShaderEXT &&
3643 context->getClientVersion() < ES_3_2)
3644 {
3645 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3646 return false;
3647 }
3648 break;
3649
3650 default:
3651 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3652 return false;
3653 }
3654
3655 return true;
3656 }
3657
ValidateBufferData(const Context * context,BufferBinding target,GLsizeiptr size,const void * data,BufferUsage usage)3658 bool ValidateBufferData(const Context *context,
3659 BufferBinding target,
3660 GLsizeiptr size,
3661 const void *data,
3662 BufferUsage usage)
3663 {
3664 if (size < 0)
3665 {
3666 context->validationError(GL_INVALID_VALUE, kNegativeSize);
3667 return false;
3668 }
3669
3670 switch (usage)
3671 {
3672 case BufferUsage::StreamDraw:
3673 case BufferUsage::StaticDraw:
3674 case BufferUsage::DynamicDraw:
3675 break;
3676
3677 case BufferUsage::StreamRead:
3678 case BufferUsage::StaticRead:
3679 case BufferUsage::DynamicRead:
3680 case BufferUsage::StreamCopy:
3681 case BufferUsage::StaticCopy:
3682 case BufferUsage::DynamicCopy:
3683 if (context->getClientMajorVersion() < 3)
3684 {
3685 context->validationError(GL_INVALID_ENUM, kInvalidBufferUsage);
3686 return false;
3687 }
3688 break;
3689
3690 default:
3691 context->validationError(GL_INVALID_ENUM, kInvalidBufferUsage);
3692 return false;
3693 }
3694
3695 if (!context->isValidBufferBinding(target))
3696 {
3697 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3698 return false;
3699 }
3700
3701 Buffer *buffer = context->getState().getTargetBuffer(target);
3702
3703 if (!buffer)
3704 {
3705 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
3706 return false;
3707 }
3708
3709 if (context->getExtensions().webglCompatibility &&
3710 buffer->isBoundForTransformFeedbackAndOtherUse())
3711 {
3712 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3713 return false;
3714 }
3715
3716 if (buffer->isImmutable())
3717 {
3718 context->validationError(GL_INVALID_OPERATION, kBufferImmutable);
3719 return false;
3720 }
3721
3722 return true;
3723 }
3724
ValidateBufferSubData(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr size,const void * data)3725 bool ValidateBufferSubData(const Context *context,
3726 BufferBinding target,
3727 GLintptr offset,
3728 GLsizeiptr size,
3729 const void *data)
3730 {
3731 if (size < 0)
3732 {
3733 context->validationError(GL_INVALID_VALUE, kNegativeSize);
3734 return false;
3735 }
3736
3737 if (offset < 0)
3738 {
3739 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3740 return false;
3741 }
3742
3743 if (!context->isValidBufferBinding(target))
3744 {
3745 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3746 return false;
3747 }
3748
3749 Buffer *buffer = context->getState().getTargetBuffer(target);
3750
3751 if (!buffer)
3752 {
3753 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
3754 return false;
3755 }
3756
3757 if (buffer->isMapped())
3758 {
3759 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
3760 return false;
3761 }
3762
3763 if (context->getExtensions().webglCompatibility &&
3764 buffer->isBoundForTransformFeedbackAndOtherUse())
3765 {
3766 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3767 return false;
3768 }
3769
3770 if (buffer->isImmutable() &&
3771 (buffer->getStorageExtUsageFlags() & GL_DYNAMIC_STORAGE_BIT_EXT) == 0)
3772 {
3773 context->validationError(GL_INVALID_OPERATION, kBufferNotUpdatable);
3774 return false;
3775 }
3776
3777 // Check for possible overflow of size + offset
3778 angle::CheckedNumeric<size_t> checkedSize(size);
3779 checkedSize += offset;
3780 if (!checkedSize.IsValid())
3781 {
3782 context->validationError(GL_INVALID_VALUE, kParamOverflow);
3783 return false;
3784 }
3785
3786 if (size + offset > buffer->getSize())
3787 {
3788 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
3789 return false;
3790 }
3791
3792 return true;
3793 }
3794
ValidateRequestExtensionANGLE(const Context * context,const GLchar * name)3795 bool ValidateRequestExtensionANGLE(const Context *context, const GLchar *name)
3796 {
3797 if (!context->getExtensions().requestExtension)
3798 {
3799 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3800 return false;
3801 }
3802
3803 if (!context->isExtensionRequestable(name))
3804 {
3805 context->validationError(GL_INVALID_OPERATION, kExtensionNotRequestable);
3806 return false;
3807 }
3808
3809 return true;
3810 }
3811
ValidateDisableExtensionANGLE(const Context * context,const GLchar * name)3812 bool ValidateDisableExtensionANGLE(const Context *context, const GLchar *name)
3813 {
3814 if (!context->getExtensions().requestExtension)
3815 {
3816 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3817 return false;
3818 }
3819
3820 if (!context->isExtensionDisablable(name))
3821 {
3822 context->validationError(GL_INVALID_OPERATION, kExtensionNotDisablable);
3823 return false;
3824 }
3825
3826 return true;
3827 }
3828
ValidateActiveTexture(const Context * context,GLenum texture)3829 bool ValidateActiveTexture(const Context *context, GLenum texture)
3830 {
3831 if (context->getClientMajorVersion() < 2)
3832 {
3833 return ValidateMultitextureUnit(context, texture);
3834 }
3835
3836 if (texture < GL_TEXTURE0 ||
3837 texture >
3838 GL_TEXTURE0 + static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits) - 1)
3839 {
3840 context->validationError(GL_INVALID_ENUM, kInvalidCombinedImageUnit);
3841 return false;
3842 }
3843
3844 return true;
3845 }
3846
ValidateAttachShader(const Context * context,ShaderProgramID program,ShaderProgramID shader)3847 bool ValidateAttachShader(const Context *context, ShaderProgramID program, ShaderProgramID shader)
3848 {
3849 Program *programObject = GetValidProgram(context, program);
3850 if (!programObject)
3851 {
3852 return false;
3853 }
3854
3855 Shader *shaderObject = GetValidShader(context, shader);
3856 if (!shaderObject)
3857 {
3858 return false;
3859 }
3860
3861 if (programObject->getAttachedShader(shaderObject->getType()))
3862 {
3863 context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
3864 return false;
3865 }
3866
3867 return true;
3868 }
3869
ValidateBindAttribLocation(const Context * context,ShaderProgramID program,GLuint index,const GLchar * name)3870 bool ValidateBindAttribLocation(const Context *context,
3871 ShaderProgramID program,
3872 GLuint index,
3873 const GLchar *name)
3874 {
3875 if (index >= MAX_VERTEX_ATTRIBS)
3876 {
3877 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
3878 return false;
3879 }
3880
3881 if (strncmp(name, "gl_", 3) == 0)
3882 {
3883 context->validationError(GL_INVALID_OPERATION, kNameBeginsWithGL);
3884 return false;
3885 }
3886
3887 if (context->isWebGL())
3888 {
3889 const size_t length = strlen(name);
3890
3891 if (!IsValidESSLString(name, length))
3892 {
3893 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
3894 // for shader-related entry points
3895 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
3896 return false;
3897 }
3898
3899 if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
3900 {
3901 return false;
3902 }
3903 }
3904
3905 return GetValidProgram(context, program) != nullptr;
3906 }
3907
ValidateBindFramebuffer(const Context * context,GLenum target,FramebufferID framebuffer)3908 bool ValidateBindFramebuffer(const Context *context, GLenum target, FramebufferID framebuffer)
3909 {
3910 return ValidateBindFramebufferBase(context, target, framebuffer);
3911 }
3912
ValidateBindRenderbuffer(const Context * context,GLenum target,RenderbufferID renderbuffer)3913 bool ValidateBindRenderbuffer(const Context *context, GLenum target, RenderbufferID renderbuffer)
3914 {
3915 return ValidateBindRenderbufferBase(context, target, renderbuffer);
3916 }
3917
ValidBlendEquationMode(const Context * context,GLenum mode)3918 static bool ValidBlendEquationMode(const Context *context, GLenum mode)
3919 {
3920 switch (mode)
3921 {
3922 case GL_FUNC_ADD:
3923 case GL_FUNC_SUBTRACT:
3924 case GL_FUNC_REVERSE_SUBTRACT:
3925 return true;
3926
3927 case GL_MIN:
3928 case GL_MAX:
3929 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
3930
3931 default:
3932 return false;
3933 }
3934 }
3935
ValidateBlendColor(const Context * context,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)3936 bool ValidateBlendColor(const Context *context,
3937 GLfloat red,
3938 GLfloat green,
3939 GLfloat blue,
3940 GLfloat alpha)
3941 {
3942 return true;
3943 }
3944
ValidateBlendEquation(const Context * context,GLenum mode)3945 bool ValidateBlendEquation(const Context *context, GLenum mode)
3946 {
3947 if (!ValidBlendEquationMode(context, mode))
3948 {
3949 context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
3950 return false;
3951 }
3952
3953 return true;
3954 }
3955
ValidateBlendEquationSeparate(const Context * context,GLenum modeRGB,GLenum modeAlpha)3956 bool ValidateBlendEquationSeparate(const Context *context, GLenum modeRGB, GLenum modeAlpha)
3957 {
3958 if (!ValidBlendEquationMode(context, modeRGB))
3959 {
3960 context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
3961 return false;
3962 }
3963
3964 if (!ValidBlendEquationMode(context, modeAlpha))
3965 {
3966 context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
3967 return false;
3968 }
3969
3970 return true;
3971 }
3972
ValidateBlendFunc(const Context * context,GLenum sfactor,GLenum dfactor)3973 bool ValidateBlendFunc(const Context *context, GLenum sfactor, GLenum dfactor)
3974 {
3975 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3976 }
3977
ValidateBlendFuncSeparate(const Context * context,GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)3978 bool ValidateBlendFuncSeparate(const Context *context,
3979 GLenum srcRGB,
3980 GLenum dstRGB,
3981 GLenum srcAlpha,
3982 GLenum dstAlpha)
3983 {
3984 if (!ValidSrcBlendFunc(context, srcRGB))
3985 {
3986 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3987 return false;
3988 }
3989
3990 if (!ValidDstBlendFunc(context, dstRGB))
3991 {
3992 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3993 return false;
3994 }
3995
3996 if (!ValidSrcBlendFunc(context, srcAlpha))
3997 {
3998 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3999 return false;
4000 }
4001
4002 if (!ValidDstBlendFunc(context, dstAlpha))
4003 {
4004 context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
4005 return false;
4006 }
4007
4008 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4009 context->getExtensions().webglCompatibility)
4010 {
4011 bool constantColorUsed =
4012 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4013 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4014
4015 bool constantAlphaUsed =
4016 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4017 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4018
4019 if (constantColorUsed && constantAlphaUsed)
4020 {
4021 if (context->getExtensions().webglCompatibility)
4022 {
4023 context->validationError(GL_INVALID_OPERATION, kInvalidConstantColor);
4024 return false;
4025 }
4026
4027 WARN() << kConstantColorAlphaLimitation;
4028 context->validationError(GL_INVALID_OPERATION, kConstantColorAlphaLimitation);
4029 return false;
4030 }
4031 }
4032
4033 return true;
4034 }
4035
ValidateGetString(const Context * context,GLenum name)4036 bool ValidateGetString(const Context *context, GLenum name)
4037 {
4038 switch (name)
4039 {
4040 case GL_VENDOR:
4041 case GL_RENDERER:
4042 case GL_VERSION:
4043 case GL_SHADING_LANGUAGE_VERSION:
4044 case GL_EXTENSIONS:
4045 break;
4046
4047 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4048 if (!context->getExtensions().requestExtension)
4049 {
4050 context->validationError(GL_INVALID_ENUM, kInvalidName);
4051 return false;
4052 }
4053 break;
4054
4055 case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
4056 if (!context->getExtensions().getSerializedContextStringANGLE)
4057 {
4058 context->validationError(GL_INVALID_ENUM, kInvalidName);
4059 return false;
4060 }
4061 break;
4062
4063 default:
4064 context->validationError(GL_INVALID_ENUM, kInvalidName);
4065 return false;
4066 }
4067
4068 return true;
4069 }
4070
ValidateLineWidth(const Context * context,GLfloat width)4071 bool ValidateLineWidth(const Context *context, GLfloat width)
4072 {
4073 if (width <= 0.0f || isNaN(width))
4074 {
4075 context->validationError(GL_INVALID_VALUE, kInvalidWidth);
4076 return false;
4077 }
4078
4079 return true;
4080 }
4081
ValidateDepthRangef(const Context * context,GLfloat zNear,GLfloat zFar)4082 bool ValidateDepthRangef(const Context *context, GLfloat zNear, GLfloat zFar)
4083 {
4084 if (context->getExtensions().webglCompatibility && zNear > zFar)
4085 {
4086 context->validationError(GL_INVALID_OPERATION, kInvalidDepthRange);
4087 return false;
4088 }
4089
4090 return true;
4091 }
4092
ValidateRenderbufferStorage(const Context * context,GLenum target,GLenum internalformat,GLsizei width,GLsizei height)4093 bool ValidateRenderbufferStorage(const Context *context,
4094 GLenum target,
4095 GLenum internalformat,
4096 GLsizei width,
4097 GLsizei height)
4098 {
4099 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4100 height);
4101 }
4102
ValidateRenderbufferStorageMultisampleANGLE(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)4103 bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
4104 GLenum target,
4105 GLsizei samples,
4106 GLenum internalformat,
4107 GLsizei width,
4108 GLsizei height)
4109 {
4110 if (!context->getExtensions().framebufferMultisample)
4111 {
4112 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4113 return false;
4114 }
4115
4116 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4117 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
4118 // generated.
4119 if (samples > context->getCaps().maxSamples)
4120 {
4121 context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
4122 return false;
4123 }
4124
4125 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4126 // the specified storage. This is different than ES 3.0 in which a sample number higher
4127 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4128 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4129 if (context->getClientMajorVersion() >= 3)
4130 {
4131 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4132 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4133 {
4134 context->validationError(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
4135 return false;
4136 }
4137 }
4138
4139 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4140 width, height);
4141 }
4142
ValidateCheckFramebufferStatus(const Context * context,GLenum target)4143 bool ValidateCheckFramebufferStatus(const Context *context, GLenum target)
4144 {
4145 if (!ValidFramebufferTarget(context, target))
4146 {
4147 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
4148 return false;
4149 }
4150
4151 return true;
4152 }
4153
ValidateClearColor(const Context * context,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)4154 bool ValidateClearColor(const Context *context,
4155 GLfloat red,
4156 GLfloat green,
4157 GLfloat blue,
4158 GLfloat alpha)
4159 {
4160 return true;
4161 }
4162
ValidateClearDepthf(const Context * context,GLfloat depth)4163 bool ValidateClearDepthf(const Context *context, GLfloat depth)
4164 {
4165 return true;
4166 }
4167
ValidateClearStencil(const Context * context,GLint s)4168 bool ValidateClearStencil(const Context *context, GLint s)
4169 {
4170 return true;
4171 }
4172
ValidateColorMask(const Context * context,GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)4173 bool ValidateColorMask(const Context *context,
4174 GLboolean red,
4175 GLboolean green,
4176 GLboolean blue,
4177 GLboolean alpha)
4178 {
4179 return true;
4180 }
4181
ValidateCompileShader(const Context * context,ShaderProgramID shader)4182 bool ValidateCompileShader(const Context *context, ShaderProgramID shader)
4183 {
4184 return true;
4185 }
4186
ValidateCreateProgram(const Context * context)4187 bool ValidateCreateProgram(const Context *context)
4188 {
4189 return true;
4190 }
4191
ValidateCullFace(const Context * context,CullFaceMode mode)4192 bool ValidateCullFace(const Context *context, CullFaceMode mode)
4193 {
4194 switch (mode)
4195 {
4196 case CullFaceMode::Front:
4197 case CullFaceMode::Back:
4198 case CullFaceMode::FrontAndBack:
4199 break;
4200
4201 default:
4202 context->validationError(GL_INVALID_ENUM, kInvalidCullMode);
4203 return false;
4204 }
4205
4206 return true;
4207 }
4208
ValidateDeleteProgram(const Context * context,ShaderProgramID program)4209 bool ValidateDeleteProgram(const Context *context, ShaderProgramID program)
4210 {
4211 if (program.value == 0)
4212 {
4213 return false;
4214 }
4215
4216 if (!context->getProgramResolveLink(program))
4217 {
4218 if (context->getShader(program))
4219 {
4220 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
4221 return false;
4222 }
4223 else
4224 {
4225 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
4226 return false;
4227 }
4228 }
4229
4230 return true;
4231 }
4232
ValidateDeleteShader(const Context * context,ShaderProgramID shader)4233 bool ValidateDeleteShader(const Context *context, ShaderProgramID shader)
4234 {
4235 if (shader.value == 0)
4236 {
4237 return false;
4238 }
4239
4240 if (!context->getShader(shader))
4241 {
4242 if (context->getProgramResolveLink(shader))
4243 {
4244 context->validationError(GL_INVALID_OPERATION, kInvalidShaderName);
4245 return false;
4246 }
4247 else
4248 {
4249 context->validationError(GL_INVALID_VALUE, kExpectedShaderName);
4250 return false;
4251 }
4252 }
4253
4254 return true;
4255 }
4256
ValidateDepthFunc(const Context * context,GLenum func)4257 bool ValidateDepthFunc(const Context *context, GLenum func)
4258 {
4259 switch (func)
4260 {
4261 case GL_NEVER:
4262 case GL_ALWAYS:
4263 case GL_LESS:
4264 case GL_LEQUAL:
4265 case GL_EQUAL:
4266 case GL_GREATER:
4267 case GL_GEQUAL:
4268 case GL_NOTEQUAL:
4269 break;
4270
4271 default:
4272 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4273 return false;
4274 }
4275
4276 return true;
4277 }
4278
ValidateDepthMask(const Context * context,GLboolean flag)4279 bool ValidateDepthMask(const Context *context, GLboolean flag)
4280 {
4281 return true;
4282 }
4283
ValidateDetachShader(const Context * context,ShaderProgramID program,ShaderProgramID shader)4284 bool ValidateDetachShader(const Context *context, ShaderProgramID program, ShaderProgramID shader)
4285 {
4286 Program *programObject = GetValidProgram(context, program);
4287 if (!programObject)
4288 {
4289 return false;
4290 }
4291
4292 Shader *shaderObject = GetValidShader(context, shader);
4293 if (!shaderObject)
4294 {
4295 return false;
4296 }
4297
4298 const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType());
4299 if (attachedShader != shaderObject)
4300 {
4301 context->validationError(GL_INVALID_OPERATION, kShaderToDetachMustBeAttached);
4302 return false;
4303 }
4304
4305 return true;
4306 }
4307
ValidateDisableVertexAttribArray(const Context * context,GLuint index)4308 bool ValidateDisableVertexAttribArray(const Context *context, GLuint index)
4309 {
4310 if (index >= MAX_VERTEX_ATTRIBS)
4311 {
4312 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4313 return false;
4314 }
4315
4316 return true;
4317 }
4318
ValidateEnableVertexAttribArray(const Context * context,GLuint index)4319 bool ValidateEnableVertexAttribArray(const Context *context, GLuint index)
4320 {
4321 if (index >= MAX_VERTEX_ATTRIBS)
4322 {
4323 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4324 return false;
4325 }
4326
4327 return true;
4328 }
4329
ValidateFinish(const Context * context)4330 bool ValidateFinish(const Context *context)
4331 {
4332 return true;
4333 }
4334
ValidateFlush(const Context * context)4335 bool ValidateFlush(const Context *context)
4336 {
4337 return true;
4338 }
4339
ValidateFrontFace(const Context * context,GLenum mode)4340 bool ValidateFrontFace(const Context *context, GLenum mode)
4341 {
4342 switch (mode)
4343 {
4344 case GL_CW:
4345 case GL_CCW:
4346 break;
4347 default:
4348 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4349 return false;
4350 }
4351
4352 return true;
4353 }
4354
ValidateGetActiveAttrib(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufsize,const GLsizei * length,const GLint * size,const GLenum * type,const GLchar * name)4355 bool ValidateGetActiveAttrib(const Context *context,
4356 ShaderProgramID program,
4357 GLuint index,
4358 GLsizei bufsize,
4359 const GLsizei *length,
4360 const GLint *size,
4361 const GLenum *type,
4362 const GLchar *name)
4363 {
4364 if (bufsize < 0)
4365 {
4366 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4367 return false;
4368 }
4369
4370 Program *programObject = GetValidProgram(context, program);
4371
4372 if (!programObject)
4373 {
4374 return false;
4375 }
4376
4377 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4378 {
4379 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4380 return false;
4381 }
4382
4383 return true;
4384 }
4385
ValidateGetActiveUniform(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufsize,const GLsizei * length,const GLint * size,const GLenum * type,const GLchar * name)4386 bool ValidateGetActiveUniform(const Context *context,
4387 ShaderProgramID program,
4388 GLuint index,
4389 GLsizei bufsize,
4390 const GLsizei *length,
4391 const GLint *size,
4392 const GLenum *type,
4393 const GLchar *name)
4394 {
4395 if (bufsize < 0)
4396 {
4397 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4398 return false;
4399 }
4400
4401 Program *programObject = GetValidProgram(context, program);
4402
4403 if (!programObject)
4404 {
4405 return false;
4406 }
4407
4408 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4409 {
4410 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4411 return false;
4412 }
4413
4414 return true;
4415 }
4416
ValidateGetAttachedShaders(const Context * context,ShaderProgramID program,GLsizei maxcount,const GLsizei * count,const ShaderProgramID * shaders)4417 bool ValidateGetAttachedShaders(const Context *context,
4418 ShaderProgramID program,
4419 GLsizei maxcount,
4420 const GLsizei *count,
4421 const ShaderProgramID *shaders)
4422 {
4423 if (maxcount < 0)
4424 {
4425 context->validationError(GL_INVALID_VALUE, kNegativeMaxCount);
4426 return false;
4427 }
4428
4429 Program *programObject = GetValidProgram(context, program);
4430
4431 if (!programObject)
4432 {
4433 return false;
4434 }
4435
4436 return true;
4437 }
4438
ValidateGetAttribLocation(const Context * context,ShaderProgramID program,const GLchar * name)4439 bool ValidateGetAttribLocation(const Context *context, ShaderProgramID program, const GLchar *name)
4440 {
4441 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4442 // shader-related entry points
4443 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4444 {
4445 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
4446 return false;
4447 }
4448
4449 Program *programObject = GetValidProgram(context, program);
4450
4451 if (!programObject)
4452 {
4453 context->validationError(GL_INVALID_OPERATION, kProgramNotBound);
4454 return false;
4455 }
4456
4457 if (!programObject->isLinked())
4458 {
4459 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4460 return false;
4461 }
4462
4463 return true;
4464 }
4465
ValidateGetBooleanv(const Context * context,GLenum pname,const GLboolean * params)4466 bool ValidateGetBooleanv(const Context *context, GLenum pname, const GLboolean *params)
4467 {
4468 GLenum nativeType;
4469 unsigned int numParams = 0;
4470 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4471 }
4472
ValidateGetError(const Context * context)4473 bool ValidateGetError(const Context *context)
4474 {
4475 return true;
4476 }
4477
ValidateGetFloatv(const Context * context,GLenum pname,const GLfloat * params)4478 bool ValidateGetFloatv(const Context *context, GLenum pname, const GLfloat *params)
4479 {
4480 GLenum nativeType;
4481 unsigned int numParams = 0;
4482 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4483 }
4484
ValidateGetIntegerv(const Context * context,GLenum pname,const GLint * params)4485 bool ValidateGetIntegerv(const Context *context, GLenum pname, const GLint *params)
4486 {
4487 GLenum nativeType;
4488 unsigned int numParams = 0;
4489 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4490 }
4491
ValidateGetProgramInfoLog(const Context * context,ShaderProgramID program,GLsizei bufsize,const GLsizei * length,const GLchar * infolog)4492 bool ValidateGetProgramInfoLog(const Context *context,
4493 ShaderProgramID program,
4494 GLsizei bufsize,
4495 const GLsizei *length,
4496 const GLchar *infolog)
4497 {
4498 if (bufsize < 0)
4499 {
4500 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4501 return false;
4502 }
4503
4504 Program *programObject = GetValidProgram(context, program);
4505 if (!programObject)
4506 {
4507 return false;
4508 }
4509
4510 return true;
4511 }
4512
ValidateGetShaderInfoLog(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * infolog)4513 bool ValidateGetShaderInfoLog(const Context *context,
4514 ShaderProgramID shader,
4515 GLsizei bufsize,
4516 const GLsizei *length,
4517 const GLchar *infolog)
4518 {
4519 if (bufsize < 0)
4520 {
4521 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4522 return false;
4523 }
4524
4525 Shader *shaderObject = GetValidShader(context, shader);
4526 if (!shaderObject)
4527 {
4528 return false;
4529 }
4530
4531 return true;
4532 }
4533
ValidateGetShaderPrecisionFormat(const Context * context,GLenum shadertype,GLenum precisiontype,const GLint * range,const GLint * precision)4534 bool ValidateGetShaderPrecisionFormat(const Context *context,
4535 GLenum shadertype,
4536 GLenum precisiontype,
4537 const GLint *range,
4538 const GLint *precision)
4539 {
4540 switch (shadertype)
4541 {
4542 case GL_VERTEX_SHADER:
4543 case GL_FRAGMENT_SHADER:
4544 break;
4545 case GL_COMPUTE_SHADER:
4546 context->validationError(GL_INVALID_OPERATION, kUnimplementedComputeShaderPrecision);
4547 return false;
4548 default:
4549 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
4550 return false;
4551 }
4552
4553 switch (precisiontype)
4554 {
4555 case GL_LOW_FLOAT:
4556 case GL_MEDIUM_FLOAT:
4557 case GL_HIGH_FLOAT:
4558 case GL_LOW_INT:
4559 case GL_MEDIUM_INT:
4560 case GL_HIGH_INT:
4561 break;
4562
4563 default:
4564 context->validationError(GL_INVALID_ENUM, kInvalidPrecision);
4565 return false;
4566 }
4567
4568 return true;
4569 }
4570
ValidateGetShaderSource(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * source)4571 bool ValidateGetShaderSource(const Context *context,
4572 ShaderProgramID shader,
4573 GLsizei bufsize,
4574 const GLsizei *length,
4575 const GLchar *source)
4576 {
4577 if (bufsize < 0)
4578 {
4579 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4580 return false;
4581 }
4582
4583 Shader *shaderObject = GetValidShader(context, shader);
4584 if (!shaderObject)
4585 {
4586 return false;
4587 }
4588
4589 return true;
4590 }
4591
ValidateGetUniformLocation(const Context * context,ShaderProgramID program,const GLchar * name)4592 bool ValidateGetUniformLocation(const Context *context, ShaderProgramID program, const GLchar *name)
4593 {
4594 if (strstr(name, "gl_") == name)
4595 {
4596 return false;
4597 }
4598
4599 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4600 // shader-related entry points
4601 if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4602 {
4603 context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
4604 return false;
4605 }
4606
4607 Program *programObject = GetValidProgram(context, program);
4608
4609 if (!programObject)
4610 {
4611 return false;
4612 }
4613
4614 if (!programObject->isLinked())
4615 {
4616 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4617 return false;
4618 }
4619
4620 return true;
4621 }
4622
ValidateHint(const Context * context,GLenum target,GLenum mode)4623 bool ValidateHint(const Context *context, GLenum target, GLenum mode)
4624 {
4625 switch (mode)
4626 {
4627 case GL_FASTEST:
4628 case GL_NICEST:
4629 case GL_DONT_CARE:
4630 break;
4631
4632 default:
4633 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4634 return false;
4635 }
4636
4637 switch (target)
4638 {
4639 case GL_GENERATE_MIPMAP_HINT:
4640 break;
4641
4642 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4643 if (!context->getExtensions().textureFilteringCHROMIUM)
4644 {
4645 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4646 return false;
4647 }
4648 break;
4649
4650 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
4651 if (context->getClientVersion() < ES_3_0 &&
4652 !context->getExtensions().standardDerivativesOES)
4653 {
4654 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4655 return false;
4656 }
4657 break;
4658
4659 case GL_PERSPECTIVE_CORRECTION_HINT:
4660 case GL_POINT_SMOOTH_HINT:
4661 case GL_LINE_SMOOTH_HINT:
4662 case GL_FOG_HINT:
4663 if (context->getClientMajorVersion() >= 2)
4664 {
4665 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4666 return false;
4667 }
4668 break;
4669
4670 default:
4671 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4672 return false;
4673 }
4674
4675 return true;
4676 }
4677
ValidateIsBuffer(const Context * context,BufferID buffer)4678 bool ValidateIsBuffer(const Context *context, BufferID buffer)
4679 {
4680 return true;
4681 }
4682
ValidateIsFramebuffer(const Context * context,FramebufferID framebuffer)4683 bool ValidateIsFramebuffer(const Context *context, FramebufferID framebuffer)
4684 {
4685 return true;
4686 }
4687
ValidateIsProgram(const Context * context,ShaderProgramID program)4688 bool ValidateIsProgram(const Context *context, ShaderProgramID program)
4689 {
4690 return true;
4691 }
4692
ValidateIsRenderbuffer(const Context * context,RenderbufferID renderbuffer)4693 bool ValidateIsRenderbuffer(const Context *context, RenderbufferID renderbuffer)
4694 {
4695 return true;
4696 }
4697
ValidateIsShader(const Context * context,ShaderProgramID shader)4698 bool ValidateIsShader(const Context *context, ShaderProgramID shader)
4699 {
4700 return true;
4701 }
4702
ValidateIsTexture(const Context * context,TextureID texture)4703 bool ValidateIsTexture(const Context *context, TextureID texture)
4704 {
4705 return true;
4706 }
4707
ValidatePixelStorei(const Context * context,GLenum pname,GLint param)4708 bool ValidatePixelStorei(const Context *context, GLenum pname, GLint param)
4709 {
4710 if (context->getClientMajorVersion() < 3)
4711 {
4712 switch (pname)
4713 {
4714 case GL_UNPACK_IMAGE_HEIGHT:
4715 case GL_UNPACK_SKIP_IMAGES:
4716 context->validationError(GL_INVALID_ENUM, kInvalidPname);
4717 return false;
4718
4719 case GL_UNPACK_ROW_LENGTH:
4720 case GL_UNPACK_SKIP_ROWS:
4721 case GL_UNPACK_SKIP_PIXELS:
4722 if (!context->getExtensions().unpackSubimage)
4723 {
4724 context->validationError(GL_INVALID_ENUM, kInvalidPname);
4725 return false;
4726 }
4727 break;
4728
4729 case GL_PACK_ROW_LENGTH:
4730 case GL_PACK_SKIP_ROWS:
4731 case GL_PACK_SKIP_PIXELS:
4732 if (!context->getExtensions().packSubimage)
4733 {
4734 context->validationError(GL_INVALID_ENUM, kInvalidPname);
4735 return false;
4736 }
4737 break;
4738 }
4739 }
4740
4741 if (param < 0)
4742 {
4743 context->validationError(GL_INVALID_VALUE, kNegativeParam);
4744 return false;
4745 }
4746
4747 switch (pname)
4748 {
4749 case GL_UNPACK_ALIGNMENT:
4750 if (param != 1 && param != 2 && param != 4 && param != 8)
4751 {
4752 context->validationError(GL_INVALID_VALUE, kInvalidUnpackAlignment);
4753 return false;
4754 }
4755 break;
4756
4757 case GL_PACK_ALIGNMENT:
4758 if (param != 1 && param != 2 && param != 4 && param != 8)
4759 {
4760 context->validationError(GL_INVALID_VALUE, kInvalidUnpackAlignment);
4761 return false;
4762 }
4763 break;
4764
4765 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4766 if (!context->getExtensions().packReverseRowOrder)
4767 {
4768 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4769 }
4770 break;
4771
4772 case GL_UNPACK_ROW_LENGTH:
4773 case GL_UNPACK_IMAGE_HEIGHT:
4774 case GL_UNPACK_SKIP_IMAGES:
4775 case GL_UNPACK_SKIP_ROWS:
4776 case GL_UNPACK_SKIP_PIXELS:
4777 case GL_PACK_ROW_LENGTH:
4778 case GL_PACK_SKIP_ROWS:
4779 case GL_PACK_SKIP_PIXELS:
4780 break;
4781
4782 default:
4783 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4784 return false;
4785 }
4786
4787 return true;
4788 }
4789
ValidatePolygonOffset(const Context * context,GLfloat factor,GLfloat units)4790 bool ValidatePolygonOffset(const Context *context, GLfloat factor, GLfloat units)
4791 {
4792 return true;
4793 }
4794
ValidateReleaseShaderCompiler(const Context * context)4795 bool ValidateReleaseShaderCompiler(const Context *context)
4796 {
4797 return true;
4798 }
4799
ValidateSampleCoverage(const Context * context,GLfloat value,GLboolean invert)4800 bool ValidateSampleCoverage(const Context *context, GLfloat value, GLboolean invert)
4801 {
4802 return true;
4803 }
4804
ValidateScissor(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height)4805 bool ValidateScissor(const Context *context, GLint x, GLint y, GLsizei width, GLsizei height)
4806 {
4807 if (width < 0 || height < 0)
4808 {
4809 context->validationError(GL_INVALID_VALUE, kNegativeSize);
4810 return false;
4811 }
4812
4813 return true;
4814 }
4815
ValidateShaderBinary(const Context * context,GLsizei n,const ShaderProgramID * shaders,GLenum binaryformat,const void * binary,GLsizei length)4816 bool ValidateShaderBinary(const Context *context,
4817 GLsizei n,
4818 const ShaderProgramID *shaders,
4819 GLenum binaryformat,
4820 const void *binary,
4821 GLsizei length)
4822 {
4823 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4824 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4825 shaderBinaryFormats.end())
4826 {
4827 context->validationError(GL_INVALID_ENUM, kInvalidShaderBinaryFormat);
4828 return false;
4829 }
4830
4831 return true;
4832 }
4833
ValidateShaderSource(const Context * context,ShaderProgramID shader,GLsizei count,const GLchar * const * string,const GLint * length)4834 bool ValidateShaderSource(const Context *context,
4835 ShaderProgramID shader,
4836 GLsizei count,
4837 const GLchar *const *string,
4838 const GLint *length)
4839 {
4840 if (count < 0)
4841 {
4842 context->validationError(GL_INVALID_VALUE, kNegativeCount);
4843 return false;
4844 }
4845
4846 Shader *shaderObject = GetValidShader(context, shader);
4847 if (!shaderObject)
4848 {
4849 return false;
4850 }
4851
4852 return true;
4853 }
4854
ValidateStencilFunc(const Context * context,GLenum func,GLint ref,GLuint mask)4855 bool ValidateStencilFunc(const Context *context, GLenum func, GLint ref, GLuint mask)
4856 {
4857 if (!IsValidStencilFunc(func))
4858 {
4859 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4860 return false;
4861 }
4862
4863 return true;
4864 }
4865
ValidateStencilFuncSeparate(const Context * context,GLenum face,GLenum func,GLint ref,GLuint mask)4866 bool ValidateStencilFuncSeparate(const Context *context,
4867 GLenum face,
4868 GLenum func,
4869 GLint ref,
4870 GLuint mask)
4871 {
4872 if (!IsValidStencilFace(face))
4873 {
4874 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4875 return false;
4876 }
4877
4878 if (!IsValidStencilFunc(func))
4879 {
4880 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4881 return false;
4882 }
4883
4884 return true;
4885 }
4886
ValidateStencilMask(const Context * context,GLuint mask)4887 bool ValidateStencilMask(const Context *context, GLuint mask)
4888 {
4889 return true;
4890 }
4891
ValidateStencilMaskSeparate(const Context * context,GLenum face,GLuint mask)4892 bool ValidateStencilMaskSeparate(const Context *context, GLenum face, GLuint mask)
4893 {
4894 if (!IsValidStencilFace(face))
4895 {
4896 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4897 return false;
4898 }
4899
4900 return true;
4901 }
4902
ValidateStencilOp(const Context * context,GLenum fail,GLenum zfail,GLenum zpass)4903 bool ValidateStencilOp(const Context *context, GLenum fail, GLenum zfail, GLenum zpass)
4904 {
4905 if (!IsValidStencilOp(fail))
4906 {
4907 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4908 return false;
4909 }
4910
4911 if (!IsValidStencilOp(zfail))
4912 {
4913 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4914 return false;
4915 }
4916
4917 if (!IsValidStencilOp(zpass))
4918 {
4919 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4920 return false;
4921 }
4922
4923 return true;
4924 }
4925
ValidateStencilOpSeparate(const Context * context,GLenum face,GLenum fail,GLenum zfail,GLenum zpass)4926 bool ValidateStencilOpSeparate(const Context *context,
4927 GLenum face,
4928 GLenum fail,
4929 GLenum zfail,
4930 GLenum zpass)
4931 {
4932 if (!IsValidStencilFace(face))
4933 {
4934 context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4935 return false;
4936 }
4937
4938 return ValidateStencilOp(context, fail, zfail, zpass);
4939 }
4940
ValidateUniform1f(const Context * context,UniformLocation location,GLfloat x)4941 bool ValidateUniform1f(const Context *context, UniformLocation location, GLfloat x)
4942 {
4943 return ValidateUniform(context, GL_FLOAT, location, 1);
4944 }
4945
ValidateUniform1fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4946 bool ValidateUniform1fv(const Context *context,
4947 UniformLocation location,
4948 GLsizei count,
4949 const GLfloat *v)
4950 {
4951 return ValidateUniform(context, GL_FLOAT, location, count);
4952 }
4953
ValidateUniform1i(const Context * context,UniformLocation location,GLint x)4954 bool ValidateUniform1i(const Context *context, UniformLocation location, GLint x)
4955 {
4956 return ValidateUniform1iv(context, location, 1, &x);
4957 }
4958
ValidateUniform2fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4959 bool ValidateUniform2fv(const Context *context,
4960 UniformLocation location,
4961 GLsizei count,
4962 const GLfloat *v)
4963 {
4964 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
4965 }
4966
ValidateUniform2i(const Context * context,UniformLocation location,GLint x,GLint y)4967 bool ValidateUniform2i(const Context *context, UniformLocation location, GLint x, GLint y)
4968 {
4969 return ValidateUniform(context, GL_INT_VEC2, location, 1);
4970 }
4971
ValidateUniform2iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)4972 bool ValidateUniform2iv(const Context *context,
4973 UniformLocation location,
4974 GLsizei count,
4975 const GLint *v)
4976 {
4977 return ValidateUniform(context, GL_INT_VEC2, location, count);
4978 }
4979
ValidateUniform3f(const Context * context,UniformLocation location,GLfloat x,GLfloat y,GLfloat z)4980 bool ValidateUniform3f(const Context *context,
4981 UniformLocation location,
4982 GLfloat x,
4983 GLfloat y,
4984 GLfloat z)
4985 {
4986 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
4987 }
4988
ValidateUniform3fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4989 bool ValidateUniform3fv(const Context *context,
4990 UniformLocation location,
4991 GLsizei count,
4992 const GLfloat *v)
4993 {
4994 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
4995 }
4996
ValidateUniform3i(const Context * context,UniformLocation location,GLint x,GLint y,GLint z)4997 bool ValidateUniform3i(const Context *context, UniformLocation location, GLint x, GLint y, GLint z)
4998 {
4999 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5000 }
5001
ValidateUniform3iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)5002 bool ValidateUniform3iv(const Context *context,
5003 UniformLocation location,
5004 GLsizei count,
5005 const GLint *v)
5006 {
5007 return ValidateUniform(context, GL_INT_VEC3, location, count);
5008 }
5009
ValidateUniform4f(const Context * context,UniformLocation location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)5010 bool ValidateUniform4f(const Context *context,
5011 UniformLocation location,
5012 GLfloat x,
5013 GLfloat y,
5014 GLfloat z,
5015 GLfloat w)
5016 {
5017 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5018 }
5019
ValidateUniform4fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)5020 bool ValidateUniform4fv(const Context *context,
5021 UniformLocation location,
5022 GLsizei count,
5023 const GLfloat *v)
5024 {
5025 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5026 }
5027
ValidateUniform4i(const Context * context,UniformLocation location,GLint x,GLint y,GLint z,GLint w)5028 bool ValidateUniform4i(const Context *context,
5029 UniformLocation location,
5030 GLint x,
5031 GLint y,
5032 GLint z,
5033 GLint w)
5034 {
5035 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5036 }
5037
ValidateUniform4iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)5038 bool ValidateUniform4iv(const Context *context,
5039 UniformLocation location,
5040 GLsizei count,
5041 const GLint *v)
5042 {
5043 return ValidateUniform(context, GL_INT_VEC4, location, count);
5044 }
5045
ValidateUniformMatrix2fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)5046 bool ValidateUniformMatrix2fv(const Context *context,
5047 UniformLocation location,
5048 GLsizei count,
5049 GLboolean transpose,
5050 const GLfloat *value)
5051 {
5052 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5053 }
5054
ValidateUniformMatrix3fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)5055 bool ValidateUniformMatrix3fv(const Context *context,
5056 UniformLocation location,
5057 GLsizei count,
5058 GLboolean transpose,
5059 const GLfloat *value)
5060 {
5061 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5062 }
5063
ValidateUniformMatrix4fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)5064 bool ValidateUniformMatrix4fv(const Context *context,
5065 UniformLocation location,
5066 GLsizei count,
5067 GLboolean transpose,
5068 const GLfloat *value)
5069 {
5070 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5071 }
5072
ValidateValidateProgram(const Context * context,ShaderProgramID program)5073 bool ValidateValidateProgram(const Context *context, ShaderProgramID program)
5074 {
5075 Program *programObject = GetValidProgram(context, program);
5076
5077 if (!programObject)
5078 {
5079 return false;
5080 }
5081
5082 return true;
5083 }
5084
ValidateVertexAttrib1f(const Context * context,GLuint index,GLfloat x)5085 bool ValidateVertexAttrib1f(const Context *context, GLuint index, GLfloat x)
5086 {
5087 return ValidateVertexAttribIndex(context, index);
5088 }
5089
ValidateVertexAttrib1fv(const Context * context,GLuint index,const GLfloat * values)5090 bool ValidateVertexAttrib1fv(const Context *context, GLuint index, const GLfloat *values)
5091 {
5092 return ValidateVertexAttribIndex(context, index);
5093 }
5094
ValidateVertexAttrib2f(const Context * context,GLuint index,GLfloat x,GLfloat y)5095 bool ValidateVertexAttrib2f(const Context *context, GLuint index, GLfloat x, GLfloat y)
5096 {
5097 return ValidateVertexAttribIndex(context, index);
5098 }
5099
ValidateVertexAttrib2fv(const Context * context,GLuint index,const GLfloat * values)5100 bool ValidateVertexAttrib2fv(const Context *context, GLuint index, const GLfloat *values)
5101 {
5102 return ValidateVertexAttribIndex(context, index);
5103 }
5104
ValidateVertexAttrib3f(const Context * context,GLuint index,GLfloat x,GLfloat y,GLfloat z)5105 bool ValidateVertexAttrib3f(const Context *context, GLuint index, GLfloat x, GLfloat y, GLfloat z)
5106 {
5107 return ValidateVertexAttribIndex(context, index);
5108 }
5109
ValidateVertexAttrib3fv(const Context * context,GLuint index,const GLfloat * values)5110 bool ValidateVertexAttrib3fv(const Context *context, GLuint index, const GLfloat *values)
5111 {
5112 return ValidateVertexAttribIndex(context, index);
5113 }
5114
ValidateVertexAttrib4f(const Context * context,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)5115 bool ValidateVertexAttrib4f(const Context *context,
5116 GLuint index,
5117 GLfloat x,
5118 GLfloat y,
5119 GLfloat z,
5120 GLfloat w)
5121 {
5122 return ValidateVertexAttribIndex(context, index);
5123 }
5124
ValidateVertexAttrib4fv(const Context * context,GLuint index,const GLfloat * values)5125 bool ValidateVertexAttrib4fv(const Context *context, GLuint index, const GLfloat *values)
5126 {
5127 return ValidateVertexAttribIndex(context, index);
5128 }
5129
ValidateViewport(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height)5130 bool ValidateViewport(const Context *context, GLint x, GLint y, GLsizei width, GLsizei height)
5131 {
5132 if (width < 0 || height < 0)
5133 {
5134 context->validationError(GL_INVALID_VALUE, kViewportNegativeSize);
5135 return false;
5136 }
5137
5138 return true;
5139 }
5140
ValidateGetFramebufferAttachmentParameteriv(const Context * context,GLenum target,GLenum attachment,GLenum pname,const GLint * params)5141 bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
5142 GLenum target,
5143 GLenum attachment,
5144 GLenum pname,
5145 const GLint *params)
5146 {
5147 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5148 nullptr);
5149 }
5150
ValidateGetProgramiv(const Context * context,ShaderProgramID program,GLenum pname,const GLint * params)5151 bool ValidateGetProgramiv(const Context *context,
5152 ShaderProgramID program,
5153 GLenum pname,
5154 const GLint *params)
5155 {
5156 return ValidateGetProgramivBase(context, program, pname, nullptr);
5157 }
5158
ValidateCopyTexImage2D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)5159 bool ValidateCopyTexImage2D(const Context *context,
5160 TextureTarget target,
5161 GLint level,
5162 GLenum internalformat,
5163 GLint x,
5164 GLint y,
5165 GLsizei width,
5166 GLsizei height,
5167 GLint border)
5168 {
5169 if (context->getClientMajorVersion() < 3)
5170 {
5171 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5172 0, x, y, width, height, border);
5173 }
5174
5175 ASSERT(context->getClientMajorVersion() == 3);
5176 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5177 0, x, y, width, height, border);
5178 }
5179
ValidateCopyTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)5180 bool ValidateCopyTexSubImage2D(const Context *context,
5181 TextureTarget target,
5182 GLint level,
5183 GLint xoffset,
5184 GLint yoffset,
5185 GLint x,
5186 GLint y,
5187 GLsizei width,
5188 GLsizei height)
5189 {
5190 if (context->getClientMajorVersion() < 3)
5191 {
5192 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5193 yoffset, x, y, width, height, 0);
5194 }
5195
5196 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5197 yoffset, 0, x, y, width, height, 0);
5198 }
5199
ValidateCopyTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)5200 bool ValidateCopyTexSubImage3DOES(const Context *context,
5201 TextureTarget target,
5202 GLint level,
5203 GLint xoffset,
5204 GLint yoffset,
5205 GLint zoffset,
5206 GLint x,
5207 GLint y,
5208 GLsizei width,
5209 GLsizei height)
5210 {
5211 return ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y, width,
5212 height);
5213 }
5214
ValidateDeleteBuffers(const Context * context,GLint n,const BufferID * buffers)5215 bool ValidateDeleteBuffers(const Context *context, GLint n, const BufferID *buffers)
5216 {
5217 return ValidateGenOrDelete(context, n);
5218 }
5219
ValidateDeleteFramebuffers(const Context * context,GLint n,const FramebufferID * framebuffers)5220 bool ValidateDeleteFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers)
5221 {
5222 return ValidateGenOrDelete(context, n);
5223 }
5224
ValidateDeleteRenderbuffers(const Context * context,GLint n,const RenderbufferID * renderbuffers)5225 bool ValidateDeleteRenderbuffers(const Context *context,
5226 GLint n,
5227 const RenderbufferID *renderbuffers)
5228 {
5229 return ValidateGenOrDelete(context, n);
5230 }
5231
ValidateDeleteTextures(const Context * context,GLint n,const TextureID * textures)5232 bool ValidateDeleteTextures(const Context *context, GLint n, const TextureID *textures)
5233 {
5234 return ValidateGenOrDelete(context, n);
5235 }
5236
ValidateDisable(const Context * context,GLenum cap)5237 bool ValidateDisable(const Context *context, GLenum cap)
5238 {
5239 if (!ValidCap(context, cap, false))
5240 {
5241 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5242 return false;
5243 }
5244
5245 return true;
5246 }
5247
ValidateEnable(const Context * context,GLenum cap)5248 bool ValidateEnable(const Context *context, GLenum cap)
5249 {
5250 if (!ValidCap(context, cap, false))
5251 {
5252 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5253 return false;
5254 }
5255
5256 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5257 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5258 {
5259 context->validationError(GL_INVALID_OPERATION, kNoSampleAlphaToCoveragesLimitation);
5260
5261 // We also output an error message to the debugger window if tracing is active, so that
5262 // developers can see the error message.
5263 ERR() << kNoSampleAlphaToCoveragesLimitation;
5264 return false;
5265 }
5266
5267 return true;
5268 }
5269
ValidateFramebufferRenderbuffer(const Context * context,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)5270 bool ValidateFramebufferRenderbuffer(const Context *context,
5271 GLenum target,
5272 GLenum attachment,
5273 GLenum renderbuffertarget,
5274 RenderbufferID renderbuffer)
5275 {
5276 return ValidateFramebufferRenderbufferBase(context, target, attachment, renderbuffertarget,
5277 renderbuffer);
5278 }
5279
ValidateFramebufferTexture2D(const Context * context,GLenum target,GLenum attachment,TextureTarget textarget,TextureID texture,GLint level)5280 bool ValidateFramebufferTexture2D(const Context *context,
5281 GLenum target,
5282 GLenum attachment,
5283 TextureTarget textarget,
5284 TextureID texture,
5285 GLint level)
5286 {
5287 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5288 // extension
5289 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
5290 level != 0)
5291 {
5292 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
5293 return false;
5294 }
5295
5296 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5297 {
5298 return false;
5299 }
5300
5301 if (texture.value != 0)
5302 {
5303 Texture *tex = context->getTexture(texture);
5304 ASSERT(tex);
5305
5306 const Caps &caps = context->getCaps();
5307
5308 switch (textarget)
5309 {
5310 case TextureTarget::_2D:
5311 {
5312 if (level > log2(caps.max2DTextureSize))
5313 {
5314 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5315 return false;
5316 }
5317 if (tex->getType() != TextureType::_2D)
5318 {
5319 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
5320 return false;
5321 }
5322 }
5323 break;
5324
5325 case TextureTarget::Rectangle:
5326 {
5327 if (level != 0)
5328 {
5329 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5330 return false;
5331 }
5332 if (tex->getType() != TextureType::Rectangle)
5333 {
5334 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5335 return false;
5336 }
5337 }
5338 break;
5339
5340 case TextureTarget::CubeMapNegativeX:
5341 case TextureTarget::CubeMapNegativeY:
5342 case TextureTarget::CubeMapNegativeZ:
5343 case TextureTarget::CubeMapPositiveX:
5344 case TextureTarget::CubeMapPositiveY:
5345 case TextureTarget::CubeMapPositiveZ:
5346 {
5347 if (level > log2(caps.maxCubeMapTextureSize))
5348 {
5349 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5350 return false;
5351 }
5352 if (tex->getType() != TextureType::CubeMap)
5353 {
5354 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5355 return false;
5356 }
5357 }
5358 break;
5359
5360 case TextureTarget::_2DMultisample:
5361 {
5362 if (context->getClientVersion() < ES_3_1 &&
5363 !context->getExtensions().textureMultisample)
5364 {
5365 context->validationError(GL_INVALID_OPERATION,
5366 kMultisampleTextureExtensionOrES31Required);
5367 return false;
5368 }
5369
5370 if (level != 0)
5371 {
5372 context->validationError(GL_INVALID_VALUE, kLevelNotZero);
5373 return false;
5374 }
5375 if (tex->getType() != TextureType::_2DMultisample)
5376 {
5377 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5378 return false;
5379 }
5380 }
5381 break;
5382
5383 case TextureTarget::External:
5384 {
5385 if (!context->getExtensions().yuvTargetEXT)
5386 {
5387 context->validationError(GL_INVALID_OPERATION, kYUVTargetExtensionRequired);
5388 return false;
5389 }
5390
5391 if (attachment != GL_COLOR_ATTACHMENT0)
5392 {
5393 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
5394 return false;
5395 }
5396
5397 if (tex->getType() != TextureType::External)
5398 {
5399 context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5400 return false;
5401 }
5402 }
5403 break;
5404
5405 default:
5406 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5407 return false;
5408 }
5409 }
5410
5411 return true;
5412 }
5413
ValidateFramebufferTexture3DOES(const Context * context,GLenum target,GLenum attachment,TextureTarget textargetPacked,TextureID texture,GLint level,GLint zoffset)5414 bool ValidateFramebufferTexture3DOES(const Context *context,
5415 GLenum target,
5416 GLenum attachment,
5417 TextureTarget textargetPacked,
5418 TextureID texture,
5419 GLint level,
5420 GLint zoffset)
5421 {
5422 // We don't call into a base ValidateFramebufferTexture3D here because
5423 // it doesn't exist for OpenGL ES. This function is replaced by
5424 // FramebufferTextureLayer in ES 3.x, which has broader support.
5425 if (!context->getExtensions().texture3DOES)
5426 {
5427 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5428 return false;
5429 }
5430
5431 // Attachments are required to be bound to level 0 without ES3 or the
5432 // GL_OES_fbo_render_mipmap extension
5433 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
5434 level != 0)
5435 {
5436 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
5437 return false;
5438 }
5439
5440 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5441 {
5442 return false;
5443 }
5444
5445 if (texture.value != 0)
5446 {
5447 Texture *tex = context->getTexture(texture);
5448 ASSERT(tex);
5449
5450 const Caps &caps = context->getCaps();
5451
5452 switch (textargetPacked)
5453 {
5454 case TextureTarget::_3D:
5455 {
5456 if (level > log2(caps.max3DTextureSize))
5457 {
5458 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5459 return false;
5460 }
5461 if (zoffset >= caps.max3DTextureSize)
5462 {
5463 context->validationError(GL_INVALID_VALUE, kInvalidZOffset);
5464 return false;
5465 }
5466 if (tex->getType() != TextureType::_3D)
5467 {
5468 context->validationError(GL_INVALID_OPERATION, kInvalidTextureType);
5469 return false;
5470 }
5471 }
5472 break;
5473
5474 default:
5475 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
5476 return false;
5477 }
5478 }
5479
5480 return true;
5481 }
5482
ValidateGenBuffers(const Context * context,GLint n,const BufferID * buffers)5483 bool ValidateGenBuffers(const Context *context, GLint n, const BufferID *buffers)
5484 {
5485 return ValidateGenOrDelete(context, n);
5486 }
5487
ValidateGenFramebuffers(const Context * context,GLint n,const FramebufferID * framebuffers)5488 bool ValidateGenFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers)
5489 {
5490 return ValidateGenOrDelete(context, n);
5491 }
5492
ValidateGenRenderbuffers(const Context * context,GLint n,const RenderbufferID * renderbuffers)5493 bool ValidateGenRenderbuffers(const Context *context, GLint n, const RenderbufferID *renderbuffers)
5494 {
5495 return ValidateGenOrDelete(context, n);
5496 }
5497
ValidateGenTextures(const Context * context,GLint n,const TextureID * textures)5498 bool ValidateGenTextures(const Context *context, GLint n, const TextureID *textures)
5499 {
5500 return ValidateGenOrDelete(context, n);
5501 }
5502
ValidateGenerateMipmap(const Context * context,TextureType target)5503 bool ValidateGenerateMipmap(const Context *context, TextureType target)
5504 {
5505 return ValidateGenerateMipmapBase(context, target);
5506 }
5507
ValidateGetBufferParameteriv(const Context * context,BufferBinding target,GLenum pname,const GLint * params)5508 bool ValidateGetBufferParameteriv(const Context *context,
5509 BufferBinding target,
5510 GLenum pname,
5511 const GLint *params)
5512 {
5513 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5514 }
5515
ValidateGetRenderbufferParameteriv(const Context * context,GLenum target,GLenum pname,const GLint * params)5516 bool ValidateGetRenderbufferParameteriv(const Context *context,
5517 GLenum target,
5518 GLenum pname,
5519 const GLint *params)
5520 {
5521 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5522 }
5523
ValidateGetShaderiv(const Context * context,ShaderProgramID shader,GLenum pname,const GLint * params)5524 bool ValidateGetShaderiv(const Context *context,
5525 ShaderProgramID shader,
5526 GLenum pname,
5527 const GLint *params)
5528 {
5529 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5530 }
5531
ValidateGetTexParameterfv(const Context * context,TextureType target,GLenum pname,const GLfloat * params)5532 bool ValidateGetTexParameterfv(const Context *context,
5533 TextureType target,
5534 GLenum pname,
5535 const GLfloat *params)
5536 {
5537 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5538 }
5539
ValidateGetTexParameteriv(const Context * context,TextureType target,GLenum pname,const GLint * params)5540 bool ValidateGetTexParameteriv(const Context *context,
5541 TextureType target,
5542 GLenum pname,
5543 const GLint *params)
5544 {
5545 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5546 }
5547
ValidateGetTexParameterIivOES(const Context * context,TextureType target,GLenum pname,const GLint * params)5548 bool ValidateGetTexParameterIivOES(const Context *context,
5549 TextureType target,
5550 GLenum pname,
5551 const GLint *params)
5552 {
5553 if (context->getClientMajorVersion() < 3)
5554 {
5555 context->validationError(GL_INVALID_OPERATION, kES3Required);
5556 return false;
5557 }
5558 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5559 }
5560
ValidateGetTexParameterIuivOES(const Context * context,TextureType target,GLenum pname,const GLuint * params)5561 bool ValidateGetTexParameterIuivOES(const Context *context,
5562 TextureType target,
5563 GLenum pname,
5564 const GLuint *params)
5565 {
5566 if (context->getClientMajorVersion() < 3)
5567 {
5568 context->validationError(GL_INVALID_OPERATION, kES3Required);
5569 return false;
5570 }
5571 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5572 }
5573
ValidateGetUniformfv(const Context * context,ShaderProgramID program,UniformLocation location,const GLfloat * params)5574 bool ValidateGetUniformfv(const Context *context,
5575 ShaderProgramID program,
5576 UniformLocation location,
5577 const GLfloat *params)
5578 {
5579 return ValidateGetUniformBase(context, program, location);
5580 }
5581
ValidateGetUniformiv(const Context * context,ShaderProgramID program,UniformLocation location,const GLint * params)5582 bool ValidateGetUniformiv(const Context *context,
5583 ShaderProgramID program,
5584 UniformLocation location,
5585 const GLint *params)
5586 {
5587 return ValidateGetUniformBase(context, program, location);
5588 }
5589
ValidateGetVertexAttribfv(const Context * context,GLuint index,GLenum pname,const GLfloat * params)5590 bool ValidateGetVertexAttribfv(const Context *context,
5591 GLuint index,
5592 GLenum pname,
5593 const GLfloat *params)
5594 {
5595 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5596 }
5597
ValidateGetVertexAttribiv(const Context * context,GLuint index,GLenum pname,const GLint * params)5598 bool ValidateGetVertexAttribiv(const Context *context,
5599 GLuint index,
5600 GLenum pname,
5601 const GLint *params)
5602 {
5603 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5604 }
5605
ValidateGetVertexAttribPointerv(const Context * context,GLuint index,GLenum pname,void * const * pointer)5606 bool ValidateGetVertexAttribPointerv(const Context *context,
5607 GLuint index,
5608 GLenum pname,
5609 void *const *pointer)
5610 {
5611 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5612 }
5613
ValidateIsEnabled(const Context * context,GLenum cap)5614 bool ValidateIsEnabled(const Context *context, GLenum cap)
5615 {
5616 if (!ValidCap(context, cap, true))
5617 {
5618 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5619 return false;
5620 }
5621
5622 return true;
5623 }
5624
ValidateLinkProgram(const Context * context,ShaderProgramID program)5625 bool ValidateLinkProgram(const Context *context, ShaderProgramID program)
5626 {
5627 if (context->hasActiveTransformFeedback(program))
5628 {
5629 // ES 3.0.4 section 2.15 page 91
5630 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackActiveDuringLink);
5631 return false;
5632 }
5633
5634 Program *programObject = GetValidProgram(context, program);
5635 if (!programObject)
5636 {
5637 return false;
5638 }
5639
5640 return true;
5641 }
5642
ValidateReadPixels(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)5643 bool ValidateReadPixels(const Context *context,
5644 GLint x,
5645 GLint y,
5646 GLsizei width,
5647 GLsizei height,
5648 GLenum format,
5649 GLenum type,
5650 const void *pixels)
5651 {
5652 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5653 nullptr, pixels);
5654 }
5655
ValidateTexParameterf(const Context * context,TextureType target,GLenum pname,GLfloat param)5656 bool ValidateTexParameterf(const Context *context, TextureType target, GLenum pname, GLfloat param)
5657 {
5658 return ValidateTexParameterBase(context, target, pname, -1, false, ¶m);
5659 }
5660
ValidateTexParameterfv(const Context * context,TextureType target,GLenum pname,const GLfloat * params)5661 bool ValidateTexParameterfv(const Context *context,
5662 TextureType target,
5663 GLenum pname,
5664 const GLfloat *params)
5665 {
5666 return ValidateTexParameterBase(context, target, pname, -1, true, params);
5667 }
5668
ValidateTexParameteri(const Context * context,TextureType target,GLenum pname,GLint param)5669 bool ValidateTexParameteri(const Context *context, TextureType target, GLenum pname, GLint param)
5670 {
5671 return ValidateTexParameterBase(context, target, pname, -1, false, ¶m);
5672 }
5673
ValidateTexParameteriv(const Context * context,TextureType target,GLenum pname,const GLint * params)5674 bool ValidateTexParameteriv(const Context *context,
5675 TextureType target,
5676 GLenum pname,
5677 const GLint *params)
5678 {
5679 return ValidateTexParameterBase(context, target, pname, -1, true, params);
5680 }
5681
ValidateTexParameterIivOES(const Context * context,TextureType target,GLenum pname,const GLint * params)5682 bool ValidateTexParameterIivOES(const Context *context,
5683 TextureType target,
5684 GLenum pname,
5685 const GLint *params)
5686 {
5687 if (context->getClientMajorVersion() < 3)
5688 {
5689 context->validationError(GL_INVALID_OPERATION, kES3Required);
5690 return false;
5691 }
5692 return ValidateTexParameterBase(context, target, pname, -1, true, params);
5693 }
5694
ValidateTexParameterIuivOES(const Context * context,TextureType target,GLenum pname,const GLuint * params)5695 bool ValidateTexParameterIuivOES(const Context *context,
5696 TextureType target,
5697 GLenum pname,
5698 const GLuint *params)
5699 {
5700 if (context->getClientMajorVersion() < 3)
5701 {
5702 context->validationError(GL_INVALID_OPERATION, kES3Required);
5703 return false;
5704 }
5705 return ValidateTexParameterBase(context, target, pname, -1, true, params);
5706 }
5707
ValidateUseProgram(const Context * context,ShaderProgramID program)5708 bool ValidateUseProgram(const Context *context, ShaderProgramID program)
5709 {
5710 if (program.value != 0)
5711 {
5712 Program *programObject = context->getProgramResolveLink(program);
5713 if (!programObject)
5714 {
5715 // ES 3.1.0 section 7.3 page 72
5716 if (context->getShader(program))
5717 {
5718 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
5719 return false;
5720 }
5721 else
5722 {
5723 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
5724 return false;
5725 }
5726 }
5727 if (!programObject->isLinked())
5728 {
5729 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
5730 return false;
5731 }
5732 }
5733 if (context->getState().isTransformFeedbackActiveUnpaused())
5734 {
5735 // ES 3.0.4 section 2.15 page 91
5736 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackUseProgram);
5737 return false;
5738 }
5739
5740 return true;
5741 }
5742
ValidateDeleteFencesNV(const Context * context,GLsizei n,const FenceNVID * fences)5743 bool ValidateDeleteFencesNV(const Context *context, GLsizei n, const FenceNVID *fences)
5744 {
5745 if (!context->getExtensions().fenceNV)
5746 {
5747 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5748 return false;
5749 }
5750
5751 if (n < 0)
5752 {
5753 context->validationError(GL_INVALID_VALUE, kNegativeCount);
5754 return false;
5755 }
5756
5757 return true;
5758 }
5759
ValidateFinishFenceNV(const Context * context,FenceNVID fence)5760 bool ValidateFinishFenceNV(const Context *context, FenceNVID fence)
5761 {
5762 if (!context->getExtensions().fenceNV)
5763 {
5764 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5765 return false;
5766 }
5767
5768 FenceNV *fenceObject = context->getFenceNV(fence);
5769
5770 if (fenceObject == nullptr)
5771 {
5772 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5773 return false;
5774 }
5775
5776 if (!fenceObject->isSet())
5777 {
5778 context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
5779 return false;
5780 }
5781
5782 return true;
5783 }
5784
ValidateGenFencesNV(const Context * context,GLsizei n,const FenceNVID * fences)5785 bool ValidateGenFencesNV(const Context *context, GLsizei n, const FenceNVID *fences)
5786 {
5787 if (!context->getExtensions().fenceNV)
5788 {
5789 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5790 return false;
5791 }
5792
5793 if (n < 0)
5794 {
5795 context->validationError(GL_INVALID_VALUE, kNegativeCount);
5796 return false;
5797 }
5798
5799 return true;
5800 }
5801
ValidateGetFenceivNV(const Context * context,FenceNVID fence,GLenum pname,const GLint * params)5802 bool ValidateGetFenceivNV(const Context *context,
5803 FenceNVID fence,
5804 GLenum pname,
5805 const GLint *params)
5806 {
5807 if (!context->getExtensions().fenceNV)
5808 {
5809 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5810 return false;
5811 }
5812
5813 FenceNV *fenceObject = context->getFenceNV(fence);
5814
5815 if (fenceObject == nullptr)
5816 {
5817 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5818 return false;
5819 }
5820
5821 if (!fenceObject->isSet())
5822 {
5823 context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
5824 return false;
5825 }
5826
5827 switch (pname)
5828 {
5829 case GL_FENCE_STATUS_NV:
5830 case GL_FENCE_CONDITION_NV:
5831 break;
5832
5833 default:
5834 context->validationError(GL_INVALID_ENUM, kInvalidPname);
5835 return false;
5836 }
5837
5838 return true;
5839 }
5840
ValidateGetGraphicsResetStatusEXT(const Context * context)5841 bool ValidateGetGraphicsResetStatusEXT(const Context *context)
5842 {
5843 if (!context->getExtensions().robustness)
5844 {
5845 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5846 return false;
5847 }
5848
5849 return true;
5850 }
5851
ValidateGetTranslatedShaderSourceANGLE(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * source)5852 bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
5853 ShaderProgramID shader,
5854 GLsizei bufsize,
5855 const GLsizei *length,
5856 const GLchar *source)
5857 {
5858 if (!context->getExtensions().translatedShaderSource)
5859 {
5860 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5861 return false;
5862 }
5863
5864 if (bufsize < 0)
5865 {
5866 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
5867 return false;
5868 }
5869
5870 Shader *shaderObject = context->getShader(shader);
5871
5872 if (!shaderObject)
5873 {
5874 context->validationError(GL_INVALID_OPERATION, kInvalidShaderName);
5875 return false;
5876 }
5877
5878 return true;
5879 }
5880
ValidateIsFenceNV(const Context * context,FenceNVID fence)5881 bool ValidateIsFenceNV(const Context *context, FenceNVID fence)
5882 {
5883 if (!context->getExtensions().fenceNV)
5884 {
5885 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5886 return false;
5887 }
5888
5889 return true;
5890 }
5891
ValidateSetFenceNV(const Context * context,FenceNVID fence,GLenum condition)5892 bool ValidateSetFenceNV(const Context *context, FenceNVID fence, GLenum condition)
5893 {
5894 if (!context->getExtensions().fenceNV)
5895 {
5896 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5897 return false;
5898 }
5899
5900 if (condition != GL_ALL_COMPLETED_NV)
5901 {
5902 context->validationError(GL_INVALID_ENUM, kInvalidFenceCondition);
5903 return false;
5904 }
5905
5906 FenceNV *fenceObject = context->getFenceNV(fence);
5907
5908 if (fenceObject == nullptr)
5909 {
5910 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5911 return false;
5912 }
5913
5914 return true;
5915 }
5916
ValidateTestFenceNV(const Context * context,FenceNVID fence)5917 bool ValidateTestFenceNV(const Context *context, FenceNVID fence)
5918 {
5919 if (!context->getExtensions().fenceNV)
5920 {
5921 context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5922 return false;
5923 }
5924
5925 FenceNV *fenceObject = context->getFenceNV(fence);
5926
5927 if (fenceObject == nullptr)
5928 {
5929 context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5930 return false;
5931 }
5932
5933 if (fenceObject->isSet() != GL_TRUE)
5934 {
5935 context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
5936 return false;
5937 }
5938
5939 return true;
5940 }
5941
ValidateTexStorage2DEXT(const Context * context,TextureType type,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)5942 bool ValidateTexStorage2DEXT(const Context *context,
5943 TextureType type,
5944 GLsizei levels,
5945 GLenum internalformat,
5946 GLsizei width,
5947 GLsizei height)
5948 {
5949 if (!context->getExtensions().textureStorage)
5950 {
5951 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5952 return false;
5953 }
5954
5955 if (context->getClientMajorVersion() < 3)
5956 {
5957 return ValidateES2TexStorageParametersBase(context, type, levels, internalformat, width,
5958 height);
5959 }
5960
5961 ASSERT(context->getClientMajorVersion() >= 3);
5962 return ValidateES3TexStorage2DParameters(context, type, levels, internalformat, width, height,
5963 1);
5964 }
5965
ValidateVertexAttribDivisorANGLE(const Context * context,GLuint index,GLuint divisor)5966 bool ValidateVertexAttribDivisorANGLE(const Context *context, GLuint index, GLuint divisor)
5967 {
5968 if (!context->getExtensions().instancedArraysANGLE)
5969 {
5970 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5971 return false;
5972 }
5973
5974 if (index >= MAX_VERTEX_ATTRIBS)
5975 {
5976 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
5977 return false;
5978 }
5979
5980 if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT)
5981 {
5982 if (index == 0 && divisor != 0)
5983 {
5984 context->validationError(GL_INVALID_OPERATION, kAttributeZeroRequiresDivisorLimitation);
5985
5986 // We also output an error message to the debugger window if tracing is active, so
5987 // that developers can see the error message.
5988 ERR() << kAttributeZeroRequiresDivisorLimitation;
5989 return false;
5990 }
5991 }
5992
5993 return true;
5994 }
5995
ValidateVertexAttribDivisorEXT(const Context * context,GLuint index,GLuint divisor)5996 bool ValidateVertexAttribDivisorEXT(const Context *context, GLuint index, GLuint divisor)
5997 {
5998 if (!context->getExtensions().instancedArraysEXT)
5999 {
6000 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6001 return false;
6002 }
6003
6004 if (index >= MAX_VERTEX_ATTRIBS)
6005 {
6006 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
6007 return false;
6008 }
6009
6010 return true;
6011 }
6012
ValidateTexImage3DOES(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)6013 bool ValidateTexImage3DOES(const Context *context,
6014 TextureTarget target,
6015 GLint level,
6016 GLenum internalformat,
6017 GLsizei width,
6018 GLsizei height,
6019 GLsizei depth,
6020 GLint border,
6021 GLenum format,
6022 GLenum type,
6023 const void *pixels)
6024 {
6025 return ValidateTexImage3D(context, target, level, internalformat, width, height, depth, border,
6026 format, type, pixels);
6027 }
6028
ValidatePopGroupMarkerEXT(const Context * context)6029 bool ValidatePopGroupMarkerEXT(const Context *context)
6030 {
6031 if (!context->getExtensions().debugMarker)
6032 {
6033 // The debug marker calls should not set error state
6034 // However, it seems reasonable to set an error state if the extension is not enabled
6035 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6036 return false;
6037 }
6038
6039 return true;
6040 }
6041
ValidateTexStorage1DEXT(const Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)6042 bool ValidateTexStorage1DEXT(const Context *context,
6043 GLenum target,
6044 GLsizei levels,
6045 GLenum internalformat,
6046 GLsizei width)
6047 {
6048 UNIMPLEMENTED();
6049 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6050 return false;
6051 }
6052
ValidateTexStorage3DEXT(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)6053 bool ValidateTexStorage3DEXT(const Context *context,
6054 TextureType target,
6055 GLsizei levels,
6056 GLenum internalformat,
6057 GLsizei width,
6058 GLsizei height,
6059 GLsizei depth)
6060 {
6061 if (!context->getExtensions().textureStorage)
6062 {
6063 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6064 return false;
6065 }
6066
6067 if (context->getClientMajorVersion() < 3)
6068 {
6069 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6070 return false;
6071 }
6072
6073 return ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
6074 depth);
6075 }
6076
ValidateMaxShaderCompilerThreadsKHR(const Context * context,GLuint count)6077 bool ValidateMaxShaderCompilerThreadsKHR(const Context *context, GLuint count)
6078 {
6079 if (!context->getExtensions().parallelShaderCompile)
6080 {
6081 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6082 return false;
6083 }
6084 return true;
6085 }
6086
ValidateMultiDrawArraysANGLE(const Context * context,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)6087 bool ValidateMultiDrawArraysANGLE(const Context *context,
6088 PrimitiveMode mode,
6089 const GLint *firsts,
6090 const GLsizei *counts,
6091 GLsizei drawcount)
6092 {
6093 if (!context->getExtensions().multiDraw)
6094 {
6095 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6096 return false;
6097 }
6098 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
6099 {
6100 if (!ValidateDrawArrays(context, mode, firsts[drawID], counts[drawID]))
6101 {
6102 return false;
6103 }
6104 }
6105 return true;
6106 }
6107
ValidateMultiDrawElementsANGLE(const Context * context,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)6108 bool ValidateMultiDrawElementsANGLE(const Context *context,
6109 PrimitiveMode mode,
6110 const GLsizei *counts,
6111 DrawElementsType type,
6112 const GLvoid *const *indices,
6113 GLsizei drawcount)
6114 {
6115 if (!context->getExtensions().multiDraw)
6116 {
6117 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6118 return false;
6119 }
6120 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
6121 {
6122 if (!ValidateDrawElements(context, mode, counts[drawID], type, indices[drawID]))
6123 {
6124 return false;
6125 }
6126 }
6127 return true;
6128 }
6129
ValidateProvokingVertexANGLE(const Context * context,ProvokingVertexConvention modePacked)6130 bool ValidateProvokingVertexANGLE(const Context *context, ProvokingVertexConvention modePacked)
6131 {
6132 if (!context->getExtensions().provokingVertex)
6133 {
6134 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6135 return false;
6136 }
6137
6138 switch (modePacked)
6139 {
6140 case ProvokingVertexConvention::FirstVertexConvention:
6141 case ProvokingVertexConvention::LastVertexConvention:
6142 break;
6143 default:
6144 context->validationError(GL_INVALID_ENUM, kInvalidProvokingVertex);
6145 return false;
6146 }
6147
6148 return true;
6149 }
6150
ValidateFramebufferTexture2DMultisampleEXT(const Context * context,GLenum target,GLenum attachment,TextureTarget textarget,TextureID texture,GLint level,GLsizei samples)6151 bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
6152 GLenum target,
6153 GLenum attachment,
6154 TextureTarget textarget,
6155 TextureID texture,
6156 GLint level,
6157 GLsizei samples)
6158 {
6159 if (!context->getExtensions().multisampledRenderToTexture)
6160 {
6161 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6162 return false;
6163 }
6164
6165 if (samples < 0)
6166 {
6167 return false;
6168 }
6169
6170 // EXT_multisampled_render_to_texture states that the value of samples
6171 // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
6172 // otherwise GL_INVALID_VALUE is generated.
6173 if (samples > context->getCaps().maxSamples)
6174 {
6175 context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
6176 return false;
6177 }
6178
6179 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
6180 {
6181 return false;
6182 }
6183
6184 // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than
6185 // the maximum sample number supported by this format is passed.
6186 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
6187 if (texture.value != 0 && context->getClientMajorVersion() >= 3)
6188 {
6189 Texture *tex = context->getTexture(texture);
6190 GLenum internalformat = tex->getFormat(textarget, level).info->internalFormat;
6191 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6192 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6193 {
6194 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
6195 return false;
6196 }
6197 }
6198
6199 // Unless EXT_multisampled_render_to_texture2 is enabled, only color attachment 0 can be used.
6200 if (!context->getExtensions().multisampledRenderToTexture2 &&
6201 attachment != GL_COLOR_ATTACHMENT0)
6202 {
6203 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
6204 return false;
6205 }
6206
6207 if (!ValidTexture2DDestinationTarget(context, textarget))
6208 {
6209 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6210 return false;
6211 }
6212
6213 return true;
6214 }
6215
ValidateRenderbufferStorageMultisampleEXT(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)6216 bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
6217 GLenum target,
6218 GLsizei samples,
6219 GLenum internalformat,
6220 GLsizei width,
6221 GLsizei height)
6222 {
6223 if (!context->getExtensions().multisampledRenderToTexture)
6224 {
6225 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6226 return false;
6227 }
6228 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
6229 height))
6230 {
6231 return false;
6232 }
6233
6234 // EXT_multisampled_render_to_texture states that the value of samples
6235 // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
6236 // otherwise GL_INVALID_VALUE is generated.
6237 if (samples > context->getCaps().maxSamples)
6238 {
6239 context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
6240 return false;
6241 }
6242
6243 // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create
6244 // the specified storage. This is different than ES 3.0 in which a sample number higher
6245 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
6246 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
6247 if (context->getClientMajorVersion() >= 3)
6248 {
6249 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6250 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6251 {
6252 context->validationError(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
6253 return false;
6254 }
6255 }
6256
6257 return true;
6258 }
6259
RecordBindTextureTypeError(const Context * context,TextureType target)6260 void RecordBindTextureTypeError(const Context *context, TextureType target)
6261 {
6262 ASSERT(!context->getStateCache().isValidBindTextureType(target));
6263
6264 switch (target)
6265 {
6266 case TextureType::Rectangle:
6267 ASSERT(!context->getExtensions().textureRectangle);
6268 context->validationError(GL_INVALID_ENUM, kTextureRectangleNotSupported);
6269 break;
6270
6271 case TextureType::_3D:
6272 case TextureType::_2DArray:
6273 ASSERT(context->getClientMajorVersion() < 3);
6274 context->validationError(GL_INVALID_ENUM, kES3Required);
6275 break;
6276
6277 case TextureType::_2DMultisample:
6278 ASSERT(context->getClientVersion() < Version(3, 1) &&
6279 !context->getExtensions().textureMultisample);
6280 context->validationError(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
6281 break;
6282
6283 case TextureType::_2DMultisampleArray:
6284 ASSERT(!context->getExtensions().textureStorageMultisample2DArrayOES);
6285 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
6286 break;
6287
6288 case TextureType::External:
6289 ASSERT(!context->getExtensions().eglImageExternalOES &&
6290 !context->getExtensions().eglStreamConsumerExternalNV);
6291 context->validationError(GL_INVALID_ENUM, kExternalTextureNotSupported);
6292 break;
6293
6294 case TextureType::VideoImage:
6295 ASSERT(!context->getExtensions().webglVideoTexture);
6296 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6297 break;
6298
6299 case TextureType::Buffer:
6300 ASSERT(!context->getExtensions().textureBufferOES &&
6301 !context->getExtensions().textureBufferEXT);
6302 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6303 break;
6304
6305 default:
6306 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6307 }
6308 }
6309
6310 } // namespace gl
6311