blob: 417502ad04c1983394e4dac46d9e7346e363b5ed [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// 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
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES2.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030010
11#include <cstdint>
12
Geoff Lange8ebe7f2013-08-05 15:03:13 -040013#include "common/mathutil.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040015#include "common/utilities.h"
Jamie Madillef300b12016-10-07 15:12:09 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Texture.h"
18#include "libANGLE/Framebuffer.h"
19#include "libANGLE/FramebufferAttachment.h"
20#include "libANGLE/Renderbuffer.h"
21#include "libANGLE/Shader.h"
22#include "libANGLE/Uniform.h"
23#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES.h"
25#include "libANGLE/validationES3.h"
Corentin Wallez0c7baf12016-12-19 15:43:10 -050026#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28namespace gl
29{
30
Jamie Madillc29968b2016-01-20 11:17:23 -050031namespace
32{
33
34bool IsPartialBlit(gl::Context *context,
35 const FramebufferAttachment *readBuffer,
36 const FramebufferAttachment *writeBuffer,
37 GLint srcX0,
38 GLint srcY0,
39 GLint srcX1,
40 GLint srcY1,
41 GLint dstX0,
42 GLint dstY0,
43 GLint dstX1,
44 GLint dstY1)
45{
46 const Extents &writeSize = writeBuffer->getSize();
47 const Extents &readSize = readBuffer->getSize();
48
49 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
50 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
51 {
52 return true;
53 }
54
Jamie Madilldfde6ab2016-06-09 07:07:18 -070055 if (context->getGLState().isScissorTestEnabled())
Jamie Madillc29968b2016-01-20 11:17:23 -050056 {
Jamie Madilldfde6ab2016-06-09 07:07:18 -070057 const Rectangle &scissor = context->getGLState().getScissor();
Jamie Madillc29968b2016-01-20 11:17:23 -050058 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
59 scissor.height < writeSize.height;
60 }
61
62 return false;
63}
64
Sami Väisänend59ca052016-06-21 16:10:00 +030065template <typename T>
66bool ValidatePathInstances(gl::Context *context,
67 GLsizei numPaths,
68 const void *paths,
69 GLuint pathBase)
70{
71 const auto *array = static_cast<const T *>(paths);
72
73 for (GLsizei i = 0; i < numPaths; ++i)
74 {
75 const GLuint pathName = array[i] + pathBase;
76 if (context->hasPath(pathName) && !context->hasPathData(pathName))
77 {
78 context->handleError(gl::Error(GL_INVALID_OPERATION, "No such path object."));
79 return false;
80 }
81 }
82 return true;
83}
84
85bool ValidateInstancedPathParameters(gl::Context *context,
86 GLsizei numPaths,
87 GLenum pathNameType,
88 const void *paths,
89 GLuint pathBase,
90 GLenum transformType,
91 const GLfloat *transformValues)
92{
93 if (!context->getExtensions().pathRendering)
94 {
95 context->handleError(
96 gl::Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
97 return false;
98 }
99
100 if (paths == nullptr)
101 {
102 context->handleError(gl::Error(GL_INVALID_VALUE, "No path name array."));
103 return false;
104 }
105
106 if (numPaths < 0)
107 {
108 context->handleError(gl::Error(GL_INVALID_VALUE, "Invalid (negative) numPaths."));
109 return false;
110 }
111
112 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
113 {
114 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in numPaths."));
115 return false;
116 }
117
118 std::uint32_t pathNameTypeSize = 0;
119 std::uint32_t componentCount = 0;
120
121 switch (pathNameType)
122 {
123 case GL_UNSIGNED_BYTE:
124 pathNameTypeSize = sizeof(GLubyte);
125 if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
126 return false;
127 break;
128
129 case GL_BYTE:
130 pathNameTypeSize = sizeof(GLbyte);
131 if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
132 return false;
133 break;
134
135 case GL_UNSIGNED_SHORT:
136 pathNameTypeSize = sizeof(GLushort);
137 if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
138 return false;
139 break;
140
141 case GL_SHORT:
142 pathNameTypeSize = sizeof(GLshort);
143 if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
144 return false;
145 break;
146
147 case GL_UNSIGNED_INT:
148 pathNameTypeSize = sizeof(GLuint);
149 if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
150 return false;
151 break;
152
153 case GL_INT:
154 pathNameTypeSize = sizeof(GLint);
155 if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
156 return false;
157 break;
158
159 default:
160 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid path name type."));
161 return false;
162 }
163
164 switch (transformType)
165 {
166 case GL_NONE:
167 componentCount = 0;
168 break;
169 case GL_TRANSLATE_X_CHROMIUM:
170 case GL_TRANSLATE_Y_CHROMIUM:
171 componentCount = 1;
172 break;
173 case GL_TRANSLATE_2D_CHROMIUM:
174 componentCount = 2;
175 break;
176 case GL_TRANSLATE_3D_CHROMIUM:
177 componentCount = 3;
178 break;
179 case GL_AFFINE_2D_CHROMIUM:
180 case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
181 componentCount = 6;
182 break;
183 case GL_AFFINE_3D_CHROMIUM:
184 case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
185 componentCount = 12;
186 break;
187 default:
188 context->handleError(gl::Error(GL_INVALID_ENUM, "Invalid transformation."));
189 return false;
190 }
191 if (componentCount != 0 && transformValues == nullptr)
192 {
193 context->handleError(gl::Error(GL_INVALID_VALUE, "No transform array given."));
194 return false;
195 }
196
197 angle::CheckedNumeric<std::uint32_t> checkedSize(0);
198 checkedSize += (numPaths * pathNameTypeSize);
199 checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
200 if (!checkedSize.IsValid())
201 {
202 context->handleError(gl::Error(GL_INVALID_OPERATION, "Overflow in num paths."));
203 return false;
204 }
205
206 return true;
207}
208
Geoff Lang97073d12016-04-20 10:42:34 -0700209bool IsValidCopyTextureFormat(Context *context, GLenum internalFormat)
210{
Geoff Langca271392017-04-05 12:30:00 -0400211 switch (GetUnsizedFormat(internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -0700212 {
213 case GL_ALPHA:
214 case GL_LUMINANCE:
215 case GL_LUMINANCE_ALPHA:
216 case GL_RGB:
217 case GL_RGBA:
218 return true;
219
220 case GL_RED:
221 return context->getClientMajorVersion() >= 3 || context->getExtensions().textureRG;
222
223 case GL_BGRA_EXT:
224 return context->getExtensions().textureFormatBGRA8888;
225
226 default:
227 return false;
228 }
229}
230
231bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
232{
233 switch (internalFormat)
234 {
235 case GL_RGB:
236 case GL_RGBA:
237 break;
238
239 case GL_BGRA_EXT:
240 return context->getExtensions().textureFormatBGRA8888;
241
242 default:
243 return false;
244 }
245
246 switch (type)
247 {
248 case GL_UNSIGNED_BYTE:
249 break;
250
251 default:
252 return false;
253 }
254
255 return true;
256}
257
258bool IsValidCopyTextureDestinationTarget(Context *context, GLenum target)
259{
260 switch (target)
261 {
262 case GL_TEXTURE_2D:
263 return true;
264
265 // TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
266 // supported
267
268 default:
269 return false;
270 }
271}
272
273bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
274{
275 if (IsValidCopyTextureDestinationTarget(context, target))
276 {
277 return true;
278 }
279
280 // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
281 // supported
282
283 return false;
284}
285
Jamie Madillc1d770e2017-04-13 17:31:24 -0400286bool IsValidStencilFunc(GLenum func)
287{
288 switch (func)
289 {
290 case GL_NEVER:
291 case GL_ALWAYS:
292 case GL_LESS:
293 case GL_LEQUAL:
294 case GL_EQUAL:
295 case GL_GEQUAL:
296 case GL_GREATER:
297 case GL_NOTEQUAL:
298 return true;
299
300 default:
301 return false;
302 }
303}
304
305bool IsValidStencilFace(GLenum face)
306{
307 switch (face)
308 {
309 case GL_FRONT:
310 case GL_BACK:
311 case GL_FRONT_AND_BACK:
312 return true;
313
314 default:
315 return false;
316 }
317}
318
319bool IsValidStencilOp(GLenum op)
320{
321 switch (op)
322 {
323 case GL_ZERO:
324 case GL_KEEP:
325 case GL_REPLACE:
326 case GL_INCR:
327 case GL_DECR:
328 case GL_INVERT:
329 case GL_INCR_WRAP:
330 case GL_DECR_WRAP:
331 return true;
332
333 default:
334 return false;
335 }
336}
337
Jamie Madillbe849e42017-05-02 15:49:00 -0400338bool ValidateES2CopyTexImageParameters(ValidationContext *context,
339 GLenum target,
340 GLint level,
341 GLenum internalformat,
342 bool isSubImage,
343 GLint xoffset,
344 GLint yoffset,
345 GLint x,
346 GLint y,
347 GLsizei width,
348 GLsizei height,
349 GLint border)
350{
351 if (!ValidTexture2DDestinationTarget(context, target))
352 {
353 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
354 return false;
355 }
356
357 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
358 {
359 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
360 return false;
361 }
362
363 Format textureFormat = Format::Invalid();
364 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
365 xoffset, yoffset, 0, x, y, width, height, border,
366 &textureFormat))
367 {
368 return false;
369 }
370
371 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
372 GLenum colorbufferFormat =
373 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
374 const auto &formatInfo = *textureFormat.info;
375
376 // [OpenGL ES 2.0.24] table 3.9
377 if (isSubImage)
378 {
379 switch (formatInfo.format)
380 {
381 case GL_ALPHA:
382 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
383 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
384 {
385 context->handleError(Error(GL_INVALID_OPERATION));
386 return false;
387 }
388 break;
389 case GL_LUMINANCE:
390 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
391 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
392 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
393 colorbufferFormat != GL_RGBA8_OES)
394 {
395 context->handleError(Error(GL_INVALID_OPERATION));
396 return false;
397 }
398 break;
399 case GL_RED_EXT:
400 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
401 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
402 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
403 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
404 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
405 colorbufferFormat != GL_RGBA32F)
406 {
407 context->handleError(Error(GL_INVALID_OPERATION));
408 return false;
409 }
410 break;
411 case GL_RG_EXT:
412 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
413 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
414 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
415 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
416 colorbufferFormat != GL_RGBA32F)
417 {
418 context->handleError(Error(GL_INVALID_OPERATION));
419 return false;
420 }
421 break;
422 case GL_RGB:
423 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
424 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
425 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
426 colorbufferFormat != GL_RGBA32F)
427 {
428 context->handleError(Error(GL_INVALID_OPERATION));
429 return false;
430 }
431 break;
432 case GL_LUMINANCE_ALPHA:
433 case GL_RGBA:
434 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
435 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
436 {
437 context->handleError(Error(GL_INVALID_OPERATION));
438 return false;
439 }
440 break;
441 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
442 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
443 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
444 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
445 case GL_ETC1_RGB8_OES:
446 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
447 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
448 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
449 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
450 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
451 context->handleError(Error(GL_INVALID_OPERATION));
452 return false;
453 case GL_DEPTH_COMPONENT:
454 case GL_DEPTH_STENCIL_OES:
455 context->handleError(Error(GL_INVALID_OPERATION));
456 return false;
457 default:
458 context->handleError(Error(GL_INVALID_OPERATION));
459 return false;
460 }
461
462 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
463 {
464 context->handleError(Error(GL_INVALID_OPERATION));
465 return false;
466 }
467 }
468 else
469 {
470 switch (internalformat)
471 {
472 case GL_ALPHA:
473 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
474 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
475 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
476 {
477 context->handleError(Error(GL_INVALID_OPERATION));
478 return false;
479 }
480 break;
481 case GL_LUMINANCE:
482 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
483 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
484 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
485 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
486 colorbufferFormat != GL_BGR5_A1_ANGLEX)
487 {
488 context->handleError(Error(GL_INVALID_OPERATION));
489 return false;
490 }
491 break;
492 case GL_RED_EXT:
493 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
494 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
495 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
496 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
497 colorbufferFormat != GL_BGR5_A1_ANGLEX)
498 {
499 context->handleError(Error(GL_INVALID_OPERATION));
500 return false;
501 }
502 break;
503 case GL_RG_EXT:
504 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
505 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
506 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
507 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
508 {
509 context->handleError(Error(GL_INVALID_OPERATION));
510 return false;
511 }
512 break;
513 case GL_RGB:
514 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
515 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
516 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
517 colorbufferFormat != GL_BGR5_A1_ANGLEX)
518 {
519 context->handleError(Error(GL_INVALID_OPERATION));
520 return false;
521 }
522 break;
523 case GL_LUMINANCE_ALPHA:
524 case GL_RGBA:
525 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
526 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
527 colorbufferFormat != GL_BGR5_A1_ANGLEX)
528 {
529 context->handleError(Error(GL_INVALID_OPERATION));
530 return false;
531 }
532 break;
533 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
534 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
535 if (context->getExtensions().textureCompressionDXT1)
536 {
537 context->handleError(Error(GL_INVALID_OPERATION));
538 return false;
539 }
540 else
541 {
542 context->handleError(Error(GL_INVALID_ENUM));
543 return false;
544 }
545 break;
546 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
547 if (context->getExtensions().textureCompressionDXT3)
548 {
549 context->handleError(Error(GL_INVALID_OPERATION));
550 return false;
551 }
552 else
553 {
554 context->handleError(Error(GL_INVALID_ENUM));
555 return false;
556 }
557 break;
558 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
559 if (context->getExtensions().textureCompressionDXT5)
560 {
561 context->handleError(Error(GL_INVALID_OPERATION));
562 return false;
563 }
564 else
565 {
566 context->handleError(Error(GL_INVALID_ENUM));
567 return false;
568 }
569 break;
570 case GL_ETC1_RGB8_OES:
571 if (context->getExtensions().compressedETC1RGB8Texture)
572 {
573 context->handleError(Error(GL_INVALID_OPERATION));
574 return false;
575 }
576 else
577 {
578 context->handleError(Error(GL_INVALID_ENUM));
579 return false;
580 }
581 break;
582 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
583 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
584 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
585 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
586 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
587 if (context->getExtensions().lossyETCDecode)
588 {
589 context->handleError(Error(GL_INVALID_OPERATION,
590 "ETC lossy decode formats can't be copied to."));
591 return false;
592 }
593 else
594 {
595 context->handleError(Error(
596 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
597 return false;
598 }
599 break;
600 case GL_DEPTH_COMPONENT:
601 case GL_DEPTH_COMPONENT16:
602 case GL_DEPTH_COMPONENT32_OES:
603 case GL_DEPTH_STENCIL_OES:
604 case GL_DEPTH24_STENCIL8_OES:
605 if (context->getExtensions().depthTextures)
606 {
607 context->handleError(Error(GL_INVALID_OPERATION));
608 return false;
609 }
610 else
611 {
612 context->handleError(Error(GL_INVALID_ENUM));
613 return false;
614 }
615 default:
616 context->handleError(Error(GL_INVALID_ENUM));
617 return false;
618 }
619 }
620
621 // If width or height is zero, it is a no-op. Return false without setting an error.
622 return (width > 0 && height > 0);
623}
624
625bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
626{
627 switch (cap)
628 {
629 // EXT_multisample_compatibility
630 case GL_MULTISAMPLE_EXT:
631 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
632 return context->getExtensions().multisampleCompatibility;
633
634 case GL_CULL_FACE:
635 case GL_POLYGON_OFFSET_FILL:
636 case GL_SAMPLE_ALPHA_TO_COVERAGE:
637 case GL_SAMPLE_COVERAGE:
638 case GL_SCISSOR_TEST:
639 case GL_STENCIL_TEST:
640 case GL_DEPTH_TEST:
641 case GL_BLEND:
642 case GL_DITHER:
643 return true;
644
645 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
646 case GL_RASTERIZER_DISCARD:
647 return (context->getClientMajorVersion() >= 3);
648
649 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
650 case GL_DEBUG_OUTPUT:
651 return context->getExtensions().debug;
652
653 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
654 return queryOnly && context->getExtensions().bindGeneratesResource;
655
656 case GL_CLIENT_ARRAYS_ANGLE:
657 return queryOnly && context->getExtensions().clientArrays;
658
659 case GL_FRAMEBUFFER_SRGB_EXT:
660 return context->getExtensions().sRGBWriteControl;
661
662 case GL_SAMPLE_MASK:
663 return context->getClientVersion() >= Version(3, 1);
664
665 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
666 return queryOnly && context->getExtensions().robustResourceInitialization;
667
668 default:
669 return false;
670 }
671}
672
Jamie Madillc29968b2016-01-20 11:17:23 -0500673} // anonymous namespace
674
Geoff Langff5b2d52016-09-07 11:32:23 -0400675bool ValidateES2TexImageParameters(Context *context,
676 GLenum target,
677 GLint level,
678 GLenum internalformat,
679 bool isCompressed,
680 bool isSubImage,
681 GLint xoffset,
682 GLint yoffset,
683 GLsizei width,
684 GLsizei height,
685 GLint border,
686 GLenum format,
687 GLenum type,
688 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400689 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400690{
Jamie Madill6f38f822014-06-06 17:12:20 -0400691 if (!ValidTexture2DDestinationTarget(context, target))
692 {
Jamie Madill437fa652016-05-03 15:13:24 -0400693 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400694 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400695 }
696
Austin Kinross08528e12015-10-07 16:24:40 -0700697 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400698 {
Jamie Madill437fa652016-05-03 15:13:24 -0400699 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400700 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400701 }
702
He Yunchaoced53ae2016-11-29 15:00:51 +0800703 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400704 std::numeric_limits<GLsizei>::max() - yoffset < height)
705 {
Jamie Madill437fa652016-05-03 15:13:24 -0400706 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400707 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400708 }
709
Geoff Lang005df412013-10-16 14:12:50 -0400710 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400711 {
Jamie Madill437fa652016-05-03 15:13:24 -0400712 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400713 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400714 }
715
Geoff Langaae65a42014-05-26 12:43:44 -0400716 const gl::Caps &caps = context->getCaps();
717
Geoff Langa9be0dc2014-12-17 12:34:40 -0500718 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400719 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500720 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
721 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400722 {
Jamie Madill437fa652016-05-03 15:13:24 -0400723 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500726 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500727 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500728 {
729 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400730 {
Jamie Madill437fa652016-05-03 15:13:24 -0400731 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500732 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400733 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400734
Geoff Langa9be0dc2014-12-17 12:34:40 -0500735 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
736 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
737 {
Jamie Madill437fa652016-05-03 15:13:24 -0400738 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500739 return false;
740 }
741 }
742 else
743 {
Jamie Madill437fa652016-05-03 15:13:24 -0400744 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400745 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400746 }
747
He Yunchaoced53ae2016-11-29 15:00:51 +0800748 gl::Texture *texture =
749 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400750 if (!texture)
751 {
Jamie Madill437fa652016-05-03 15:13:24 -0400752 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400753 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754 }
755
Geoff Langa9be0dc2014-12-17 12:34:40 -0500756 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400757 {
Geoff Langca271392017-04-05 12:30:00 -0400758 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
759 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500760 {
761 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
762 return false;
763 }
764
Geoff Langa9be0dc2014-12-17 12:34:40 -0500765 if (format != GL_NONE)
766 {
Geoff Langca271392017-04-05 12:30:00 -0400767 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
768 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500769 {
Jamie Madill437fa652016-05-03 15:13:24 -0400770 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500771 return false;
772 }
773 }
774
775 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
776 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
777 {
Jamie Madill437fa652016-05-03 15:13:24 -0400778 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500779 return false;
780 }
781 }
782 else
783 {
Geoff Lang69cce582015-09-17 13:20:36 -0400784 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500785 {
Jamie Madill437fa652016-05-03 15:13:24 -0400786 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500787 return false;
788 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 }
790
791 // Verify zero border
792 if (border != 0)
793 {
Jamie Madill437fa652016-05-03 15:13:24 -0400794 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400796 }
797
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 if (isCompressed)
799 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400800 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400801 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
802 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400803 switch (actualInternalFormat)
804 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800805 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
806 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
807 if (!context->getExtensions().textureCompressionDXT1)
808 {
809 context->handleError(Error(GL_INVALID_ENUM));
810 return false;
811 }
812 break;
813 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
814 if (!context->getExtensions().textureCompressionDXT1)
815 {
816 context->handleError(Error(GL_INVALID_ENUM));
817 return false;
818 }
819 break;
820 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
821 if (!context->getExtensions().textureCompressionDXT5)
822 {
823 context->handleError(Error(GL_INVALID_ENUM));
824 return false;
825 }
826 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800827 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
828 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
829 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
830 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
831 if (!context->getExtensions().textureCompressionS3TCsRGB)
832 {
833 context->handleError(Error(GL_INVALID_ENUM));
834 return false;
835 }
836 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800837 case GL_ETC1_RGB8_OES:
838 if (!context->getExtensions().compressedETC1RGB8Texture)
839 {
840 context->handleError(Error(GL_INVALID_ENUM));
841 return false;
842 }
843 break;
844 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800845 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
846 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
847 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
848 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800849 if (!context->getExtensions().lossyETCDecode)
850 {
851 context->handleError(Error(
852 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
853 return false;
854 }
855 break;
856 default:
857 context->handleError(
858 Error(GL_INVALID_ENUM,
859 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400860 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400861 }
Geoff Lang966c9402017-04-18 12:38:27 -0400862
863 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -0400864 {
Geoff Lang966c9402017-04-18 12:38:27 -0400865 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
866 height, texture->getWidth(target, level),
867 texture->getHeight(target, level)))
868 {
869 context->handleError(
870 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
871 return false;
872 }
873
874 if (format != actualInternalFormat)
875 {
876 context->handleError(Error(
877 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
878 return false;
879 }
880 }
881 else
882 {
883 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
884 {
885 context->handleError(
886 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
887 return false;
888 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400889 }
890 }
891 else
892 {
893 // validate <type> by itself (used as secondary key below)
894 switch (type)
895 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800896 case GL_UNSIGNED_BYTE:
897 case GL_UNSIGNED_SHORT_5_6_5:
898 case GL_UNSIGNED_SHORT_4_4_4_4:
899 case GL_UNSIGNED_SHORT_5_5_5_1:
900 case GL_UNSIGNED_SHORT:
901 case GL_UNSIGNED_INT:
902 case GL_UNSIGNED_INT_24_8_OES:
903 case GL_HALF_FLOAT_OES:
904 case GL_FLOAT:
905 break;
906 default:
907 context->handleError(Error(GL_INVALID_ENUM));
908 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400909 }
910
911 // validate <format> + <type> combinations
912 // - invalid <format> -> sets INVALID_ENUM
913 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
914 switch (format)
915 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800916 case GL_ALPHA:
917 case GL_LUMINANCE:
918 case GL_LUMINANCE_ALPHA:
919 switch (type)
920 {
921 case GL_UNSIGNED_BYTE:
922 case GL_FLOAT:
923 case GL_HALF_FLOAT_OES:
924 break;
925 default:
926 context->handleError(Error(GL_INVALID_OPERATION));
927 return false;
928 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400929 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800930 case GL_RED:
931 case GL_RG:
932 if (!context->getExtensions().textureRG)
933 {
934 context->handleError(Error(GL_INVALID_ENUM));
935 return false;
936 }
937 switch (type)
938 {
939 case GL_UNSIGNED_BYTE:
940 case GL_FLOAT:
941 case GL_HALF_FLOAT_OES:
942 break;
943 default:
944 context->handleError(Error(GL_INVALID_OPERATION));
945 return false;
946 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 case GL_RGB:
949 switch (type)
950 {
951 case GL_UNSIGNED_BYTE:
952 case GL_UNSIGNED_SHORT_5_6_5:
953 case GL_FLOAT:
954 case GL_HALF_FLOAT_OES:
955 break;
956 default:
957 context->handleError(Error(GL_INVALID_OPERATION));
958 return false;
959 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800961 case GL_RGBA:
962 switch (type)
963 {
964 case GL_UNSIGNED_BYTE:
965 case GL_UNSIGNED_SHORT_4_4_4_4:
966 case GL_UNSIGNED_SHORT_5_5_5_1:
967 case GL_FLOAT:
968 case GL_HALF_FLOAT_OES:
969 break;
970 default:
971 context->handleError(Error(GL_INVALID_OPERATION));
972 return false;
973 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400974 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800975 case GL_BGRA_EXT:
976 switch (type)
977 {
978 case GL_UNSIGNED_BYTE:
979 break;
980 default:
981 context->handleError(Error(GL_INVALID_OPERATION));
982 return false;
983 }
984 break;
985 case GL_SRGB_EXT:
986 case GL_SRGB_ALPHA_EXT:
987 if (!context->getExtensions().sRGB)
988 {
989 context->handleError(Error(GL_INVALID_ENUM));
990 return false;
991 }
992 switch (type)
993 {
994 case GL_UNSIGNED_BYTE:
995 break;
996 default:
997 context->handleError(Error(GL_INVALID_OPERATION));
998 return false;
999 }
1000 break;
1001 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1002 // handled below
1003 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1004 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1005 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1006 break;
1007 case GL_DEPTH_COMPONENT:
1008 switch (type)
1009 {
1010 case GL_UNSIGNED_SHORT:
1011 case GL_UNSIGNED_INT:
1012 break;
1013 default:
1014 context->handleError(Error(GL_INVALID_OPERATION));
1015 return false;
1016 }
1017 break;
1018 case GL_DEPTH_STENCIL_OES:
1019 switch (type)
1020 {
1021 case GL_UNSIGNED_INT_24_8_OES:
1022 break;
1023 default:
1024 context->handleError(Error(GL_INVALID_OPERATION));
1025 return false;
1026 }
1027 break;
1028 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001029 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001030 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001031 }
1032
1033 switch (format)
1034 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1036 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1037 if (context->getExtensions().textureCompressionDXT1)
1038 {
1039 context->handleError(Error(GL_INVALID_OPERATION));
1040 return false;
1041 }
1042 else
1043 {
1044 context->handleError(Error(GL_INVALID_ENUM));
1045 return false;
1046 }
1047 break;
1048 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1049 if (context->getExtensions().textureCompressionDXT3)
1050 {
1051 context->handleError(Error(GL_INVALID_OPERATION));
1052 return false;
1053 }
1054 else
1055 {
1056 context->handleError(Error(GL_INVALID_ENUM));
1057 return false;
1058 }
1059 break;
1060 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1061 if (context->getExtensions().textureCompressionDXT5)
1062 {
1063 context->handleError(Error(GL_INVALID_OPERATION));
1064 return false;
1065 }
1066 else
1067 {
1068 context->handleError(Error(GL_INVALID_ENUM));
1069 return false;
1070 }
1071 break;
1072 case GL_ETC1_RGB8_OES:
1073 if (context->getExtensions().compressedETC1RGB8Texture)
1074 {
1075 context->handleError(Error(GL_INVALID_OPERATION));
1076 return false;
1077 }
1078 else
1079 {
1080 context->handleError(Error(GL_INVALID_ENUM));
1081 return false;
1082 }
1083 break;
1084 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001085 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1086 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1087 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1088 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 if (context->getExtensions().lossyETCDecode)
1090 {
1091 context->handleError(
1092 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -08001093 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +08001094 return false;
1095 }
1096 else
1097 {
1098 context->handleError(Error(
1099 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1100 return false;
1101 }
1102 break;
1103 case GL_DEPTH_COMPONENT:
1104 case GL_DEPTH_STENCIL_OES:
1105 if (!context->getExtensions().depthTextures)
1106 {
1107 context->handleError(Error(GL_INVALID_VALUE));
1108 return false;
1109 }
1110 if (target != GL_TEXTURE_2D)
1111 {
1112 context->handleError(Error(GL_INVALID_OPERATION));
1113 return false;
1114 }
1115 // OES_depth_texture supports loading depth data and multiple levels,
1116 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001117 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 {
1119 context->handleError(Error(GL_INVALID_OPERATION));
1120 return false;
1121 }
1122 break;
1123 default:
1124 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 }
1126
1127 if (type == GL_FLOAT)
1128 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001129 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001130 {
Jamie Madill437fa652016-05-03 15:13:24 -04001131 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001132 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 }
1134 }
1135 else if (type == GL_HALF_FLOAT_OES)
1136 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001137 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 {
Jamie Madill437fa652016-05-03 15:13:24 -04001139 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001140 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 }
1142 }
1143 }
1144
Geoff Langff5b2d52016-09-07 11:32:23 -04001145 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
1146 imageSize))
1147 {
1148 return false;
1149 }
1150
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 return true;
1152}
1153
He Yunchaoced53ae2016-11-29 15:00:51 +08001154bool ValidateES2TexStorageParameters(Context *context,
1155 GLenum target,
1156 GLsizei levels,
1157 GLenum internalformat,
1158 GLsizei width,
1159 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160{
1161 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1162 {
Jamie Madill437fa652016-05-03 15:13:24 -04001163 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 }
1166
1167 if (width < 1 || height < 1 || levels < 1)
1168 {
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001171 }
1172
1173 if (target == GL_TEXTURE_CUBE_MAP && width != height)
1174 {
Jamie Madill437fa652016-05-03 15:13:24 -04001175 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001176 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001177 }
1178
1179 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1180 {
Jamie Madill437fa652016-05-03 15:13:24 -04001181 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001182 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183 }
1184
Geoff Langca271392017-04-05 12:30:00 -04001185 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001186 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001187 {
Jamie Madill437fa652016-05-03 15:13:24 -04001188 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001189 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001190 }
1191
Geoff Langaae65a42014-05-26 12:43:44 -04001192 const gl::Caps &caps = context->getCaps();
1193
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001194 switch (target)
1195 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001196 case GL_TEXTURE_2D:
1197 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1198 static_cast<GLuint>(height) > caps.max2DTextureSize)
1199 {
1200 context->handleError(Error(GL_INVALID_VALUE));
1201 return false;
1202 }
1203 break;
1204 case GL_TEXTURE_CUBE_MAP:
1205 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1206 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1207 {
1208 context->handleError(Error(GL_INVALID_VALUE));
1209 return false;
1210 }
1211 break;
1212 default:
1213 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215 }
1216
Geoff Langc0b9ef42014-07-02 10:02:37 -04001217 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001218 {
1219 if (!gl::isPow2(width) || !gl::isPow2(height))
1220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224 }
1225
1226 switch (internalformat)
1227 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001228 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1229 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1230 if (!context->getExtensions().textureCompressionDXT1)
1231 {
1232 context->handleError(Error(GL_INVALID_ENUM));
1233 return false;
1234 }
1235 break;
1236 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1237 if (!context->getExtensions().textureCompressionDXT3)
1238 {
1239 context->handleError(Error(GL_INVALID_ENUM));
1240 return false;
1241 }
1242 break;
1243 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1244 if (!context->getExtensions().textureCompressionDXT5)
1245 {
1246 context->handleError(Error(GL_INVALID_ENUM));
1247 return false;
1248 }
1249 break;
1250 case GL_ETC1_RGB8_OES:
1251 if (!context->getExtensions().compressedETC1RGB8Texture)
1252 {
1253 context->handleError(Error(GL_INVALID_ENUM));
1254 return false;
1255 }
1256 break;
1257 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001258 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1259 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1260 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1261 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001262 if (!context->getExtensions().lossyETCDecode)
1263 {
1264 context->handleError(
1265 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1266 return false;
1267 }
1268 break;
1269 case GL_RGBA32F_EXT:
1270 case GL_RGB32F_EXT:
1271 case GL_ALPHA32F_EXT:
1272 case GL_LUMINANCE32F_EXT:
1273 case GL_LUMINANCE_ALPHA32F_EXT:
1274 if (!context->getExtensions().textureFloat)
1275 {
1276 context->handleError(Error(GL_INVALID_ENUM));
1277 return false;
1278 }
1279 break;
1280 case GL_RGBA16F_EXT:
1281 case GL_RGB16F_EXT:
1282 case GL_ALPHA16F_EXT:
1283 case GL_LUMINANCE16F_EXT:
1284 case GL_LUMINANCE_ALPHA16F_EXT:
1285 if (!context->getExtensions().textureHalfFloat)
1286 {
1287 context->handleError(Error(GL_INVALID_ENUM));
1288 return false;
1289 }
1290 break;
1291 case GL_R8_EXT:
1292 case GL_RG8_EXT:
1293 case GL_R16F_EXT:
1294 case GL_RG16F_EXT:
1295 case GL_R32F_EXT:
1296 case GL_RG32F_EXT:
1297 if (!context->getExtensions().textureRG)
1298 {
1299 context->handleError(Error(GL_INVALID_ENUM));
1300 return false;
1301 }
1302 break;
1303 case GL_DEPTH_COMPONENT16:
1304 case GL_DEPTH_COMPONENT32_OES:
1305 case GL_DEPTH24_STENCIL8_OES:
1306 if (!context->getExtensions().depthTextures)
1307 {
1308 context->handleError(Error(GL_INVALID_ENUM));
1309 return false;
1310 }
1311 if (target != GL_TEXTURE_2D)
1312 {
1313 context->handleError(Error(GL_INVALID_OPERATION));
1314 return false;
1315 }
1316 // ANGLE_depth_texture only supports 1-level textures
1317 if (levels != 1)
1318 {
1319 context->handleError(Error(GL_INVALID_OPERATION));
1320 return false;
1321 }
1322 break;
1323 default:
1324 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 }
1326
Geoff Lang691e58c2014-12-19 17:03:25 -05001327 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 if (!texture || texture->id() == 0)
1329 {
Jamie Madill437fa652016-05-03 15:13:24 -04001330 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001331 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 }
1333
Geoff Lang69cce582015-09-17 13:20:36 -04001334 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 {
Jamie Madill437fa652016-05-03 15:13:24 -04001336 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 }
1339
1340 return true;
1341}
1342
He Yunchaoced53ae2016-11-29 15:00:51 +08001343bool ValidateDiscardFramebufferEXT(Context *context,
1344 GLenum target,
1345 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001346 const GLenum *attachments)
1347{
Jamie Madillc29968b2016-01-20 11:17:23 -05001348 if (!context->getExtensions().discardFramebuffer)
1349 {
Jamie Madill437fa652016-05-03 15:13:24 -04001350 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001351 return false;
1352 }
1353
Austin Kinross08332632015-05-05 13:35:47 -07001354 bool defaultFramebuffer = false;
1355
1356 switch (target)
1357 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001358 case GL_FRAMEBUFFER:
1359 defaultFramebuffer =
1360 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1361 break;
1362 default:
1363 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1364 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001365 }
1366
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1368 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001369}
1370
Austin Kinrossbc781f32015-10-26 09:27:38 -07001371bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1372{
1373 if (!context->getExtensions().vertexArrayObject)
1374 {
Jamie Madill437fa652016-05-03 15:13:24 -04001375 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001376 return false;
1377 }
1378
1379 return ValidateBindVertexArrayBase(context, array);
1380}
1381
1382bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1383{
1384 if (!context->getExtensions().vertexArrayObject)
1385 {
Jamie Madill437fa652016-05-03 15:13:24 -04001386 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001387 return false;
1388 }
1389
Olli Etuaho41997e72016-03-10 13:38:39 +02001390 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001391}
1392
1393bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1394{
1395 if (!context->getExtensions().vertexArrayObject)
1396 {
Jamie Madill437fa652016-05-03 15:13:24 -04001397 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001398 return false;
1399 }
1400
Olli Etuaho41997e72016-03-10 13:38:39 +02001401 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001402}
1403
1404bool ValidateIsVertexArrayOES(Context *context)
1405{
1406 if (!context->getExtensions().vertexArrayObject)
1407 {
Jamie Madill437fa652016-05-03 15:13:24 -04001408 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001409 return false;
1410 }
1411
1412 return true;
1413}
Geoff Langc5629752015-12-07 16:29:04 -05001414
1415bool ValidateProgramBinaryOES(Context *context,
1416 GLuint program,
1417 GLenum binaryFormat,
1418 const void *binary,
1419 GLint length)
1420{
1421 if (!context->getExtensions().getProgramBinary)
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001424 return false;
1425 }
1426
1427 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1428}
1429
1430bool ValidateGetProgramBinaryOES(Context *context,
1431 GLuint program,
1432 GLsizei bufSize,
1433 GLsizei *length,
1434 GLenum *binaryFormat,
1435 void *binary)
1436{
1437 if (!context->getExtensions().getProgramBinary)
1438 {
Jamie Madill437fa652016-05-03 15:13:24 -04001439 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001440 return false;
1441 }
1442
1443 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1444}
Geoff Lange102fee2015-12-10 11:23:30 -05001445
Geoff Lang70d0f492015-12-10 17:45:46 -05001446static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1447{
1448 switch (source)
1449 {
1450 case GL_DEBUG_SOURCE_API:
1451 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1452 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1453 case GL_DEBUG_SOURCE_OTHER:
1454 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1455 return !mustBeThirdPartyOrApplication;
1456
1457 case GL_DEBUG_SOURCE_THIRD_PARTY:
1458 case GL_DEBUG_SOURCE_APPLICATION:
1459 return true;
1460
1461 default:
1462 return false;
1463 }
1464}
1465
1466static bool ValidDebugType(GLenum type)
1467{
1468 switch (type)
1469 {
1470 case GL_DEBUG_TYPE_ERROR:
1471 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1472 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1473 case GL_DEBUG_TYPE_PERFORMANCE:
1474 case GL_DEBUG_TYPE_PORTABILITY:
1475 case GL_DEBUG_TYPE_OTHER:
1476 case GL_DEBUG_TYPE_MARKER:
1477 case GL_DEBUG_TYPE_PUSH_GROUP:
1478 case GL_DEBUG_TYPE_POP_GROUP:
1479 return true;
1480
1481 default:
1482 return false;
1483 }
1484}
1485
1486static bool ValidDebugSeverity(GLenum severity)
1487{
1488 switch (severity)
1489 {
1490 case GL_DEBUG_SEVERITY_HIGH:
1491 case GL_DEBUG_SEVERITY_MEDIUM:
1492 case GL_DEBUG_SEVERITY_LOW:
1493 case GL_DEBUG_SEVERITY_NOTIFICATION:
1494 return true;
1495
1496 default:
1497 return false;
1498 }
1499}
1500
Geoff Lange102fee2015-12-10 11:23:30 -05001501bool ValidateDebugMessageControlKHR(Context *context,
1502 GLenum source,
1503 GLenum type,
1504 GLenum severity,
1505 GLsizei count,
1506 const GLuint *ids,
1507 GLboolean enabled)
1508{
1509 if (!context->getExtensions().debug)
1510 {
Jamie Madill437fa652016-05-03 15:13:24 -04001511 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001512 return false;
1513 }
1514
Geoff Lang70d0f492015-12-10 17:45:46 -05001515 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1516 {
Jamie Madill437fa652016-05-03 15:13:24 -04001517 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001518 return false;
1519 }
1520
1521 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1522 {
Jamie Madill437fa652016-05-03 15:13:24 -04001523 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001524 return false;
1525 }
1526
1527 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001530 return false;
1531 }
1532
1533 if (count > 0)
1534 {
1535 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001538 GL_INVALID_OPERATION,
1539 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1540 return false;
1541 }
1542
1543 if (severity != GL_DONT_CARE)
1544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001546 Error(GL_INVALID_OPERATION,
1547 "If count is greater than zero, severity must be GL_DONT_CARE."));
1548 return false;
1549 }
1550 }
1551
Geoff Lange102fee2015-12-10 11:23:30 -05001552 return true;
1553}
1554
1555bool ValidateDebugMessageInsertKHR(Context *context,
1556 GLenum source,
1557 GLenum type,
1558 GLuint id,
1559 GLenum severity,
1560 GLsizei length,
1561 const GLchar *buf)
1562{
1563 if (!context->getExtensions().debug)
1564 {
Jamie Madill437fa652016-05-03 15:13:24 -04001565 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001566 return false;
1567 }
1568
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001569 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001570 {
1571 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1572 // not generate an error.
1573 return false;
1574 }
1575
1576 if (!ValidDebugSeverity(severity))
1577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001579 return false;
1580 }
1581
1582 if (!ValidDebugType(type))
1583 {
Jamie Madill437fa652016-05-03 15:13:24 -04001584 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001585 return false;
1586 }
1587
1588 if (!ValidDebugSource(source, true))
1589 {
Jamie Madill437fa652016-05-03 15:13:24 -04001590 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001591 return false;
1592 }
1593
1594 size_t messageLength = (length < 0) ? strlen(buf) : length;
1595 if (messageLength > context->getExtensions().maxDebugMessageLength)
1596 {
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001598 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1599 return false;
1600 }
1601
Geoff Lange102fee2015-12-10 11:23:30 -05001602 return true;
1603}
1604
1605bool ValidateDebugMessageCallbackKHR(Context *context,
1606 GLDEBUGPROCKHR callback,
1607 const void *userParam)
1608{
1609 if (!context->getExtensions().debug)
1610 {
Jamie Madill437fa652016-05-03 15:13:24 -04001611 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001612 return false;
1613 }
1614
Geoff Lange102fee2015-12-10 11:23:30 -05001615 return true;
1616}
1617
1618bool ValidateGetDebugMessageLogKHR(Context *context,
1619 GLuint count,
1620 GLsizei bufSize,
1621 GLenum *sources,
1622 GLenum *types,
1623 GLuint *ids,
1624 GLenum *severities,
1625 GLsizei *lengths,
1626 GLchar *messageLog)
1627{
1628 if (!context->getExtensions().debug)
1629 {
Jamie Madill437fa652016-05-03 15:13:24 -04001630 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001631 return false;
1632 }
1633
Geoff Lang70d0f492015-12-10 17:45:46 -05001634 if (bufSize < 0 && messageLog != nullptr)
1635 {
Jamie Madill437fa652016-05-03 15:13:24 -04001636 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001637 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1638 return false;
1639 }
1640
Geoff Lange102fee2015-12-10 11:23:30 -05001641 return true;
1642}
1643
1644bool ValidatePushDebugGroupKHR(Context *context,
1645 GLenum source,
1646 GLuint id,
1647 GLsizei length,
1648 const GLchar *message)
1649{
1650 if (!context->getExtensions().debug)
1651 {
Jamie Madill437fa652016-05-03 15:13:24 -04001652 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001653 return false;
1654 }
1655
Geoff Lang70d0f492015-12-10 17:45:46 -05001656 if (!ValidDebugSource(source, true))
1657 {
Jamie Madill437fa652016-05-03 15:13:24 -04001658 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001659 return false;
1660 }
1661
1662 size_t messageLength = (length < 0) ? strlen(message) : length;
1663 if (messageLength > context->getExtensions().maxDebugMessageLength)
1664 {
Jamie Madill437fa652016-05-03 15:13:24 -04001665 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001666 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1667 return false;
1668 }
1669
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001670 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001671 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1672 {
Jamie Madill437fa652016-05-03 15:13:24 -04001673 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001674 Error(GL_STACK_OVERFLOW,
1675 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1676 return false;
1677 }
1678
Geoff Lange102fee2015-12-10 11:23:30 -05001679 return true;
1680}
1681
1682bool ValidatePopDebugGroupKHR(Context *context)
1683{
1684 if (!context->getExtensions().debug)
1685 {
Jamie Madill437fa652016-05-03 15:13:24 -04001686 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001687 return false;
1688 }
1689
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001690 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001691 if (currentStackSize <= 1)
1692 {
Jamie Madill437fa652016-05-03 15:13:24 -04001693 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001694 return false;
1695 }
1696
1697 return true;
1698}
1699
1700static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1701{
1702 switch (identifier)
1703 {
1704 case GL_BUFFER:
1705 if (context->getBuffer(name) == nullptr)
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001708 return false;
1709 }
1710 return true;
1711
1712 case GL_SHADER:
1713 if (context->getShader(name) == nullptr)
1714 {
Jamie Madill437fa652016-05-03 15:13:24 -04001715 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001716 return false;
1717 }
1718 return true;
1719
1720 case GL_PROGRAM:
1721 if (context->getProgram(name) == nullptr)
1722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001724 return false;
1725 }
1726 return true;
1727
1728 case GL_VERTEX_ARRAY:
1729 if (context->getVertexArray(name) == nullptr)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001732 return false;
1733 }
1734 return true;
1735
1736 case GL_QUERY:
1737 if (context->getQuery(name) == nullptr)
1738 {
Jamie Madill437fa652016-05-03 15:13:24 -04001739 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001740 return false;
1741 }
1742 return true;
1743
1744 case GL_TRANSFORM_FEEDBACK:
1745 if (context->getTransformFeedback(name) == nullptr)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001748 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1749 return false;
1750 }
1751 return true;
1752
1753 case GL_SAMPLER:
1754 if (context->getSampler(name) == nullptr)
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001757 return false;
1758 }
1759 return true;
1760
1761 case GL_TEXTURE:
1762 if (context->getTexture(name) == nullptr)
1763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001765 return false;
1766 }
1767 return true;
1768
1769 case GL_RENDERBUFFER:
1770 if (context->getRenderbuffer(name) == nullptr)
1771 {
Jamie Madill437fa652016-05-03 15:13:24 -04001772 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001773 return false;
1774 }
1775 return true;
1776
1777 case GL_FRAMEBUFFER:
1778 if (context->getFramebuffer(name) == nullptr)
1779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001781 return false;
1782 }
1783 return true;
1784
1785 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001787 return false;
1788 }
Geoff Lange102fee2015-12-10 11:23:30 -05001789}
1790
Martin Radev9d901792016-07-15 15:58:58 +03001791static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1792{
1793 size_t labelLength = 0;
1794
1795 if (length < 0)
1796 {
1797 if (label != nullptr)
1798 {
1799 labelLength = strlen(label);
1800 }
1801 }
1802 else
1803 {
1804 labelLength = static_cast<size_t>(length);
1805 }
1806
1807 if (labelLength > context->getExtensions().maxLabelLength)
1808 {
1809 context->handleError(
1810 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1811 return false;
1812 }
1813
1814 return true;
1815}
1816
Geoff Lange102fee2015-12-10 11:23:30 -05001817bool ValidateObjectLabelKHR(Context *context,
1818 GLenum identifier,
1819 GLuint name,
1820 GLsizei length,
1821 const GLchar *label)
1822{
1823 if (!context->getExtensions().debug)
1824 {
Jamie Madill437fa652016-05-03 15:13:24 -04001825 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001826 return false;
1827 }
1828
Geoff Lang70d0f492015-12-10 17:45:46 -05001829 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1830 {
1831 return false;
1832 }
1833
Martin Radev9d901792016-07-15 15:58:58 +03001834 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001835 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001836 return false;
1837 }
1838
Geoff Lange102fee2015-12-10 11:23:30 -05001839 return true;
1840}
1841
1842bool ValidateGetObjectLabelKHR(Context *context,
1843 GLenum identifier,
1844 GLuint name,
1845 GLsizei bufSize,
1846 GLsizei *length,
1847 GLchar *label)
1848{
1849 if (!context->getExtensions().debug)
1850 {
Jamie Madill437fa652016-05-03 15:13:24 -04001851 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001852 return false;
1853 }
1854
Geoff Lang70d0f492015-12-10 17:45:46 -05001855 if (bufSize < 0)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001858 return false;
1859 }
1860
1861 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1862 {
1863 return false;
1864 }
1865
Martin Radev9d901792016-07-15 15:58:58 +03001866 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001867}
1868
1869static bool ValidateObjectPtrName(Context *context, const void *ptr)
1870{
1871 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1872 {
Jamie Madill437fa652016-05-03 15:13:24 -04001873 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001874 return false;
1875 }
1876
Geoff Lange102fee2015-12-10 11:23:30 -05001877 return true;
1878}
1879
1880bool ValidateObjectPtrLabelKHR(Context *context,
1881 const void *ptr,
1882 GLsizei length,
1883 const GLchar *label)
1884{
1885 if (!context->getExtensions().debug)
1886 {
Jamie Madill437fa652016-05-03 15:13:24 -04001887 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001888 return false;
1889 }
1890
Geoff Lang70d0f492015-12-10 17:45:46 -05001891 if (!ValidateObjectPtrName(context, ptr))
1892 {
1893 return false;
1894 }
1895
Martin Radev9d901792016-07-15 15:58:58 +03001896 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001897 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001898 return false;
1899 }
1900
Geoff Lange102fee2015-12-10 11:23:30 -05001901 return true;
1902}
1903
1904bool ValidateGetObjectPtrLabelKHR(Context *context,
1905 const void *ptr,
1906 GLsizei bufSize,
1907 GLsizei *length,
1908 GLchar *label)
1909{
1910 if (!context->getExtensions().debug)
1911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001913 return false;
1914 }
1915
Geoff Lang70d0f492015-12-10 17:45:46 -05001916 if (bufSize < 0)
1917 {
Jamie Madill437fa652016-05-03 15:13:24 -04001918 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001919 return false;
1920 }
1921
1922 if (!ValidateObjectPtrName(context, ptr))
1923 {
1924 return false;
1925 }
1926
Martin Radev9d901792016-07-15 15:58:58 +03001927 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001928}
1929
1930bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1931{
1932 if (!context->getExtensions().debug)
1933 {
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001935 return false;
1936 }
1937
Geoff Lang70d0f492015-12-10 17:45:46 -05001938 // TODO: represent this in Context::getQueryParameterInfo.
1939 switch (pname)
1940 {
1941 case GL_DEBUG_CALLBACK_FUNCTION:
1942 case GL_DEBUG_CALLBACK_USER_PARAM:
1943 break;
1944
1945 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001946 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001947 return false;
1948 }
1949
Geoff Lange102fee2015-12-10 11:23:30 -05001950 return true;
1951}
Jamie Madillc29968b2016-01-20 11:17:23 -05001952
1953bool ValidateBlitFramebufferANGLE(Context *context,
1954 GLint srcX0,
1955 GLint srcY0,
1956 GLint srcX1,
1957 GLint srcY1,
1958 GLint dstX0,
1959 GLint dstY0,
1960 GLint dstX1,
1961 GLint dstY1,
1962 GLbitfield mask,
1963 GLenum filter)
1964{
1965 if (!context->getExtensions().framebufferBlit)
1966 {
Jamie Madill437fa652016-05-03 15:13:24 -04001967 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001968 return false;
1969 }
1970
1971 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1972 {
1973 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001975 GL_INVALID_OPERATION,
1976 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1977 return false;
1978 }
1979
1980 if (filter == GL_LINEAR)
1981 {
Jamie Madill437fa652016-05-03 15:13:24 -04001982 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001983 return false;
1984 }
1985
Jamie Madill51f40ec2016-06-15 14:06:00 -04001986 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1987 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05001988
1989 if (mask & GL_COLOR_BUFFER_BIT)
1990 {
1991 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
1992 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
1993
1994 if (readColorAttachment && drawColorAttachment)
1995 {
1996 if (!(readColorAttachment->type() == GL_TEXTURE &&
1997 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
1998 readColorAttachment->type() != GL_RENDERBUFFER &&
1999 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2000 {
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002002 return false;
2003 }
2004
Geoff Langa15472a2015-08-11 11:48:03 -04002005 for (size_t drawbufferIdx = 0;
2006 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002007 {
Geoff Langa15472a2015-08-11 11:48:03 -04002008 const FramebufferAttachment *attachment =
2009 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2010 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002011 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002012 if (!(attachment->type() == GL_TEXTURE &&
2013 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2014 attachment->type() != GL_RENDERBUFFER &&
2015 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2016 {
Jamie Madill437fa652016-05-03 15:13:24 -04002017 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002018 return false;
2019 }
2020
2021 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002022 if (!Format::SameSized(attachment->getFormat(),
2023 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002024 {
Jamie Madill437fa652016-05-03 15:13:24 -04002025 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002026 return false;
2027 }
2028 }
2029 }
2030
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002031 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2033 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002036 return false;
2037 }
2038 }
2039 }
2040
2041 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2042 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2043 for (size_t i = 0; i < 2; i++)
2044 {
2045 if (mask & masks[i])
2046 {
2047 const FramebufferAttachment *readBuffer =
2048 readFramebuffer->getAttachment(attachments[i]);
2049 const FramebufferAttachment *drawBuffer =
2050 drawFramebuffer->getAttachment(attachments[i]);
2051
2052 if (readBuffer && drawBuffer)
2053 {
2054 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2055 dstX0, dstY0, dstX1, dstY1))
2056 {
2057 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05002058 context->handleError(Error(GL_INVALID_OPERATION,
2059 "Only whole-buffer depth and stencil blits are "
2060 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002061 return false;
2062 }
2063
2064 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2065 {
Jamie Madill437fa652016-05-03 15:13:24 -04002066 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002067 return false;
2068 }
2069 }
2070 }
2071 }
2072
2073 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2074 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002075}
Jamie Madillc29968b2016-01-20 11:17:23 -05002076
2077bool ValidateClear(ValidationContext *context, GLbitfield mask)
2078{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002079 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002080 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002083 return false;
2084 }
2085
2086 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2087 {
Jamie Madill437fa652016-05-03 15:13:24 -04002088 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05002089 return false;
2090 }
2091
Geoff Lang76e65652017-03-27 14:58:02 -04002092 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2093 {
2094 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2095 GL_SIGNED_NORMALIZED};
2096
2097 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2098 drawBufferIdx++)
2099 {
2100 if (!ValidateWebGLFramebufferAttachmentClearType(
2101 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2102 {
2103 return false;
2104 }
2105 }
2106 }
2107
Jamie Madillc29968b2016-01-20 11:17:23 -05002108 return true;
2109}
2110
2111bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2112{
2113 if (!context->getExtensions().drawBuffers)
2114 {
Jamie Madill437fa652016-05-03 15:13:24 -04002115 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002116 return false;
2117 }
2118
2119 return ValidateDrawBuffersBase(context, n, bufs);
2120}
2121
Jamie Madill73a84962016-02-12 09:27:23 -05002122bool ValidateTexImage2D(Context *context,
2123 GLenum target,
2124 GLint level,
2125 GLint internalformat,
2126 GLsizei width,
2127 GLsizei height,
2128 GLint border,
2129 GLenum format,
2130 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002131 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002132{
Martin Radev1be913c2016-07-11 17:59:16 +03002133 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002134 {
2135 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002136 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002137 }
2138
Martin Radev1be913c2016-07-11 17:59:16 +03002139 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002140 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002141 0, 0, width, height, 1, border, format, type, -1,
2142 pixels);
2143}
2144
2145bool ValidateTexImage2DRobust(Context *context,
2146 GLenum target,
2147 GLint level,
2148 GLint internalformat,
2149 GLsizei width,
2150 GLsizei height,
2151 GLint border,
2152 GLenum format,
2153 GLenum type,
2154 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002155 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002156{
2157 if (!ValidateRobustEntryPoint(context, bufSize))
2158 {
2159 return false;
2160 }
2161
2162 if (context->getClientMajorVersion() < 3)
2163 {
2164 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2165 0, 0, width, height, border, format, type, bufSize,
2166 pixels);
2167 }
2168
2169 ASSERT(context->getClientMajorVersion() >= 3);
2170 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2171 0, 0, width, height, 1, border, format, type, bufSize,
2172 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002173}
2174
2175bool ValidateTexSubImage2D(Context *context,
2176 GLenum target,
2177 GLint level,
2178 GLint xoffset,
2179 GLint yoffset,
2180 GLsizei width,
2181 GLsizei height,
2182 GLenum format,
2183 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002184 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002185{
2186
Martin Radev1be913c2016-07-11 17:59:16 +03002187 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002188 {
2189 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002190 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002191 }
2192
Martin Radev1be913c2016-07-11 17:59:16 +03002193 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002194 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002195 yoffset, 0, width, height, 1, 0, format, type, -1,
2196 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002197}
2198
Geoff Langc52f6f12016-10-14 10:18:00 -04002199bool ValidateTexSubImage2DRobustANGLE(Context *context,
2200 GLenum target,
2201 GLint level,
2202 GLint xoffset,
2203 GLint yoffset,
2204 GLsizei width,
2205 GLsizei height,
2206 GLenum format,
2207 GLenum type,
2208 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002209 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002210{
2211 if (!ValidateRobustEntryPoint(context, bufSize))
2212 {
2213 return false;
2214 }
2215
2216 if (context->getClientMajorVersion() < 3)
2217 {
2218 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2219 yoffset, width, height, 0, format, type, bufSize,
2220 pixels);
2221 }
2222
2223 ASSERT(context->getClientMajorVersion() >= 3);
2224 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2225 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2226 pixels);
2227}
2228
Jamie Madill73a84962016-02-12 09:27:23 -05002229bool ValidateCompressedTexImage2D(Context *context,
2230 GLenum target,
2231 GLint level,
2232 GLenum internalformat,
2233 GLsizei width,
2234 GLsizei height,
2235 GLint border,
2236 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002237 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002238{
Martin Radev1be913c2016-07-11 17:59:16 +03002239 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002240 {
2241 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002242 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002243 {
2244 return false;
2245 }
2246 }
2247 else
2248 {
Martin Radev1be913c2016-07-11 17:59:16 +03002249 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002250 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002251 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002252 data))
2253 {
2254 return false;
2255 }
2256 }
2257
Geoff Langca271392017-04-05 12:30:00 -04002258 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002259 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002260 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002261 if (blockSizeOrErr.isError())
2262 {
2263 context->handleError(blockSizeOrErr.getError());
2264 return false;
2265 }
2266
2267 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002268 {
Jamie Madill437fa652016-05-03 15:13:24 -04002269 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002270 return false;
2271 }
2272
2273 return true;
2274}
2275
Corentin Wallezb2931602017-04-11 15:58:57 -04002276bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2277 GLenum target,
2278 GLint level,
2279 GLenum internalformat,
2280 GLsizei width,
2281 GLsizei height,
2282 GLint border,
2283 GLsizei imageSize,
2284 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002285 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002286{
2287 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2288 {
2289 return false;
2290 }
2291
2292 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2293 border, imageSize, data);
2294}
2295bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2296 GLenum target,
2297 GLint level,
2298 GLint xoffset,
2299 GLint yoffset,
2300 GLsizei width,
2301 GLsizei height,
2302 GLenum format,
2303 GLsizei imageSize,
2304 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002305 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002306{
2307 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2308 {
2309 return false;
2310 }
2311
2312 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2313 format, imageSize, data);
2314}
2315
Jamie Madill73a84962016-02-12 09:27:23 -05002316bool ValidateCompressedTexSubImage2D(Context *context,
2317 GLenum target,
2318 GLint level,
2319 GLint xoffset,
2320 GLint yoffset,
2321 GLsizei width,
2322 GLsizei height,
2323 GLenum format,
2324 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002325 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002326{
Martin Radev1be913c2016-07-11 17:59:16 +03002327 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002328 {
2329 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002330 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002331 {
2332 return false;
2333 }
2334 }
2335 else
2336 {
Martin Radev1be913c2016-07-11 17:59:16 +03002337 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002338 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002339 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002340 data))
2341 {
2342 return false;
2343 }
2344 }
2345
Geoff Langca271392017-04-05 12:30:00 -04002346 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002347 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002348 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002349 if (blockSizeOrErr.isError())
2350 {
2351 context->handleError(blockSizeOrErr.getError());
2352 return false;
2353 }
2354
2355 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002356 {
Jamie Madill437fa652016-05-03 15:13:24 -04002357 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002358 return false;
2359 }
2360
2361 return true;
2362}
2363
Olli Etuaho4f667482016-03-30 15:56:35 +03002364bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2365{
Geoff Lang496c02d2016-10-20 11:38:11 -07002366 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002367}
2368
2369bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2370{
2371 if (!context->getExtensions().mapBuffer)
2372 {
Jamie Madill437fa652016-05-03 15:13:24 -04002373 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002374 return false;
2375 }
2376
2377 if (!ValidBufferTarget(context, target))
2378 {
Jamie Madill437fa652016-05-03 15:13:24 -04002379 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002380 return false;
2381 }
2382
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002383 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002384
2385 if (buffer == nullptr)
2386 {
Jamie Madill437fa652016-05-03 15:13:24 -04002387 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002388 return false;
2389 }
2390
2391 if (access != GL_WRITE_ONLY_OES)
2392 {
Jamie Madill437fa652016-05-03 15:13:24 -04002393 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002394 return false;
2395 }
2396
2397 if (buffer->isMapped())
2398 {
Jamie Madill437fa652016-05-03 15:13:24 -04002399 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002400 return false;
2401 }
2402
2403 return true;
2404}
2405
2406bool ValidateUnmapBufferOES(Context *context, GLenum target)
2407{
2408 if (!context->getExtensions().mapBuffer)
2409 {
Jamie Madill437fa652016-05-03 15:13:24 -04002410 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002411 return false;
2412 }
2413
2414 return ValidateUnmapBufferBase(context, target);
2415}
2416
2417bool ValidateMapBufferRangeEXT(Context *context,
2418 GLenum target,
2419 GLintptr offset,
2420 GLsizeiptr length,
2421 GLbitfield access)
2422{
2423 if (!context->getExtensions().mapBufferRange)
2424 {
Jamie Madill437fa652016-05-03 15:13:24 -04002425 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002426 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2427 return false;
2428 }
2429
2430 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2431}
2432
2433bool ValidateFlushMappedBufferRangeEXT(Context *context,
2434 GLenum target,
2435 GLintptr offset,
2436 GLsizeiptr length)
2437{
2438 if (!context->getExtensions().mapBufferRange)
2439 {
Jamie Madill437fa652016-05-03 15:13:24 -04002440 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002441 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2442 return false;
2443 }
2444
2445 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2446}
2447
Ian Ewell54f87462016-03-10 13:47:21 -05002448bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2449{
2450 Texture *textureObject = context->getTexture(texture);
2451 if (textureObject && textureObject->getTarget() != target && texture != 0)
2452 {
Jamie Madill437fa652016-05-03 15:13:24 -04002453 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002454 return false;
2455 }
2456
Geoff Langf41a7152016-09-19 15:11:17 -04002457 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2458 !context->isTextureGenerated(texture))
2459 {
2460 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2461 return false;
2462 }
2463
Ian Ewell54f87462016-03-10 13:47:21 -05002464 switch (target)
2465 {
2466 case GL_TEXTURE_2D:
2467 case GL_TEXTURE_CUBE_MAP:
2468 break;
2469
2470 case GL_TEXTURE_3D:
2471 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002472 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002473 {
Jamie Madill437fa652016-05-03 15:13:24 -04002474 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002475 return false;
2476 }
2477 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002478
2479 case GL_TEXTURE_2D_MULTISAMPLE:
2480 if (context->getClientVersion() < Version(3, 1))
2481 {
2482 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2483 return false;
2484 }
Geoff Lang3b573612016-10-31 14:08:10 -04002485 break;
2486
Ian Ewell54f87462016-03-10 13:47:21 -05002487 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002488 if (!context->getExtensions().eglImageExternal &&
2489 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002490 {
Jamie Madill437fa652016-05-03 15:13:24 -04002491 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002492 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2493 return false;
2494 }
2495 break;
2496 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002498 return false;
2499 }
2500
2501 return true;
2502}
2503
Geoff Langd8605522016-04-13 10:19:12 -04002504bool ValidateBindUniformLocationCHROMIUM(Context *context,
2505 GLuint program,
2506 GLint location,
2507 const GLchar *name)
2508{
2509 if (!context->getExtensions().bindUniformLocation)
2510 {
Jamie Madill437fa652016-05-03 15:13:24 -04002511 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002512 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2513 return false;
2514 }
2515
2516 Program *programObject = GetValidProgram(context, program);
2517 if (!programObject)
2518 {
2519 return false;
2520 }
2521
2522 if (location < 0)
2523 {
Jamie Madill437fa652016-05-03 15:13:24 -04002524 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002525 return false;
2526 }
2527
2528 const Caps &caps = context->getCaps();
2529 if (static_cast<size_t>(location) >=
2530 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2531 {
Jamie Madill437fa652016-05-03 15:13:24 -04002532 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002533 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2534 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2535 return false;
2536 }
2537
2538 if (strncmp(name, "gl_", 3) == 0)
2539 {
Jamie Madill437fa652016-05-03 15:13:24 -04002540 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002541 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2542 return false;
2543 }
2544
2545 return true;
2546}
2547
Jamie Madille2e406c2016-06-02 13:04:10 -04002548bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002549{
2550 if (!context->getExtensions().framebufferMixedSamples)
2551 {
2552 context->handleError(
2553 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2554 return false;
2555 }
2556 switch (components)
2557 {
2558 case GL_RGB:
2559 case GL_RGBA:
2560 case GL_ALPHA:
2561 case GL_NONE:
2562 break;
2563 default:
2564 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002565 Error(GL_INVALID_ENUM,
2566 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002567 return false;
2568 }
2569
2570 return true;
2571}
2572
Sami Väisänene45e53b2016-05-25 10:36:04 +03002573// CHROMIUM_path_rendering
2574
2575bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2576{
2577 if (!context->getExtensions().pathRendering)
2578 {
2579 context->handleError(
2580 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2581 return false;
2582 }
2583 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2584 {
2585 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2586 return false;
2587 }
2588 if (matrix == nullptr)
2589 {
2590 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2591 return false;
2592 }
2593 return true;
2594}
2595
2596bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2597{
2598 if (!context->getExtensions().pathRendering)
2599 {
2600 context->handleError(
2601 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2602 return false;
2603 }
2604 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2605 {
2606 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2607 return false;
2608 }
2609 return true;
2610}
2611
2612bool ValidateGenPaths(Context *context, GLsizei range)
2613{
2614 if (!context->getExtensions().pathRendering)
2615 {
2616 context->handleError(
2617 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2618 return false;
2619 }
2620
2621 // range = 0 is undefined in NV_path_rendering.
2622 // we add stricter semantic check here and require a non zero positive range.
2623 if (range <= 0)
2624 {
2625 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2626 return false;
2627 }
2628
2629 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2630 {
2631 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2632 return false;
2633 }
2634
2635 return true;
2636}
2637
2638bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2639{
2640 if (!context->getExtensions().pathRendering)
2641 {
2642 context->handleError(
2643 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2644 return false;
2645 }
2646
2647 // range = 0 is undefined in NV_path_rendering.
2648 // we add stricter semantic check here and require a non zero positive range.
2649 if (range <= 0)
2650 {
2651 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2652 return false;
2653 }
2654
2655 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2656 checkedRange += range;
2657
2658 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2659 {
2660 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2661 return false;
2662 }
2663 return true;
2664}
2665
2666bool ValidatePathCommands(Context *context,
2667 GLuint path,
2668 GLsizei numCommands,
2669 const GLubyte *commands,
2670 GLsizei numCoords,
2671 GLenum coordType,
2672 const void *coords)
2673{
2674 if (!context->getExtensions().pathRendering)
2675 {
2676 context->handleError(
2677 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2678 return false;
2679 }
2680 if (!context->hasPath(path))
2681 {
2682 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2683 return false;
2684 }
2685
2686 if (numCommands < 0)
2687 {
2688 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2689 return false;
2690 }
2691 else if (numCommands > 0)
2692 {
2693 if (!commands)
2694 {
2695 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2696 return false;
2697 }
2698 }
2699
2700 if (numCoords < 0)
2701 {
2702 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2703 return false;
2704 }
2705 else if (numCoords > 0)
2706 {
2707 if (!coords)
2708 {
2709 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2710 return false;
2711 }
2712 }
2713
2714 std::uint32_t coordTypeSize = 0;
2715 switch (coordType)
2716 {
2717 case GL_BYTE:
2718 coordTypeSize = sizeof(GLbyte);
2719 break;
2720
2721 case GL_UNSIGNED_BYTE:
2722 coordTypeSize = sizeof(GLubyte);
2723 break;
2724
2725 case GL_SHORT:
2726 coordTypeSize = sizeof(GLshort);
2727 break;
2728
2729 case GL_UNSIGNED_SHORT:
2730 coordTypeSize = sizeof(GLushort);
2731 break;
2732
2733 case GL_FLOAT:
2734 coordTypeSize = sizeof(GLfloat);
2735 break;
2736
2737 default:
2738 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2739 return false;
2740 }
2741
2742 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2743 checkedSize += (coordTypeSize * numCoords);
2744 if (!checkedSize.IsValid())
2745 {
2746 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2747 return false;
2748 }
2749
2750 // early return skips command data validation when it doesn't exist.
2751 if (!commands)
2752 return true;
2753
2754 GLsizei expectedNumCoords = 0;
2755 for (GLsizei i = 0; i < numCommands; ++i)
2756 {
2757 switch (commands[i])
2758 {
2759 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2760 break;
2761 case GL_MOVE_TO_CHROMIUM:
2762 case GL_LINE_TO_CHROMIUM:
2763 expectedNumCoords += 2;
2764 break;
2765 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2766 expectedNumCoords += 4;
2767 break;
2768 case GL_CUBIC_CURVE_TO_CHROMIUM:
2769 expectedNumCoords += 6;
2770 break;
2771 case GL_CONIC_CURVE_TO_CHROMIUM:
2772 expectedNumCoords += 5;
2773 break;
2774 default:
2775 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2776 return false;
2777 }
2778 }
2779 if (expectedNumCoords != numCoords)
2780 {
2781 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2782 return false;
2783 }
2784
2785 return true;
2786}
2787
2788bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2789{
2790 if (!context->getExtensions().pathRendering)
2791 {
2792 context->handleError(
2793 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2794 return false;
2795 }
2796 if (!context->hasPath(path))
2797 {
2798 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2799 return false;
2800 }
2801
2802 switch (pname)
2803 {
2804 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2805 if (value < 0.0f)
2806 {
2807 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2808 return false;
2809 }
2810 break;
2811 case GL_PATH_END_CAPS_CHROMIUM:
2812 switch (static_cast<GLenum>(value))
2813 {
2814 case GL_FLAT_CHROMIUM:
2815 case GL_SQUARE_CHROMIUM:
2816 case GL_ROUND_CHROMIUM:
2817 break;
2818 default:
2819 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2820 return false;
2821 }
2822 break;
2823 case GL_PATH_JOIN_STYLE_CHROMIUM:
2824 switch (static_cast<GLenum>(value))
2825 {
2826 case GL_MITER_REVERT_CHROMIUM:
2827 case GL_BEVEL_CHROMIUM:
2828 case GL_ROUND_CHROMIUM:
2829 break;
2830 default:
2831 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2832 return false;
2833 }
2834 case GL_PATH_MITER_LIMIT_CHROMIUM:
2835 if (value < 0.0f)
2836 {
2837 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2838 return false;
2839 }
2840 break;
2841
2842 case GL_PATH_STROKE_BOUND_CHROMIUM:
2843 // no errors, only clamping.
2844 break;
2845
2846 default:
2847 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2848 return false;
2849 }
2850 return true;
2851}
2852
2853bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2854{
2855 if (!context->getExtensions().pathRendering)
2856 {
2857 context->handleError(
2858 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2859 return false;
2860 }
2861
2862 if (!context->hasPath(path))
2863 {
2864 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2865 return false;
2866 }
2867 if (!value)
2868 {
2869 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2870 return false;
2871 }
2872
2873 switch (pname)
2874 {
2875 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2876 case GL_PATH_END_CAPS_CHROMIUM:
2877 case GL_PATH_JOIN_STYLE_CHROMIUM:
2878 case GL_PATH_MITER_LIMIT_CHROMIUM:
2879 case GL_PATH_STROKE_BOUND_CHROMIUM:
2880 break;
2881
2882 default:
2883 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2884 return false;
2885 }
2886
2887 return true;
2888}
2889
2890bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2891{
2892 if (!context->getExtensions().pathRendering)
2893 {
2894 context->handleError(
2895 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2896 return false;
2897 }
2898
2899 switch (func)
2900 {
2901 case GL_NEVER:
2902 case GL_ALWAYS:
2903 case GL_LESS:
2904 case GL_LEQUAL:
2905 case GL_EQUAL:
2906 case GL_GEQUAL:
2907 case GL_GREATER:
2908 case GL_NOTEQUAL:
2909 break;
2910 default:
2911 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2912 return false;
2913 }
2914
2915 return true;
2916}
2917
2918// Note that the spec specifies that for the path drawing commands
2919// if the path object is not an existing path object the command
2920// does nothing and no error is generated.
2921// However if the path object exists but has not been specified any
2922// commands then an error is generated.
2923
2924bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2925{
2926 if (!context->getExtensions().pathRendering)
2927 {
2928 context->handleError(
2929 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2930 return false;
2931 }
2932 if (context->hasPath(path) && !context->hasPathData(path))
2933 {
2934 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2935 return false;
2936 }
2937
2938 switch (fillMode)
2939 {
2940 case GL_COUNT_UP_CHROMIUM:
2941 case GL_COUNT_DOWN_CHROMIUM:
2942 break;
2943 default:
2944 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2945 return false;
2946 }
2947
2948 if (!isPow2(mask + 1))
2949 {
2950 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2951 return false;
2952 }
2953
2954 return true;
2955}
2956
2957bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2958{
2959 if (!context->getExtensions().pathRendering)
2960 {
2961 context->handleError(
2962 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2963 return false;
2964 }
2965 if (context->hasPath(path) && !context->hasPathData(path))
2966 {
2967 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2968 return false;
2969 }
2970
2971 return true;
2972}
2973
2974bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2975{
2976 if (!context->getExtensions().pathRendering)
2977 {
2978 context->handleError(
2979 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2980 return false;
2981 }
2982 if (context->hasPath(path) && !context->hasPathData(path))
2983 {
2984 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2985 return false;
2986 }
2987
2988 switch (coverMode)
2989 {
2990 case GL_CONVEX_HULL_CHROMIUM:
2991 case GL_BOUNDING_BOX_CHROMIUM:
2992 break;
2993 default:
2994 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
2995 return false;
2996 }
2997 return true;
2998}
2999
3000bool ValidateStencilThenCoverFillPath(Context *context,
3001 GLuint path,
3002 GLenum fillMode,
3003 GLuint mask,
3004 GLenum coverMode)
3005{
3006 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3007 ValidateCoverPath(context, path, coverMode);
3008}
3009
3010bool ValidateStencilThenCoverStrokePath(Context *context,
3011 GLuint path,
3012 GLint reference,
3013 GLuint mask,
3014 GLenum coverMode)
3015{
3016 return ValidateStencilStrokePath(context, path, reference, mask) &&
3017 ValidateCoverPath(context, path, coverMode);
3018}
3019
3020bool ValidateIsPath(Context *context)
3021{
3022 if (!context->getExtensions().pathRendering)
3023 {
3024 context->handleError(
3025 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3026 return false;
3027 }
3028 return true;
3029}
3030
Sami Väisänend59ca052016-06-21 16:10:00 +03003031bool ValidateCoverFillPathInstanced(Context *context,
3032 GLsizei numPaths,
3033 GLenum pathNameType,
3034 const void *paths,
3035 GLuint pathBase,
3036 GLenum coverMode,
3037 GLenum transformType,
3038 const GLfloat *transformValues)
3039{
3040 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3041 transformType, transformValues))
3042 return false;
3043
3044 switch (coverMode)
3045 {
3046 case GL_CONVEX_HULL_CHROMIUM:
3047 case GL_BOUNDING_BOX_CHROMIUM:
3048 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3049 break;
3050 default:
3051 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3052 return false;
3053 }
3054
3055 return true;
3056}
3057
3058bool ValidateCoverStrokePathInstanced(Context *context,
3059 GLsizei numPaths,
3060 GLenum pathNameType,
3061 const void *paths,
3062 GLuint pathBase,
3063 GLenum coverMode,
3064 GLenum transformType,
3065 const GLfloat *transformValues)
3066{
3067 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3068 transformType, transformValues))
3069 return false;
3070
3071 switch (coverMode)
3072 {
3073 case GL_CONVEX_HULL_CHROMIUM:
3074 case GL_BOUNDING_BOX_CHROMIUM:
3075 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3076 break;
3077 default:
3078 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3079 return false;
3080 }
3081
3082 return true;
3083}
3084
3085bool ValidateStencilFillPathInstanced(Context *context,
3086 GLsizei numPaths,
3087 GLenum pathNameType,
3088 const void *paths,
3089 GLuint pathBase,
3090 GLenum fillMode,
3091 GLuint mask,
3092 GLenum transformType,
3093 const GLfloat *transformValues)
3094{
3095
3096 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3097 transformType, transformValues))
3098 return false;
3099
3100 switch (fillMode)
3101 {
3102 case GL_COUNT_UP_CHROMIUM:
3103 case GL_COUNT_DOWN_CHROMIUM:
3104 break;
3105 default:
3106 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3107 return false;
3108 }
3109 if (!isPow2(mask + 1))
3110 {
3111 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3112 return false;
3113 }
3114 return true;
3115}
3116
3117bool ValidateStencilStrokePathInstanced(Context *context,
3118 GLsizei numPaths,
3119 GLenum pathNameType,
3120 const void *paths,
3121 GLuint pathBase,
3122 GLint reference,
3123 GLuint mask,
3124 GLenum transformType,
3125 const GLfloat *transformValues)
3126{
3127 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3128 transformType, transformValues))
3129 return false;
3130
3131 // no more validation here.
3132
3133 return true;
3134}
3135
3136bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3137 GLsizei numPaths,
3138 GLenum pathNameType,
3139 const void *paths,
3140 GLuint pathBase,
3141 GLenum fillMode,
3142 GLuint mask,
3143 GLenum coverMode,
3144 GLenum transformType,
3145 const GLfloat *transformValues)
3146{
3147 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3148 transformType, transformValues))
3149 return false;
3150
3151 switch (coverMode)
3152 {
3153 case GL_CONVEX_HULL_CHROMIUM:
3154 case GL_BOUNDING_BOX_CHROMIUM:
3155 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3156 break;
3157 default:
3158 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3159 return false;
3160 }
3161
3162 switch (fillMode)
3163 {
3164 case GL_COUNT_UP_CHROMIUM:
3165 case GL_COUNT_DOWN_CHROMIUM:
3166 break;
3167 default:
3168 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3169 return false;
3170 }
3171 if (!isPow2(mask + 1))
3172 {
3173 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3174 return false;
3175 }
3176
3177 return true;
3178}
3179
3180bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3181 GLsizei numPaths,
3182 GLenum pathNameType,
3183 const void *paths,
3184 GLuint pathBase,
3185 GLint reference,
3186 GLuint mask,
3187 GLenum coverMode,
3188 GLenum transformType,
3189 const GLfloat *transformValues)
3190{
3191 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3192 transformType, transformValues))
3193 return false;
3194
3195 switch (coverMode)
3196 {
3197 case GL_CONVEX_HULL_CHROMIUM:
3198 case GL_BOUNDING_BOX_CHROMIUM:
3199 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3200 break;
3201 default:
3202 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3203 return false;
3204 }
3205
3206 return true;
3207}
3208
Sami Väisänen46eaa942016-06-29 10:26:37 +03003209bool ValidateBindFragmentInputLocation(Context *context,
3210 GLuint program,
3211 GLint location,
3212 const GLchar *name)
3213{
3214 if (!context->getExtensions().pathRendering)
3215 {
3216 context->handleError(
3217 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3218 return false;
3219 }
3220
3221 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3222 if (location >= MaxLocation)
3223 {
3224 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3225 return false;
3226 }
3227
3228 const auto *programObject = context->getProgram(program);
3229 if (!programObject)
3230 {
3231 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3232 return false;
3233 }
3234
3235 if (!name)
3236 {
3237 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3238 return false;
3239 }
3240
3241 if (angle::BeginsWith(name, "gl_"))
3242 {
3243 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3244 return false;
3245 }
3246
3247 return true;
3248}
3249
3250bool ValidateProgramPathFragmentInputGen(Context *context,
3251 GLuint program,
3252 GLint location,
3253 GLenum genMode,
3254 GLint components,
3255 const GLfloat *coeffs)
3256{
3257 if (!context->getExtensions().pathRendering)
3258 {
3259 context->handleError(
3260 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3261 return false;
3262 }
3263
3264 const auto *programObject = context->getProgram(program);
3265 if (!programObject || programObject->isFlaggedForDeletion())
3266 {
3267 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3268 return false;
3269 }
3270
3271 if (!programObject->isLinked())
3272 {
3273 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3274 return false;
3275 }
3276
3277 switch (genMode)
3278 {
3279 case GL_NONE:
3280 if (components != 0)
3281 {
3282 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3283 return false;
3284 }
3285 break;
3286
3287 case GL_OBJECT_LINEAR_CHROMIUM:
3288 case GL_EYE_LINEAR_CHROMIUM:
3289 case GL_CONSTANT_CHROMIUM:
3290 if (components < 1 || components > 4)
3291 {
3292 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3293 return false;
3294 }
3295 if (!coeffs)
3296 {
3297 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3298 return false;
3299 }
3300 break;
3301
3302 default:
3303 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3304 return false;
3305 }
3306
3307 // If the location is -1 then the command is silently ignored
3308 // and no further validation is needed.
3309 if (location == -1)
3310 return true;
3311
3312 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3313
3314 if (!binding.valid)
3315 {
3316 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3317 return false;
3318 }
3319
3320 if (binding.type != GL_NONE)
3321 {
3322 GLint expectedComponents = 0;
3323 switch (binding.type)
3324 {
3325 case GL_FLOAT:
3326 expectedComponents = 1;
3327 break;
3328 case GL_FLOAT_VEC2:
3329 expectedComponents = 2;
3330 break;
3331 case GL_FLOAT_VEC3:
3332 expectedComponents = 3;
3333 break;
3334 case GL_FLOAT_VEC4:
3335 expectedComponents = 4;
3336 break;
3337 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003338 context->handleError(
3339 Error(GL_INVALID_OPERATION,
3340 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003341 return false;
3342 }
3343 if (expectedComponents != components && genMode != GL_NONE)
3344 {
3345 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3346 return false;
3347 }
3348 }
3349 return true;
3350}
3351
Geoff Lang97073d12016-04-20 10:42:34 -07003352bool ValidateCopyTextureCHROMIUM(Context *context,
3353 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003354 GLint sourceLevel,
3355 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003356 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003357 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003358 GLint internalFormat,
3359 GLenum destType,
3360 GLboolean unpackFlipY,
3361 GLboolean unpackPremultiplyAlpha,
3362 GLboolean unpackUnmultiplyAlpha)
3363{
3364 if (!context->getExtensions().copyTexture)
3365 {
3366 context->handleError(
3367 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3368 return false;
3369 }
3370
3371 const gl::Texture *source = context->getTexture(sourceId);
3372 if (source == nullptr)
3373 {
3374 context->handleError(
3375 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3376 return false;
3377 }
3378
3379 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3380 {
3381 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3382 return false;
3383 }
3384
3385 GLenum sourceTarget = source->getTarget();
3386 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3387 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3388 {
3389 context->handleError(
3390 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3391 return false;
3392 }
3393
Geoff Langca271392017-04-05 12:30:00 -04003394 const gl::InternalFormat &sourceFormat = *source->getFormat(sourceTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003395 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3396 {
3397 context->handleError(
3398 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3399 return false;
3400 }
3401
3402 const gl::Texture *dest = context->getTexture(destId);
3403 if (dest == nullptr)
3404 {
3405 context->handleError(
3406 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3407 return false;
3408 }
3409
3410 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3411 {
3412 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3413 return false;
3414 }
3415
3416 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3417 {
3418 context->handleError(
3419 Error(GL_INVALID_OPERATION,
3420 "Destination internal format and type combination is not valid."));
3421 return false;
3422 }
3423
3424 if (dest->getImmutableFormat())
3425 {
3426 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3427 return false;
3428 }
3429
3430 return true;
3431}
3432
3433bool ValidateCopySubTextureCHROMIUM(Context *context,
3434 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003435 GLint sourceLevel,
3436 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003437 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003438 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003439 GLint xoffset,
3440 GLint yoffset,
3441 GLint x,
3442 GLint y,
3443 GLsizei width,
3444 GLsizei height,
3445 GLboolean unpackFlipY,
3446 GLboolean unpackPremultiplyAlpha,
3447 GLboolean unpackUnmultiplyAlpha)
3448{
3449 if (!context->getExtensions().copyTexture)
3450 {
3451 context->handleError(
3452 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3453 return false;
3454 }
3455
3456 const gl::Texture *source = context->getTexture(sourceId);
3457 if (source == nullptr)
3458 {
3459 context->handleError(
3460 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3461 return false;
3462 }
3463
3464 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3465 {
3466 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3467 return false;
3468 }
3469
3470 GLenum sourceTarget = source->getTarget();
3471 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3472 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3473 {
3474 context->handleError(
3475 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3476 return false;
3477 }
3478
3479 if (x < 0 || y < 0)
3480 {
3481 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3482 return false;
3483 }
3484
3485 if (width < 0 || height < 0)
3486 {
3487 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3488 return false;
3489 }
3490
3491 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3492 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3493 {
3494 context->handleError(
3495 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3496 return false;
3497 }
3498
3499 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
Geoff Langca271392017-04-05 12:30:00 -04003500 if (!IsValidCopyTextureFormat(context, sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003501 {
3502 context->handleError(
3503 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3504 return false;
3505 }
3506
3507 const gl::Texture *dest = context->getTexture(destId);
3508 if (dest == nullptr)
3509 {
3510 context->handleError(
3511 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3512 return false;
3513 }
3514
3515 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3516 {
3517 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3518 return false;
3519 }
3520
Geoff Lang97073d12016-04-20 10:42:34 -07003521 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3522 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3523 {
3524 context->handleError(
3525 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3526 return false;
3527 }
3528
Geoff Langca271392017-04-05 12:30:00 -04003529 const gl::InternalFormat &destFormat = *dest->getFormat(destTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003530 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3531 {
3532 context->handleError(
3533 Error(GL_INVALID_OPERATION,
3534 "Destination internal format and type combination is not valid."));
3535 return false;
3536 }
3537
3538 if (xoffset < 0 || yoffset < 0)
3539 {
3540 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3541 return false;
3542 }
3543
3544 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3545 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3546 {
3547 context->handleError(
3548 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3549 return false;
3550 }
3551
3552 return true;
3553}
3554
Geoff Lang47110bf2016-04-20 11:13:22 -07003555bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3556{
3557 if (!context->getExtensions().copyCompressedTexture)
3558 {
3559 context->handleError(Error(GL_INVALID_OPERATION,
3560 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3561 return false;
3562 }
3563
3564 const gl::Texture *source = context->getTexture(sourceId);
3565 if (source == nullptr)
3566 {
3567 context->handleError(
3568 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3569 return false;
3570 }
3571
3572 if (source->getTarget() != GL_TEXTURE_2D)
3573 {
3574 context->handleError(
3575 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3576 return false;
3577 }
3578
3579 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3580 {
3581 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3582 return false;
3583 }
3584
3585 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3586 if (!sourceFormat.info->compressed)
3587 {
3588 context->handleError(
3589 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3590 return false;
3591 }
3592
3593 const gl::Texture *dest = context->getTexture(destId);
3594 if (dest == nullptr)
3595 {
3596 context->handleError(
3597 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3598 return false;
3599 }
3600
3601 if (dest->getTarget() != GL_TEXTURE_2D)
3602 {
3603 context->handleError(
3604 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3605 return false;
3606 }
3607
3608 if (dest->getImmutableFormat())
3609 {
3610 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3611 return false;
3612 }
3613
3614 return true;
3615}
3616
Martin Radev4c4c8e72016-08-04 12:25:34 +03003617bool ValidateCreateShader(Context *context, GLenum type)
3618{
3619 switch (type)
3620 {
3621 case GL_VERTEX_SHADER:
3622 case GL_FRAGMENT_SHADER:
3623 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003624
Martin Radev4c4c8e72016-08-04 12:25:34 +03003625 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003626 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003627 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003628 context->handleError(
3629 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3630 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003631 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003632 break;
3633
Martin Radev4c4c8e72016-08-04 12:25:34 +03003634 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003635 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003636 return false;
3637 }
Jamie Madill29639852016-09-02 15:00:09 -04003638
3639 return true;
3640}
3641
3642bool ValidateBufferData(ValidationContext *context,
3643 GLenum target,
3644 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003645 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003646 GLenum usage)
3647{
3648 if (size < 0)
3649 {
3650 context->handleError(Error(GL_INVALID_VALUE));
3651 return false;
3652 }
3653
3654 switch (usage)
3655 {
3656 case GL_STREAM_DRAW:
3657 case GL_STATIC_DRAW:
3658 case GL_DYNAMIC_DRAW:
3659 break;
3660
3661 case GL_STREAM_READ:
3662 case GL_STREAM_COPY:
3663 case GL_STATIC_READ:
3664 case GL_STATIC_COPY:
3665 case GL_DYNAMIC_READ:
3666 case GL_DYNAMIC_COPY:
3667 if (context->getClientMajorVersion() < 3)
3668 {
3669 context->handleError(Error(GL_INVALID_ENUM));
3670 return false;
3671 }
3672 break;
3673
3674 default:
3675 context->handleError(Error(GL_INVALID_ENUM));
3676 return false;
3677 }
3678
3679 if (!ValidBufferTarget(context, target))
3680 {
3681 context->handleError(Error(GL_INVALID_ENUM));
3682 return false;
3683 }
3684
3685 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3686
3687 if (!buffer)
3688 {
3689 context->handleError(Error(GL_INVALID_OPERATION));
3690 return false;
3691 }
3692
3693 return true;
3694}
3695
3696bool ValidateBufferSubData(ValidationContext *context,
3697 GLenum target,
3698 GLintptr offset,
3699 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003700 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003701{
3702 if (size < 0 || offset < 0)
3703 {
3704 context->handleError(Error(GL_INVALID_VALUE));
3705 return false;
3706 }
3707
3708 if (!ValidBufferTarget(context, target))
3709 {
3710 context->handleError(Error(GL_INVALID_ENUM));
3711 return false;
3712 }
3713
3714 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3715
3716 if (!buffer)
3717 {
3718 context->handleError(Error(GL_INVALID_OPERATION));
3719 return false;
3720 }
3721
3722 if (buffer->isMapped())
3723 {
3724 context->handleError(Error(GL_INVALID_OPERATION));
3725 return false;
3726 }
3727
3728 // Check for possible overflow of size + offset
3729 angle::CheckedNumeric<size_t> checkedSize(size);
3730 checkedSize += offset;
3731 if (!checkedSize.IsValid())
3732 {
3733 context->handleError(Error(GL_OUT_OF_MEMORY));
3734 return false;
3735 }
3736
3737 if (size + offset > buffer->getSize())
3738 {
3739 context->handleError(Error(GL_INVALID_VALUE));
3740 return false;
3741 }
3742
Martin Radev4c4c8e72016-08-04 12:25:34 +03003743 return true;
3744}
3745
Geoff Langc339c4e2016-11-29 10:37:36 -05003746bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003747{
Geoff Langc339c4e2016-11-29 10:37:36 -05003748 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003749 {
3750 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003751 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003752 return false;
3753 }
3754
3755 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3756 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003757 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003758 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003759 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003760 return false;
3761 }
3762
3763 return true;
3764}
3765
Jamie Madillef300b12016-10-07 15:12:09 -04003766bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3767{
3768 if (texture < GL_TEXTURE0 ||
3769 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3770 {
3771 context->handleError(Error(GL_INVALID_ENUM));
3772 return false;
3773 }
3774
3775 return true;
3776}
3777
3778bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3779{
3780 Program *programObject = GetValidProgram(context, program);
3781 if (!programObject)
3782 {
3783 return false;
3784 }
3785
3786 Shader *shaderObject = GetValidShader(context, shader);
3787 if (!shaderObject)
3788 {
3789 return false;
3790 }
3791
3792 switch (shaderObject->getType())
3793 {
3794 case GL_VERTEX_SHADER:
3795 {
3796 if (programObject->getAttachedVertexShader())
3797 {
3798 context->handleError(Error(GL_INVALID_OPERATION));
3799 return false;
3800 }
3801 break;
3802 }
3803 case GL_FRAGMENT_SHADER:
3804 {
3805 if (programObject->getAttachedFragmentShader())
3806 {
3807 context->handleError(Error(GL_INVALID_OPERATION));
3808 return false;
3809 }
3810 break;
3811 }
3812 case GL_COMPUTE_SHADER:
3813 {
3814 if (programObject->getAttachedComputeShader())
3815 {
3816 context->handleError(Error(GL_INVALID_OPERATION));
3817 return false;
3818 }
3819 break;
3820 }
3821 default:
3822 UNREACHABLE();
3823 break;
3824 }
3825
3826 return true;
3827}
3828
Jamie Madill01a80ee2016-11-07 12:06:18 -05003829bool ValidateBindAttribLocation(ValidationContext *context,
3830 GLuint program,
3831 GLuint index,
3832 const GLchar *name)
3833{
3834 if (index >= MAX_VERTEX_ATTRIBS)
3835 {
3836 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3837 return false;
3838 }
3839
3840 if (strncmp(name, "gl_", 3) == 0)
3841 {
3842 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3843 return false;
3844 }
3845
3846 return GetValidProgram(context, program) != nullptr;
3847}
3848
3849bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3850{
3851 if (!ValidBufferTarget(context, target))
3852 {
3853 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3854 return false;
3855 }
3856
3857 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3858 !context->isBufferGenerated(buffer))
3859 {
3860 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3861 return false;
3862 }
3863
3864 return true;
3865}
3866
3867bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3868{
3869 if (!ValidFramebufferTarget(target))
3870 {
3871 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3872 return false;
3873 }
3874
3875 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3876 !context->isFramebufferGenerated(framebuffer))
3877 {
3878 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3879 return false;
3880 }
3881
3882 return true;
3883}
3884
3885bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3886{
3887 if (target != GL_RENDERBUFFER)
3888 {
3889 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3890 return false;
3891 }
3892
3893 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3894 !context->isRenderbufferGenerated(renderbuffer))
3895 {
3896 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3897 return false;
3898 }
3899
3900 return true;
3901}
3902
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003903static bool ValidBlendEquationMode(GLenum mode)
3904{
3905 switch (mode)
3906 {
3907 case GL_FUNC_ADD:
3908 case GL_FUNC_SUBTRACT:
3909 case GL_FUNC_REVERSE_SUBTRACT:
3910 case GL_MIN:
3911 case GL_MAX:
3912 return true;
3913
3914 default:
3915 return false;
3916 }
3917}
3918
Jamie Madillc1d770e2017-04-13 17:31:24 -04003919bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04003920 GLfloat red,
3921 GLfloat green,
3922 GLfloat blue,
3923 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04003924{
3925 return true;
3926}
3927
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003928bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3929{
3930 if (!ValidBlendEquationMode(mode))
3931 {
3932 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3933 return false;
3934 }
3935
3936 return true;
3937}
3938
3939bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3940{
3941 if (!ValidBlendEquationMode(modeRGB))
3942 {
3943 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3944 return false;
3945 }
3946
3947 if (!ValidBlendEquationMode(modeAlpha))
3948 {
3949 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3950 return false;
3951 }
3952
3953 return true;
3954}
3955
3956bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3957{
3958 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3959}
3960
3961static bool ValidSrcBlendFunc(GLenum srcBlend)
3962{
3963 switch (srcBlend)
3964 {
3965 case GL_ZERO:
3966 case GL_ONE:
3967 case GL_SRC_COLOR:
3968 case GL_ONE_MINUS_SRC_COLOR:
3969 case GL_DST_COLOR:
3970 case GL_ONE_MINUS_DST_COLOR:
3971 case GL_SRC_ALPHA:
3972 case GL_ONE_MINUS_SRC_ALPHA:
3973 case GL_DST_ALPHA:
3974 case GL_ONE_MINUS_DST_ALPHA:
3975 case GL_CONSTANT_COLOR:
3976 case GL_ONE_MINUS_CONSTANT_COLOR:
3977 case GL_CONSTANT_ALPHA:
3978 case GL_ONE_MINUS_CONSTANT_ALPHA:
3979 case GL_SRC_ALPHA_SATURATE:
3980 return true;
3981
3982 default:
3983 return false;
3984 }
3985}
3986
3987static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
3988{
3989 switch (dstBlend)
3990 {
3991 case GL_ZERO:
3992 case GL_ONE:
3993 case GL_SRC_COLOR:
3994 case GL_ONE_MINUS_SRC_COLOR:
3995 case GL_DST_COLOR:
3996 case GL_ONE_MINUS_DST_COLOR:
3997 case GL_SRC_ALPHA:
3998 case GL_ONE_MINUS_SRC_ALPHA:
3999 case GL_DST_ALPHA:
4000 case GL_ONE_MINUS_DST_ALPHA:
4001 case GL_CONSTANT_COLOR:
4002 case GL_ONE_MINUS_CONSTANT_COLOR:
4003 case GL_CONSTANT_ALPHA:
4004 case GL_ONE_MINUS_CONSTANT_ALPHA:
4005 return true;
4006
4007 case GL_SRC_ALPHA_SATURATE:
4008 return (contextMajorVersion >= 3);
4009
4010 default:
4011 return false;
4012 }
4013}
4014
4015bool ValidateBlendFuncSeparate(ValidationContext *context,
4016 GLenum srcRGB,
4017 GLenum dstRGB,
4018 GLenum srcAlpha,
4019 GLenum dstAlpha)
4020{
4021 if (!ValidSrcBlendFunc(srcRGB))
4022 {
4023 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4024 return false;
4025 }
4026
4027 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4028 {
4029 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4030 return false;
4031 }
4032
4033 if (!ValidSrcBlendFunc(srcAlpha))
4034 {
4035 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4036 return false;
4037 }
4038
4039 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4040 {
4041 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4042 return false;
4043 }
4044
Frank Henigman146e8a12017-03-02 23:22:37 -05004045 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4046 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004047 {
4048 bool constantColorUsed =
4049 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4050 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4051
4052 bool constantAlphaUsed =
4053 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4054 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4055
4056 if (constantColorUsed && constantAlphaUsed)
4057 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004058 const char *msg;
4059 if (context->getExtensions().webglCompatibility)
4060 {
4061 msg =
4062 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4063 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4064 }
4065 else
4066 {
4067 msg =
4068 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4069 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4070 "implementation.";
4071 ERR() << msg;
4072 }
4073 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004074 return false;
4075 }
4076 }
4077
4078 return true;
4079}
4080
Geoff Langc339c4e2016-11-29 10:37:36 -05004081bool ValidateGetString(Context *context, GLenum name)
4082{
4083 switch (name)
4084 {
4085 case GL_VENDOR:
4086 case GL_RENDERER:
4087 case GL_VERSION:
4088 case GL_SHADING_LANGUAGE_VERSION:
4089 case GL_EXTENSIONS:
4090 break;
4091
4092 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4093 if (!context->getExtensions().requestExtension)
4094 {
4095 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4096 return false;
4097 }
4098 break;
4099
4100 default:
4101 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4102 return false;
4103 }
4104
4105 return true;
4106}
4107
Geoff Lang47c48082016-12-07 15:38:13 -05004108bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4109{
4110 if (width <= 0.0f || isNaN(width))
4111 {
4112 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
4113 return false;
4114 }
4115
4116 return true;
4117}
4118
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004119bool ValidateVertexAttribPointer(ValidationContext *context,
4120 GLuint index,
4121 GLint size,
4122 GLenum type,
4123 GLboolean normalized,
4124 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004125 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004126{
Shao80957d92017-02-20 21:25:59 +08004127 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004128 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004129 return false;
4130 }
4131
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004132 if (stride < 0)
4133 {
Shao80957d92017-02-20 21:25:59 +08004134 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004135 return false;
4136 }
4137
Shao80957d92017-02-20 21:25:59 +08004138 const Caps &caps = context->getCaps();
4139 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004140 {
Shao80957d92017-02-20 21:25:59 +08004141 if (stride > caps.maxVertexAttribStride)
4142 {
4143 context->handleError(
4144 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
4145 return false;
4146 }
4147
4148 if (index >= caps.maxVertexAttribBindings)
4149 {
4150 context->handleError(
4151 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
4152 return false;
4153 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004154 }
4155
4156 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4157 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4158 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4159 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004160 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4161 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004162 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004163 {
4164 context->handleError(
4165 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08004166 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004167 return false;
4168 }
4169
4170 if (context->getExtensions().webglCompatibility)
4171 {
4172 // WebGL 1.0 [Section 6.14] Fixed point support
4173 // The WebGL API does not support the GL_FIXED data type.
4174 if (type == GL_FIXED)
4175 {
4176 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4177 return false;
4178 }
4179
Geoff Lang2d62ab72017-03-23 16:54:40 -04004180 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004181 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004182 return false;
4183 }
4184 }
4185
4186 return true;
4187}
4188
Jamie Madill876429b2017-04-20 15:46:24 -04004189bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004190{
4191 if (context->getExtensions().webglCompatibility && zNear > zFar)
4192 {
4193 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4194 return false;
4195 }
4196
4197 return true;
4198}
4199
Jamie Madille8fb6402017-02-14 17:56:40 -05004200bool ValidateRenderbufferStorage(ValidationContext *context,
4201 GLenum target,
4202 GLenum internalformat,
4203 GLsizei width,
4204 GLsizei height)
4205{
4206 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4207 height);
4208}
4209
4210bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4211 GLenum target,
4212 GLsizei samples,
4213 GLenum internalformat,
4214 GLsizei width,
4215 GLsizei height)
4216{
4217 if (!context->getExtensions().framebufferMultisample)
4218 {
4219 context->handleError(
4220 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4221 return false;
4222 }
4223
4224 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4225 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4226 // generated.
4227 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4228 {
4229 context->handleError(Error(GL_INVALID_VALUE));
4230 return false;
4231 }
4232
4233 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4234 // the specified storage. This is different than ES 3.0 in which a sample number higher
4235 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4236 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4237 if (context->getClientMajorVersion() >= 3)
4238 {
4239 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4240 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4241 {
4242 context->handleError(Error(GL_OUT_OF_MEMORY));
4243 return false;
4244 }
4245 }
4246
4247 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4248 width, height);
4249}
4250
Jamie Madillc1d770e2017-04-13 17:31:24 -04004251bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4252{
4253 if (!ValidFramebufferTarget(target))
4254 {
4255 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4256 return false;
4257 }
4258
4259 return true;
4260}
4261
4262bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004263 GLfloat red,
4264 GLfloat green,
4265 GLfloat blue,
4266 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004267{
4268 return true;
4269}
4270
Jamie Madill876429b2017-04-20 15:46:24 -04004271bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004272{
4273 return true;
4274}
4275
4276bool ValidateClearStencil(ValidationContext *context, GLint s)
4277{
4278 return true;
4279}
4280
4281bool ValidateColorMask(ValidationContext *context,
4282 GLboolean red,
4283 GLboolean green,
4284 GLboolean blue,
4285 GLboolean alpha)
4286{
4287 return true;
4288}
4289
4290bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4291{
4292 return true;
4293}
4294
4295bool ValidateCreateProgram(ValidationContext *context)
4296{
4297 return true;
4298}
4299
4300bool ValidateCullFace(ValidationContext *context, GLenum mode)
4301{
4302 switch (mode)
4303 {
4304 case GL_FRONT:
4305 case GL_BACK:
4306 case GL_FRONT_AND_BACK:
4307 break;
4308
4309 default:
4310 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
4311 return false;
4312 }
4313
4314 return true;
4315}
4316
4317bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4318{
4319 if (program == 0)
4320 {
4321 return false;
4322 }
4323
4324 if (!context->getProgram(program))
4325 {
4326 if (context->getShader(program))
4327 {
4328 context->handleError(
4329 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
4330 return false;
4331 }
4332 else
4333 {
4334 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4335 return false;
4336 }
4337 }
4338
4339 return true;
4340}
4341
4342bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4343{
4344 if (shader == 0)
4345 {
4346 return false;
4347 }
4348
4349 if (!context->getShader(shader))
4350 {
4351 if (context->getProgram(shader))
4352 {
4353 context->handleError(
4354 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4355 return false;
4356 }
4357 else
4358 {
4359 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4360 return false;
4361 }
4362 }
4363
4364 return true;
4365}
4366
4367bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4368{
4369 switch (func)
4370 {
4371 case GL_NEVER:
4372 case GL_ALWAYS:
4373 case GL_LESS:
4374 case GL_LEQUAL:
4375 case GL_EQUAL:
4376 case GL_GREATER:
4377 case GL_GEQUAL:
4378 case GL_NOTEQUAL:
4379 break;
4380
4381 default:
4382 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4383 return false;
4384 }
4385
4386 return true;
4387}
4388
4389bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4390{
4391 return true;
4392}
4393
4394bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4395{
4396 Program *programObject = GetValidProgram(context, program);
4397 if (!programObject)
4398 {
4399 return false;
4400 }
4401
4402 Shader *shaderObject = GetValidShader(context, shader);
4403 if (!shaderObject)
4404 {
4405 return false;
4406 }
4407
4408 const Shader *attachedShader = nullptr;
4409
4410 switch (shaderObject->getType())
4411 {
4412 case GL_VERTEX_SHADER:
4413 {
4414 attachedShader = programObject->getAttachedVertexShader();
4415 break;
4416 }
4417 case GL_FRAGMENT_SHADER:
4418 {
4419 attachedShader = programObject->getAttachedFragmentShader();
4420 break;
4421 }
4422 case GL_COMPUTE_SHADER:
4423 {
4424 attachedShader = programObject->getAttachedComputeShader();
4425 break;
4426 }
4427 default:
4428 UNREACHABLE();
4429 return false;
4430 }
4431
4432 if (attachedShader != shaderObject)
4433 {
4434 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4435 return false;
4436 }
4437
4438 return true;
4439}
4440
4441bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4442{
4443 if (index >= MAX_VERTEX_ATTRIBS)
4444 {
4445 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4446 return false;
4447 }
4448
4449 return true;
4450}
4451
4452bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4453{
4454 if (index >= MAX_VERTEX_ATTRIBS)
4455 {
4456 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4457 return false;
4458 }
4459
4460 return true;
4461}
4462
4463bool ValidateFinish(ValidationContext *context)
4464{
4465 return true;
4466}
4467
4468bool ValidateFlush(ValidationContext *context)
4469{
4470 return true;
4471}
4472
4473bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4474{
4475 switch (mode)
4476 {
4477 case GL_CW:
4478 case GL_CCW:
4479 break;
4480 default:
4481 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4482 return false;
4483 }
4484
4485 return true;
4486}
4487
4488bool ValidateGetActiveAttrib(ValidationContext *context,
4489 GLuint program,
4490 GLuint index,
4491 GLsizei bufsize,
4492 GLsizei *length,
4493 GLint *size,
4494 GLenum *type,
4495 GLchar *name)
4496{
4497 if (bufsize < 0)
4498 {
4499 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4500 return false;
4501 }
4502
4503 Program *programObject = GetValidProgram(context, program);
4504
4505 if (!programObject)
4506 {
4507 return false;
4508 }
4509
4510 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4511 {
4512 context->handleError(
4513 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4514 return false;
4515 }
4516
4517 return true;
4518}
4519
4520bool ValidateGetActiveUniform(ValidationContext *context,
4521 GLuint program,
4522 GLuint index,
4523 GLsizei bufsize,
4524 GLsizei *length,
4525 GLint *size,
4526 GLenum *type,
4527 GLchar *name)
4528{
4529 if (bufsize < 0)
4530 {
4531 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4532 return false;
4533 }
4534
4535 Program *programObject = GetValidProgram(context, program);
4536
4537 if (!programObject)
4538 {
4539 return false;
4540 }
4541
4542 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4543 {
4544 context->handleError(
4545 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4546 return false;
4547 }
4548
4549 return true;
4550}
4551
4552bool ValidateGetAttachedShaders(ValidationContext *context,
4553 GLuint program,
4554 GLsizei maxcount,
4555 GLsizei *count,
4556 GLuint *shaders)
4557{
4558 if (maxcount < 0)
4559 {
4560 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4561 return false;
4562 }
4563
4564 Program *programObject = GetValidProgram(context, program);
4565
4566 if (!programObject)
4567 {
4568 return false;
4569 }
4570
4571 return true;
4572}
4573
4574bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4575{
4576 Program *programObject = GetValidProgram(context, program);
4577
4578 if (!programObject)
4579 {
4580 return false;
4581 }
4582
4583 if (!programObject->isLinked())
4584 {
4585 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4586 return false;
4587 }
4588
4589 return true;
4590}
4591
4592bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4593{
4594 GLenum nativeType;
4595 unsigned int numParams = 0;
4596 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4597}
4598
4599bool ValidateGetError(ValidationContext *context)
4600{
4601 return true;
4602}
4603
4604bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4605{
4606 GLenum nativeType;
4607 unsigned int numParams = 0;
4608 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4609}
4610
4611bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4612{
4613 GLenum nativeType;
4614 unsigned int numParams = 0;
4615 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4616}
4617
4618bool ValidateGetProgramInfoLog(ValidationContext *context,
4619 GLuint program,
4620 GLsizei bufsize,
4621 GLsizei *length,
4622 GLchar *infolog)
4623{
4624 if (bufsize < 0)
4625 {
4626 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4627 return false;
4628 }
4629
4630 Program *programObject = GetValidProgram(context, program);
4631 if (!programObject)
4632 {
4633 return false;
4634 }
4635
4636 return true;
4637}
4638
4639bool ValidateGetShaderInfoLog(ValidationContext *context,
4640 GLuint shader,
4641 GLsizei bufsize,
4642 GLsizei *length,
4643 GLchar *infolog)
4644{
4645 if (bufsize < 0)
4646 {
4647 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4648 return false;
4649 }
4650
4651 Shader *shaderObject = GetValidShader(context, shader);
4652 if (!shaderObject)
4653 {
4654 return false;
4655 }
4656
4657 return true;
4658}
4659
4660bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4661 GLenum shadertype,
4662 GLenum precisiontype,
4663 GLint *range,
4664 GLint *precision)
4665{
4666 switch (shadertype)
4667 {
4668 case GL_VERTEX_SHADER:
4669 case GL_FRAGMENT_SHADER:
4670 break;
4671 case GL_COMPUTE_SHADER:
4672 context->handleError(
4673 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4674 return false;
4675 default:
4676 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4677 return false;
4678 }
4679
4680 switch (precisiontype)
4681 {
4682 case GL_LOW_FLOAT:
4683 case GL_MEDIUM_FLOAT:
4684 case GL_HIGH_FLOAT:
4685 case GL_LOW_INT:
4686 case GL_MEDIUM_INT:
4687 case GL_HIGH_INT:
4688 break;
4689
4690 default:
4691 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4692 return false;
4693 }
4694
4695 return true;
4696}
4697
4698bool ValidateGetShaderSource(ValidationContext *context,
4699 GLuint shader,
4700 GLsizei bufsize,
4701 GLsizei *length,
4702 GLchar *source)
4703{
4704 if (bufsize < 0)
4705 {
4706 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4707 return false;
4708 }
4709
4710 Shader *shaderObject = GetValidShader(context, shader);
4711 if (!shaderObject)
4712 {
4713 return false;
4714 }
4715
4716 return true;
4717}
4718
4719bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4720{
4721 if (strstr(name, "gl_") == name)
4722 {
4723 return false;
4724 }
4725
4726 Program *programObject = GetValidProgram(context, program);
4727
4728 if (!programObject)
4729 {
4730 return false;
4731 }
4732
4733 if (!programObject->isLinked())
4734 {
4735 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4736 return false;
4737 }
4738
4739 return true;
4740}
4741
4742bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4743{
4744 switch (mode)
4745 {
4746 case GL_FASTEST:
4747 case GL_NICEST:
4748 case GL_DONT_CARE:
4749 break;
4750
4751 default:
4752 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4753 return false;
4754 }
4755
4756 switch (target)
4757 {
4758 case GL_GENERATE_MIPMAP_HINT:
4759 break;
4760
4761 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4762 if (!context->getExtensions().standardDerivatives)
4763 {
4764 context->handleError(
4765 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4766 return false;
4767 }
4768 break;
4769
4770 default:
4771 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4772 return false;
4773 }
4774
4775 return true;
4776}
4777
4778bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4779{
4780 return true;
4781}
4782
4783bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4784{
4785 return true;
4786}
4787
4788bool ValidateIsProgram(ValidationContext *context, GLuint program)
4789{
4790 return true;
4791}
4792
4793bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4794{
4795 return true;
4796}
4797
4798bool ValidateIsShader(ValidationContext *context, GLuint shader)
4799{
4800 return true;
4801}
4802
4803bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4804{
4805 return true;
4806}
4807
4808bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4809{
4810 if (context->getClientMajorVersion() < 3)
4811 {
4812 switch (pname)
4813 {
4814 case GL_UNPACK_IMAGE_HEIGHT:
4815 case GL_UNPACK_SKIP_IMAGES:
4816 context->handleError(Error(GL_INVALID_ENUM));
4817 return false;
4818
4819 case GL_UNPACK_ROW_LENGTH:
4820 case GL_UNPACK_SKIP_ROWS:
4821 case GL_UNPACK_SKIP_PIXELS:
4822 if (!context->getExtensions().unpackSubimage)
4823 {
4824 context->handleError(Error(GL_INVALID_ENUM));
4825 return false;
4826 }
4827 break;
4828
4829 case GL_PACK_ROW_LENGTH:
4830 case GL_PACK_SKIP_ROWS:
4831 case GL_PACK_SKIP_PIXELS:
4832 if (!context->getExtensions().packSubimage)
4833 {
4834 context->handleError(Error(GL_INVALID_ENUM));
4835 return false;
4836 }
4837 break;
4838 }
4839 }
4840
4841 if (param < 0)
4842 {
4843 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4844 return false;
4845 }
4846
4847 switch (pname)
4848 {
4849 case GL_UNPACK_ALIGNMENT:
4850 if (param != 1 && param != 2 && param != 4 && param != 8)
4851 {
4852 context->handleError(Error(GL_INVALID_VALUE));
4853 return false;
4854 }
4855 break;
4856
4857 case GL_PACK_ALIGNMENT:
4858 if (param != 1 && param != 2 && param != 4 && param != 8)
4859 {
4860 context->handleError(Error(GL_INVALID_VALUE));
4861 return false;
4862 }
4863 break;
4864
4865 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4866 case GL_UNPACK_ROW_LENGTH:
4867 case GL_UNPACK_IMAGE_HEIGHT:
4868 case GL_UNPACK_SKIP_IMAGES:
4869 case GL_UNPACK_SKIP_ROWS:
4870 case GL_UNPACK_SKIP_PIXELS:
4871 case GL_PACK_ROW_LENGTH:
4872 case GL_PACK_SKIP_ROWS:
4873 case GL_PACK_SKIP_PIXELS:
4874 break;
4875
4876 default:
4877 context->handleError(Error(GL_INVALID_ENUM));
4878 return false;
4879 }
4880
4881 return true;
4882}
4883
4884bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4885{
4886 return true;
4887}
4888
4889bool ValidateReleaseShaderCompiler(ValidationContext *context)
4890{
4891 return true;
4892}
4893
Jamie Madill876429b2017-04-20 15:46:24 -04004894bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004895{
4896 return true;
4897}
4898
4899bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4900{
4901 if (width < 0 || height < 0)
4902 {
4903 context->handleError(
4904 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4905 return false;
4906 }
4907
4908 return true;
4909}
4910
4911bool ValidateShaderBinary(ValidationContext *context,
4912 GLsizei n,
4913 const GLuint *shaders,
4914 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04004915 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04004916 GLsizei length)
4917{
4918 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4919 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4920 shaderBinaryFormats.end())
4921 {
4922 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4923 return false;
4924 }
4925
4926 return true;
4927}
4928
4929bool ValidateShaderSource(ValidationContext *context,
4930 GLuint shader,
4931 GLsizei count,
4932 const GLchar *const *string,
4933 const GLint *length)
4934{
4935 if (count < 0)
4936 {
4937 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4938 return false;
4939 }
4940
4941 Shader *shaderObject = GetValidShader(context, shader);
4942 if (!shaderObject)
4943 {
4944 return false;
4945 }
4946
4947 return true;
4948}
4949
4950bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4951{
4952 if (!IsValidStencilFunc(func))
4953 {
4954 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4955 return false;
4956 }
4957
4958 return true;
4959}
4960
4961bool ValidateStencilFuncSeparate(ValidationContext *context,
4962 GLenum face,
4963 GLenum func,
4964 GLint ref,
4965 GLuint mask)
4966{
4967 if (!IsValidStencilFace(face))
4968 {
4969 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4970 return false;
4971 }
4972
4973 if (!IsValidStencilFunc(func))
4974 {
4975 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4976 return false;
4977 }
4978
4979 return true;
4980}
4981
4982bool ValidateStencilMask(ValidationContext *context, GLuint mask)
4983{
4984 return true;
4985}
4986
4987bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
4988{
4989 if (!IsValidStencilFace(face))
4990 {
4991 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4992 return false;
4993 }
4994
4995 return true;
4996}
4997
4998bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
4999{
5000 if (!IsValidStencilOp(fail))
5001 {
5002 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
5003 return false;
5004 }
5005
5006 if (!IsValidStencilOp(zfail))
5007 {
5008 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
5009 return false;
5010 }
5011
5012 if (!IsValidStencilOp(zpass))
5013 {
5014 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
5015 return false;
5016 }
5017
5018 return true;
5019}
5020
5021bool ValidateStencilOpSeparate(ValidationContext *context,
5022 GLenum face,
5023 GLenum fail,
5024 GLenum zfail,
5025 GLenum zpass)
5026{
5027 if (!IsValidStencilFace(face))
5028 {
5029 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5030 return false;
5031 }
5032
5033 return ValidateStencilOp(context, fail, zfail, zpass);
5034}
5035
5036bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5037{
5038 return ValidateUniform(context, GL_FLOAT, location, 1);
5039}
5040
5041bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5042{
5043 return ValidateUniform(context, GL_FLOAT, location, count);
5044}
5045
Jamie Madillbe849e42017-05-02 15:49:00 -04005046bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5047{
5048 return ValidateUniform1iv(context, location, 1, &x);
5049}
5050
Jamie Madillc1d770e2017-04-13 17:31:24 -04005051bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5052{
5053 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5054}
5055
5056bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5057{
5058 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5059}
5060
5061bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5062{
5063 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5064}
5065
5066bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5067{
5068 return ValidateUniform(context, GL_INT_VEC2, location, count);
5069}
5070
5071bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5072{
5073 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5074}
5075
5076bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5077{
5078 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5079}
5080
5081bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5082{
5083 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5084}
5085
5086bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5087{
5088 return ValidateUniform(context, GL_INT_VEC3, location, count);
5089}
5090
5091bool ValidateUniform4f(ValidationContext *context,
5092 GLint location,
5093 GLfloat x,
5094 GLfloat y,
5095 GLfloat z,
5096 GLfloat w)
5097{
5098 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5099}
5100
5101bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5102{
5103 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5104}
5105
5106bool ValidateUniform4i(ValidationContext *context,
5107 GLint location,
5108 GLint x,
5109 GLint y,
5110 GLint z,
5111 GLint w)
5112{
5113 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5114}
5115
5116bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5117{
5118 return ValidateUniform(context, GL_INT_VEC4, location, count);
5119}
5120
5121bool ValidateUniformMatrix2fv(ValidationContext *context,
5122 GLint location,
5123 GLsizei count,
5124 GLboolean transpose,
5125 const GLfloat *value)
5126{
5127 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5128}
5129
5130bool ValidateUniformMatrix3fv(ValidationContext *context,
5131 GLint location,
5132 GLsizei count,
5133 GLboolean transpose,
5134 const GLfloat *value)
5135{
5136 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5137}
5138
5139bool ValidateUniformMatrix4fv(ValidationContext *context,
5140 GLint location,
5141 GLsizei count,
5142 GLboolean transpose,
5143 const GLfloat *value)
5144{
5145 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5146}
5147
5148bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5149{
5150 Program *programObject = GetValidProgram(context, program);
5151
5152 if (!programObject)
5153 {
5154 return false;
5155 }
5156
5157 return true;
5158}
5159
5160bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5161{
5162 if (index >= MAX_VERTEX_ATTRIBS)
5163 {
5164 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
5165 return false;
5166 }
5167
5168 return true;
5169}
5170
5171bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5172{
5173 return ValidateVertexAttribIndex(context, index);
5174}
5175
5176bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5177{
5178 return ValidateVertexAttribIndex(context, index);
5179}
5180
5181bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5182{
5183 return ValidateVertexAttribIndex(context, index);
5184}
5185
5186bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5187{
5188 return ValidateVertexAttribIndex(context, index);
5189}
5190
5191bool ValidateVertexAttrib3f(ValidationContext *context,
5192 GLuint index,
5193 GLfloat x,
5194 GLfloat y,
5195 GLfloat z)
5196{
5197 return ValidateVertexAttribIndex(context, index);
5198}
5199
5200bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5201{
5202 return ValidateVertexAttribIndex(context, index);
5203}
5204
5205bool ValidateVertexAttrib4f(ValidationContext *context,
5206 GLuint index,
5207 GLfloat x,
5208 GLfloat y,
5209 GLfloat z,
5210 GLfloat w)
5211{
5212 return ValidateVertexAttribIndex(context, index);
5213}
5214
5215bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5216{
5217 return ValidateVertexAttribIndex(context, index);
5218}
5219
5220bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5221{
5222 if (width < 0 || height < 0)
5223 {
5224 context->handleError(
5225 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
5226 return false;
5227 }
5228
5229 return true;
5230}
5231
5232bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5233{
5234 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5235}
5236
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005237bool ValidateDrawElements(ValidationContext *context,
5238 GLenum mode,
5239 GLsizei count,
5240 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005241 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005242{
5243 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5244}
5245
Jamie Madillbe849e42017-05-02 15:49:00 -04005246bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5247 GLenum target,
5248 GLenum attachment,
5249 GLenum pname,
5250 GLint *params)
5251{
5252 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5253 nullptr);
5254}
5255
5256bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5257{
5258 return ValidateGetProgramivBase(context, program, pname, nullptr);
5259}
5260
5261bool ValidateCopyTexImage2D(ValidationContext *context,
5262 GLenum target,
5263 GLint level,
5264 GLenum internalformat,
5265 GLint x,
5266 GLint y,
5267 GLsizei width,
5268 GLsizei height,
5269 GLint border)
5270{
5271 if (context->getClientMajorVersion() < 3)
5272 {
5273 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5274 0, x, y, width, height, border);
5275 }
5276
5277 ASSERT(context->getClientMajorVersion() == 3);
5278 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5279 0, x, y, width, height, border);
5280}
5281
5282bool ValidateCopyTexSubImage2D(Context *context,
5283 GLenum target,
5284 GLint level,
5285 GLint xoffset,
5286 GLint yoffset,
5287 GLint x,
5288 GLint y,
5289 GLsizei width,
5290 GLsizei height)
5291{
5292 if (context->getClientMajorVersion() < 3)
5293 {
5294 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5295 yoffset, x, y, width, height, 0);
5296 }
5297
5298 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5299 yoffset, 0, x, y, width, height, 0);
5300}
5301
5302bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5303{
5304 return ValidateGenOrDelete(context, n);
5305}
5306
5307bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5308{
5309 return ValidateGenOrDelete(context, n);
5310}
5311
5312bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5313{
5314 return ValidateGenOrDelete(context, n);
5315}
5316
5317bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5318{
5319 return ValidateGenOrDelete(context, n);
5320}
5321
5322bool ValidateDisable(Context *context, GLenum cap)
5323{
5324 if (!ValidCap(context, cap, false))
5325 {
5326 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5327 return false;
5328 }
5329
5330 return true;
5331}
5332
5333bool ValidateEnable(Context *context, GLenum cap)
5334{
5335 if (!ValidCap(context, cap, false))
5336 {
5337 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5338 return false;
5339 }
5340
5341 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5342 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5343 {
5344 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5345 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
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() << errorMessage;
5350 return false;
5351 }
5352
5353 return true;
5354}
5355
5356bool ValidateFramebufferRenderbuffer(Context *context,
5357 GLenum target,
5358 GLenum attachment,
5359 GLenum renderbuffertarget,
5360 GLuint renderbuffer)
5361{
5362 if (!ValidFramebufferTarget(target) ||
5363 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5364 {
5365 context->handleError(Error(GL_INVALID_ENUM));
5366 return false;
5367 }
5368
5369 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5370 renderbuffertarget, renderbuffer);
5371}
5372
5373bool ValidateFramebufferTexture2D(Context *context,
5374 GLenum target,
5375 GLenum attachment,
5376 GLenum textarget,
5377 GLuint texture,
5378 GLint level)
5379{
5380 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5381 // extension
5382 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5383 level != 0)
5384 {
5385 context->handleError(Error(GL_INVALID_VALUE));
5386 return false;
5387 }
5388
5389 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5390 {
5391 return false;
5392 }
5393
5394 if (texture != 0)
5395 {
5396 gl::Texture *tex = context->getTexture(texture);
5397 ASSERT(tex);
5398
5399 const gl::Caps &caps = context->getCaps();
5400
5401 switch (textarget)
5402 {
5403 case GL_TEXTURE_2D:
5404 {
5405 if (level > gl::log2(caps.max2DTextureSize))
5406 {
5407 context->handleError(Error(GL_INVALID_VALUE));
5408 return false;
5409 }
5410 if (tex->getTarget() != GL_TEXTURE_2D)
5411 {
5412 context->handleError(Error(GL_INVALID_OPERATION,
5413 "Textarget must match the texture target type."));
5414 return false;
5415 }
5416 }
5417 break;
5418
5419 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5420 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5421 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5422 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5423 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5424 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5425 {
5426 if (level > gl::log2(caps.maxCubeMapTextureSize))
5427 {
5428 context->handleError(Error(GL_INVALID_VALUE));
5429 return false;
5430 }
5431 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5432 {
5433 context->handleError(Error(GL_INVALID_OPERATION,
5434 "Textarget must match the texture target type."));
5435 return false;
5436 }
5437 }
5438 break;
5439
5440 case GL_TEXTURE_2D_MULTISAMPLE:
5441 {
5442 if (context->getClientVersion() < ES_3_1)
5443 {
5444 context->handleError(Error(GL_INVALID_OPERATION,
5445 "Texture target requires at least OpenGL ES 3.1."));
5446 return false;
5447 }
5448
5449 if (level != 0)
5450 {
5451 context->handleError(
5452 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
5453 return false;
5454 }
5455 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5456 {
5457 context->handleError(Error(GL_INVALID_OPERATION,
5458 "Textarget must match the texture target type."));
5459 return false;
5460 }
5461 }
5462 break;
5463
5464 default:
5465 context->handleError(Error(GL_INVALID_ENUM));
5466 return false;
5467 }
5468
5469 const Format &format = tex->getFormat(textarget, level);
5470 if (format.info->compressed)
5471 {
5472 context->handleError(Error(GL_INVALID_OPERATION));
5473 return false;
5474 }
5475 }
5476
5477 return true;
5478}
5479
5480bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5481{
5482 return ValidateGenOrDelete(context, n);
5483}
5484
5485bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5486{
5487 return ValidateGenOrDelete(context, n);
5488}
5489
5490bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5491{
5492 return ValidateGenOrDelete(context, n);
5493}
5494
5495bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5496{
5497 return ValidateGenOrDelete(context, n);
5498}
5499
5500bool ValidateGenerateMipmap(Context *context, GLenum target)
5501{
5502 if (!ValidTextureTarget(context, target))
5503 {
5504 context->handleError(Error(GL_INVALID_ENUM));
5505 return false;
5506 }
5507
5508 Texture *texture = context->getTargetTexture(target);
5509
5510 if (texture == nullptr)
5511 {
5512 context->handleError(Error(GL_INVALID_OPERATION));
5513 return false;
5514 }
5515
5516 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5517
5518 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5519 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5520 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5521 {
5522 context->handleError(Error(GL_INVALID_OPERATION));
5523 return false;
5524 }
5525
5526 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5527 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5528 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5529
5530 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5531 // unsized formats or that are color renderable and filterable. Since we do not track if
5532 // the texture was created with sized or unsized format (only sized formats are stored),
5533 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5534 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5535 // textures since they're the only texture format that can be created with unsized formats
5536 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5537 // was the last version to use add them.
5538 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5539 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5540 {
5541 context->handleError(Error(GL_INVALID_OPERATION));
5542 return false;
5543 }
5544
5545 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
5546 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
5547 {
5548 context->handleError(Error(GL_INVALID_OPERATION));
5549 return false;
5550 }
5551
5552 // Non-power of 2 ES2 check
5553 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5554 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5555 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5556 {
5557 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
5558 context->handleError(Error(GL_INVALID_OPERATION));
5559 return false;
5560 }
5561
5562 // Cube completeness check
5563 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5564 {
5565 context->handleError(Error(GL_INVALID_OPERATION));
5566 return false;
5567 }
5568
5569 return true;
5570}
5571
5572bool ValidateGetBufferParameteriv(ValidationContext *context,
5573 GLenum target,
5574 GLenum pname,
5575 GLint *params)
5576{
5577 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5578}
5579
5580bool ValidateGetRenderbufferParameteriv(Context *context,
5581 GLenum target,
5582 GLenum pname,
5583 GLint *params)
5584{
5585 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5586}
5587
5588bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5589{
5590 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5591}
5592
5593bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5594{
5595 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5596}
5597
5598bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5599{
5600 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5601}
5602
5603bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5604{
5605 return ValidateGetUniformBase(context, program, location);
5606}
5607
5608bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5609{
5610 return ValidateGetUniformBase(context, program, location);
5611}
5612
5613bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5614{
5615 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5616}
5617
5618bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5619{
5620 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5621}
5622
5623bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5624{
5625 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5626}
5627
5628bool ValidateIsEnabled(Context *context, GLenum cap)
5629{
5630 if (!ValidCap(context, cap, true))
5631 {
5632 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5633 return false;
5634 }
5635
5636 return true;
5637}
5638
5639bool ValidateLinkProgram(Context *context, GLuint program)
5640{
5641 if (context->hasActiveTransformFeedback(program))
5642 {
5643 // ES 3.0.4 section 2.15 page 91
5644 context->handleError(Error(GL_INVALID_OPERATION,
5645 "Cannot link program while program is associated with an active "
5646 "transform feedback object."));
5647 return false;
5648 }
5649
5650 Program *programObject = GetValidProgram(context, program);
5651 if (!programObject)
5652 {
5653 return false;
5654 }
5655
5656 return true;
5657}
5658
5659bool ValidateReadPixels(ValidationContext *context,
5660 GLint x,
5661 GLint y,
5662 GLsizei width,
5663 GLsizei height,
5664 GLenum format,
5665 GLenum type,
5666 void *pixels)
5667{
5668 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5669 nullptr, pixels);
5670}
5671
5672bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5673{
5674 return ValidateTexParameterBase(context, target, pname, -1, &param);
5675}
5676
5677bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5678{
5679 return ValidateTexParameterBase(context, target, pname, -1, params);
5680}
5681
5682bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5683{
5684 return ValidateTexParameterBase(context, target, pname, -1, &param);
5685}
5686
5687bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5688{
5689 return ValidateTexParameterBase(context, target, pname, -1, params);
5690}
5691
5692bool ValidateUseProgram(Context *context, GLuint program)
5693{
5694 if (program != 0)
5695 {
5696 Program *programObject = context->getProgram(program);
5697 if (!programObject)
5698 {
5699 // ES 3.1.0 section 7.3 page 72
5700 if (context->getShader(program))
5701 {
5702 context->handleError(
5703 Error(GL_INVALID_OPERATION,
5704 "Attempted to use a single shader instead of a shader program."));
5705 return false;
5706 }
5707 else
5708 {
5709 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
5710 return false;
5711 }
5712 }
5713 if (!programObject->isLinked())
5714 {
5715 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
5716 return false;
5717 }
5718 }
5719 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5720 {
5721 // ES 3.0.4 section 2.15 page 91
5722 context->handleError(
5723 Error(GL_INVALID_OPERATION,
5724 "Cannot change active program while transform feedback is unpaused."));
5725 return false;
5726 }
5727
5728 return true;
5729}
5730
Jamie Madillc29968b2016-01-20 11:17:23 -05005731} // namespace gl