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