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