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