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