blob: 1d73ae1aab0df0fc1d08002d270a523d9d394c44 [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:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001293 if (!context->getExtensions().textureRG)
1294 {
1295 context->handleError(Error(GL_INVALID_ENUM));
1296 return false;
1297 }
1298 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001299 case GL_R16F_EXT:
1300 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001301 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1302 {
1303 context->handleError(Error(GL_INVALID_ENUM));
1304 return false;
1305 }
1306 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001307 case GL_R32F_EXT:
1308 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001309 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001310 {
1311 context->handleError(Error(GL_INVALID_ENUM));
1312 return false;
1313 }
1314 break;
1315 case GL_DEPTH_COMPONENT16:
1316 case GL_DEPTH_COMPONENT32_OES:
1317 case GL_DEPTH24_STENCIL8_OES:
1318 if (!context->getExtensions().depthTextures)
1319 {
1320 context->handleError(Error(GL_INVALID_ENUM));
1321 return false;
1322 }
1323 if (target != GL_TEXTURE_2D)
1324 {
1325 context->handleError(Error(GL_INVALID_OPERATION));
1326 return false;
1327 }
1328 // ANGLE_depth_texture only supports 1-level textures
1329 if (levels != 1)
1330 {
1331 context->handleError(Error(GL_INVALID_OPERATION));
1332 return false;
1333 }
1334 break;
1335 default:
1336 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 }
1338
Geoff Lang691e58c2014-12-19 17:03:25 -05001339 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001340 if (!texture || texture->id() == 0)
1341 {
Jamie Madill437fa652016-05-03 15:13:24 -04001342 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 }
1345
Geoff Lang69cce582015-09-17 13:20:36 -04001346 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 {
Jamie Madill437fa652016-05-03 15:13:24 -04001348 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001349 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 }
1351
1352 return true;
1353}
1354
He Yunchaoced53ae2016-11-29 15:00:51 +08001355bool ValidateDiscardFramebufferEXT(Context *context,
1356 GLenum target,
1357 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001358 const GLenum *attachments)
1359{
Jamie Madillc29968b2016-01-20 11:17:23 -05001360 if (!context->getExtensions().discardFramebuffer)
1361 {
Jamie Madill437fa652016-05-03 15:13:24 -04001362 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001363 return false;
1364 }
1365
Austin Kinross08332632015-05-05 13:35:47 -07001366 bool defaultFramebuffer = false;
1367
1368 switch (target)
1369 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001370 case GL_FRAMEBUFFER:
1371 defaultFramebuffer =
1372 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1373 break;
1374 default:
1375 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1376 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001377 }
1378
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1380 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001381}
1382
Austin Kinrossbc781f32015-10-26 09:27:38 -07001383bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1384{
1385 if (!context->getExtensions().vertexArrayObject)
1386 {
Jamie Madill437fa652016-05-03 15:13:24 -04001387 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001388 return false;
1389 }
1390
1391 return ValidateBindVertexArrayBase(context, array);
1392}
1393
1394bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1395{
1396 if (!context->getExtensions().vertexArrayObject)
1397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001399 return false;
1400 }
1401
Olli Etuaho41997e72016-03-10 13:38:39 +02001402 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001403}
1404
1405bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1406{
1407 if (!context->getExtensions().vertexArrayObject)
1408 {
Jamie Madill437fa652016-05-03 15:13:24 -04001409 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001410 return false;
1411 }
1412
Olli Etuaho41997e72016-03-10 13:38:39 +02001413 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001414}
1415
1416bool ValidateIsVertexArrayOES(Context *context)
1417{
1418 if (!context->getExtensions().vertexArrayObject)
1419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001421 return false;
1422 }
1423
1424 return true;
1425}
Geoff Langc5629752015-12-07 16:29:04 -05001426
1427bool ValidateProgramBinaryOES(Context *context,
1428 GLuint program,
1429 GLenum binaryFormat,
1430 const void *binary,
1431 GLint length)
1432{
1433 if (!context->getExtensions().getProgramBinary)
1434 {
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001436 return false;
1437 }
1438
1439 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1440}
1441
1442bool ValidateGetProgramBinaryOES(Context *context,
1443 GLuint program,
1444 GLsizei bufSize,
1445 GLsizei *length,
1446 GLenum *binaryFormat,
1447 void *binary)
1448{
1449 if (!context->getExtensions().getProgramBinary)
1450 {
Jamie Madill437fa652016-05-03 15:13:24 -04001451 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001452 return false;
1453 }
1454
1455 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1456}
Geoff Lange102fee2015-12-10 11:23:30 -05001457
Geoff Lang70d0f492015-12-10 17:45:46 -05001458static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1459{
1460 switch (source)
1461 {
1462 case GL_DEBUG_SOURCE_API:
1463 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1464 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1465 case GL_DEBUG_SOURCE_OTHER:
1466 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1467 return !mustBeThirdPartyOrApplication;
1468
1469 case GL_DEBUG_SOURCE_THIRD_PARTY:
1470 case GL_DEBUG_SOURCE_APPLICATION:
1471 return true;
1472
1473 default:
1474 return false;
1475 }
1476}
1477
1478static bool ValidDebugType(GLenum type)
1479{
1480 switch (type)
1481 {
1482 case GL_DEBUG_TYPE_ERROR:
1483 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1484 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1485 case GL_DEBUG_TYPE_PERFORMANCE:
1486 case GL_DEBUG_TYPE_PORTABILITY:
1487 case GL_DEBUG_TYPE_OTHER:
1488 case GL_DEBUG_TYPE_MARKER:
1489 case GL_DEBUG_TYPE_PUSH_GROUP:
1490 case GL_DEBUG_TYPE_POP_GROUP:
1491 return true;
1492
1493 default:
1494 return false;
1495 }
1496}
1497
1498static bool ValidDebugSeverity(GLenum severity)
1499{
1500 switch (severity)
1501 {
1502 case GL_DEBUG_SEVERITY_HIGH:
1503 case GL_DEBUG_SEVERITY_MEDIUM:
1504 case GL_DEBUG_SEVERITY_LOW:
1505 case GL_DEBUG_SEVERITY_NOTIFICATION:
1506 return true;
1507
1508 default:
1509 return false;
1510 }
1511}
1512
Geoff Lange102fee2015-12-10 11:23:30 -05001513bool ValidateDebugMessageControlKHR(Context *context,
1514 GLenum source,
1515 GLenum type,
1516 GLenum severity,
1517 GLsizei count,
1518 const GLuint *ids,
1519 GLboolean enabled)
1520{
1521 if (!context->getExtensions().debug)
1522 {
Jamie Madill437fa652016-05-03 15:13:24 -04001523 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001524 return false;
1525 }
1526
Geoff Lang70d0f492015-12-10 17:45:46 -05001527 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001530 return false;
1531 }
1532
1533 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001536 return false;
1537 }
1538
1539 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1540 {
Jamie Madill437fa652016-05-03 15:13:24 -04001541 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001542 return false;
1543 }
1544
1545 if (count > 0)
1546 {
1547 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1548 {
Jamie Madill437fa652016-05-03 15:13:24 -04001549 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001550 GL_INVALID_OPERATION,
1551 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1552 return false;
1553 }
1554
1555 if (severity != GL_DONT_CARE)
1556 {
Jamie Madill437fa652016-05-03 15:13:24 -04001557 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001558 Error(GL_INVALID_OPERATION,
1559 "If count is greater than zero, severity must be GL_DONT_CARE."));
1560 return false;
1561 }
1562 }
1563
Geoff Lange102fee2015-12-10 11:23:30 -05001564 return true;
1565}
1566
1567bool ValidateDebugMessageInsertKHR(Context *context,
1568 GLenum source,
1569 GLenum type,
1570 GLuint id,
1571 GLenum severity,
1572 GLsizei length,
1573 const GLchar *buf)
1574{
1575 if (!context->getExtensions().debug)
1576 {
Jamie Madill437fa652016-05-03 15:13:24 -04001577 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001578 return false;
1579 }
1580
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001581 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001582 {
1583 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1584 // not generate an error.
1585 return false;
1586 }
1587
1588 if (!ValidDebugSeverity(severity))
1589 {
Jamie Madill437fa652016-05-03 15:13:24 -04001590 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001591 return false;
1592 }
1593
1594 if (!ValidDebugType(type))
1595 {
Jamie Madill437fa652016-05-03 15:13:24 -04001596 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001597 return false;
1598 }
1599
1600 if (!ValidDebugSource(source, true))
1601 {
Jamie Madill437fa652016-05-03 15:13:24 -04001602 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001603 return false;
1604 }
1605
1606 size_t messageLength = (length < 0) ? strlen(buf) : length;
1607 if (messageLength > context->getExtensions().maxDebugMessageLength)
1608 {
Jamie Madill437fa652016-05-03 15:13:24 -04001609 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001610 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1611 return false;
1612 }
1613
Geoff Lange102fee2015-12-10 11:23:30 -05001614 return true;
1615}
1616
1617bool ValidateDebugMessageCallbackKHR(Context *context,
1618 GLDEBUGPROCKHR callback,
1619 const void *userParam)
1620{
1621 if (!context->getExtensions().debug)
1622 {
Jamie Madill437fa652016-05-03 15:13:24 -04001623 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001624 return false;
1625 }
1626
Geoff Lange102fee2015-12-10 11:23:30 -05001627 return true;
1628}
1629
1630bool ValidateGetDebugMessageLogKHR(Context *context,
1631 GLuint count,
1632 GLsizei bufSize,
1633 GLenum *sources,
1634 GLenum *types,
1635 GLuint *ids,
1636 GLenum *severities,
1637 GLsizei *lengths,
1638 GLchar *messageLog)
1639{
1640 if (!context->getExtensions().debug)
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001643 return false;
1644 }
1645
Geoff Lang70d0f492015-12-10 17:45:46 -05001646 if (bufSize < 0 && messageLog != nullptr)
1647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001649 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1650 return false;
1651 }
1652
Geoff Lange102fee2015-12-10 11:23:30 -05001653 return true;
1654}
1655
1656bool ValidatePushDebugGroupKHR(Context *context,
1657 GLenum source,
1658 GLuint id,
1659 GLsizei length,
1660 const GLchar *message)
1661{
1662 if (!context->getExtensions().debug)
1663 {
Jamie Madill437fa652016-05-03 15:13:24 -04001664 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001665 return false;
1666 }
1667
Geoff Lang70d0f492015-12-10 17:45:46 -05001668 if (!ValidDebugSource(source, true))
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001671 return false;
1672 }
1673
1674 size_t messageLength = (length < 0) ? strlen(message) : length;
1675 if (messageLength > context->getExtensions().maxDebugMessageLength)
1676 {
Jamie Madill437fa652016-05-03 15:13:24 -04001677 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001678 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1679 return false;
1680 }
1681
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001682 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001683 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001686 Error(GL_STACK_OVERFLOW,
1687 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1688 return false;
1689 }
1690
Geoff Lange102fee2015-12-10 11:23:30 -05001691 return true;
1692}
1693
1694bool ValidatePopDebugGroupKHR(Context *context)
1695{
1696 if (!context->getExtensions().debug)
1697 {
Jamie Madill437fa652016-05-03 15:13:24 -04001698 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001699 return false;
1700 }
1701
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001702 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001703 if (currentStackSize <= 1)
1704 {
Jamie Madill437fa652016-05-03 15:13:24 -04001705 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001706 return false;
1707 }
1708
1709 return true;
1710}
1711
1712static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1713{
1714 switch (identifier)
1715 {
1716 case GL_BUFFER:
1717 if (context->getBuffer(name) == nullptr)
1718 {
Jamie Madill437fa652016-05-03 15:13:24 -04001719 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001720 return false;
1721 }
1722 return true;
1723
1724 case GL_SHADER:
1725 if (context->getShader(name) == nullptr)
1726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001728 return false;
1729 }
1730 return true;
1731
1732 case GL_PROGRAM:
1733 if (context->getProgram(name) == nullptr)
1734 {
Jamie Madill437fa652016-05-03 15:13:24 -04001735 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001736 return false;
1737 }
1738 return true;
1739
1740 case GL_VERTEX_ARRAY:
1741 if (context->getVertexArray(name) == nullptr)
1742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001744 return false;
1745 }
1746 return true;
1747
1748 case GL_QUERY:
1749 if (context->getQuery(name) == nullptr)
1750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001752 return false;
1753 }
1754 return true;
1755
1756 case GL_TRANSFORM_FEEDBACK:
1757 if (context->getTransformFeedback(name) == nullptr)
1758 {
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001760 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1761 return false;
1762 }
1763 return true;
1764
1765 case GL_SAMPLER:
1766 if (context->getSampler(name) == nullptr)
1767 {
Jamie Madill437fa652016-05-03 15:13:24 -04001768 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001769 return false;
1770 }
1771 return true;
1772
1773 case GL_TEXTURE:
1774 if (context->getTexture(name) == nullptr)
1775 {
Jamie Madill437fa652016-05-03 15:13:24 -04001776 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001777 return false;
1778 }
1779 return true;
1780
1781 case GL_RENDERBUFFER:
1782 if (context->getRenderbuffer(name) == nullptr)
1783 {
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001785 return false;
1786 }
1787 return true;
1788
1789 case GL_FRAMEBUFFER:
1790 if (context->getFramebuffer(name) == nullptr)
1791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001793 return false;
1794 }
1795 return true;
1796
1797 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001799 return false;
1800 }
Geoff Lange102fee2015-12-10 11:23:30 -05001801}
1802
Martin Radev9d901792016-07-15 15:58:58 +03001803static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1804{
1805 size_t labelLength = 0;
1806
1807 if (length < 0)
1808 {
1809 if (label != nullptr)
1810 {
1811 labelLength = strlen(label);
1812 }
1813 }
1814 else
1815 {
1816 labelLength = static_cast<size_t>(length);
1817 }
1818
1819 if (labelLength > context->getExtensions().maxLabelLength)
1820 {
1821 context->handleError(
1822 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1823 return false;
1824 }
1825
1826 return true;
1827}
1828
Geoff Lange102fee2015-12-10 11:23:30 -05001829bool ValidateObjectLabelKHR(Context *context,
1830 GLenum identifier,
1831 GLuint name,
1832 GLsizei length,
1833 const GLchar *label)
1834{
1835 if (!context->getExtensions().debug)
1836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001838 return false;
1839 }
1840
Geoff Lang70d0f492015-12-10 17:45:46 -05001841 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1842 {
1843 return false;
1844 }
1845
Martin Radev9d901792016-07-15 15:58:58 +03001846 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001847 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001848 return false;
1849 }
1850
Geoff Lange102fee2015-12-10 11:23:30 -05001851 return true;
1852}
1853
1854bool ValidateGetObjectLabelKHR(Context *context,
1855 GLenum identifier,
1856 GLuint name,
1857 GLsizei bufSize,
1858 GLsizei *length,
1859 GLchar *label)
1860{
1861 if (!context->getExtensions().debug)
1862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001864 return false;
1865 }
1866
Geoff Lang70d0f492015-12-10 17:45:46 -05001867 if (bufSize < 0)
1868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001870 return false;
1871 }
1872
1873 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1874 {
1875 return false;
1876 }
1877
Martin Radev9d901792016-07-15 15:58:58 +03001878 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001879}
1880
1881static bool ValidateObjectPtrName(Context *context, const void *ptr)
1882{
1883 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1884 {
Jamie Madill437fa652016-05-03 15:13:24 -04001885 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001886 return false;
1887 }
1888
Geoff Lange102fee2015-12-10 11:23:30 -05001889 return true;
1890}
1891
1892bool ValidateObjectPtrLabelKHR(Context *context,
1893 const void *ptr,
1894 GLsizei length,
1895 const GLchar *label)
1896{
1897 if (!context->getExtensions().debug)
1898 {
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001900 return false;
1901 }
1902
Geoff Lang70d0f492015-12-10 17:45:46 -05001903 if (!ValidateObjectPtrName(context, ptr))
1904 {
1905 return false;
1906 }
1907
Martin Radev9d901792016-07-15 15:58:58 +03001908 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001909 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001910 return false;
1911 }
1912
Geoff Lange102fee2015-12-10 11:23:30 -05001913 return true;
1914}
1915
1916bool ValidateGetObjectPtrLabelKHR(Context *context,
1917 const void *ptr,
1918 GLsizei bufSize,
1919 GLsizei *length,
1920 GLchar *label)
1921{
1922 if (!context->getExtensions().debug)
1923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001925 return false;
1926 }
1927
Geoff Lang70d0f492015-12-10 17:45:46 -05001928 if (bufSize < 0)
1929 {
Jamie Madill437fa652016-05-03 15:13:24 -04001930 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001931 return false;
1932 }
1933
1934 if (!ValidateObjectPtrName(context, ptr))
1935 {
1936 return false;
1937 }
1938
Martin Radev9d901792016-07-15 15:58:58 +03001939 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001940}
1941
1942bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1943{
1944 if (!context->getExtensions().debug)
1945 {
Jamie Madill437fa652016-05-03 15:13:24 -04001946 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001947 return false;
1948 }
1949
Geoff Lang70d0f492015-12-10 17:45:46 -05001950 // TODO: represent this in Context::getQueryParameterInfo.
1951 switch (pname)
1952 {
1953 case GL_DEBUG_CALLBACK_FUNCTION:
1954 case GL_DEBUG_CALLBACK_USER_PARAM:
1955 break;
1956
1957 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001958 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001959 return false;
1960 }
1961
Geoff Lange102fee2015-12-10 11:23:30 -05001962 return true;
1963}
Jamie Madillc29968b2016-01-20 11:17:23 -05001964
1965bool ValidateBlitFramebufferANGLE(Context *context,
1966 GLint srcX0,
1967 GLint srcY0,
1968 GLint srcX1,
1969 GLint srcY1,
1970 GLint dstX0,
1971 GLint dstY0,
1972 GLint dstX1,
1973 GLint dstY1,
1974 GLbitfield mask,
1975 GLenum filter)
1976{
1977 if (!context->getExtensions().framebufferBlit)
1978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001980 return false;
1981 }
1982
1983 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1984 {
1985 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001987 GL_INVALID_OPERATION,
1988 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1989 return false;
1990 }
1991
1992 if (filter == GL_LINEAR)
1993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001995 return false;
1996 }
1997
Jamie Madill51f40ec2016-06-15 14:06:00 -04001998 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
1999 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002000
2001 if (mask & GL_COLOR_BUFFER_BIT)
2002 {
2003 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2004 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2005
2006 if (readColorAttachment && drawColorAttachment)
2007 {
2008 if (!(readColorAttachment->type() == GL_TEXTURE &&
2009 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2010 readColorAttachment->type() != GL_RENDERBUFFER &&
2011 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2012 {
Jamie Madill437fa652016-05-03 15:13:24 -04002013 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002014 return false;
2015 }
2016
Geoff Langa15472a2015-08-11 11:48:03 -04002017 for (size_t drawbufferIdx = 0;
2018 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002019 {
Geoff Langa15472a2015-08-11 11:48:03 -04002020 const FramebufferAttachment *attachment =
2021 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2022 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002023 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002024 if (!(attachment->type() == GL_TEXTURE &&
2025 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2026 attachment->type() != GL_RENDERBUFFER &&
2027 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2028 {
Jamie Madill437fa652016-05-03 15:13:24 -04002029 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002030 return false;
2031 }
2032
2033 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002034 if (!Format::SameSized(attachment->getFormat(),
2035 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002036 {
Jamie Madill437fa652016-05-03 15:13:24 -04002037 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002038 return false;
2039 }
2040 }
2041 }
2042
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002043 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002044 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2045 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2046 {
Jamie Madill437fa652016-05-03 15:13:24 -04002047 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002048 return false;
2049 }
2050 }
2051 }
2052
2053 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2054 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2055 for (size_t i = 0; i < 2; i++)
2056 {
2057 if (mask & masks[i])
2058 {
2059 const FramebufferAttachment *readBuffer =
2060 readFramebuffer->getAttachment(attachments[i]);
2061 const FramebufferAttachment *drawBuffer =
2062 drawFramebuffer->getAttachment(attachments[i]);
2063
2064 if (readBuffer && drawBuffer)
2065 {
2066 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2067 dstX0, dstY0, dstX1, dstY1))
2068 {
2069 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05002070 context->handleError(Error(GL_INVALID_OPERATION,
2071 "Only whole-buffer depth and stencil blits are "
2072 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002073 return false;
2074 }
2075
2076 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2077 {
Jamie Madill437fa652016-05-03 15:13:24 -04002078 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002079 return false;
2080 }
2081 }
2082 }
2083 }
2084
2085 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2086 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087}
Jamie Madillc29968b2016-01-20 11:17:23 -05002088
2089bool ValidateClear(ValidationContext *context, GLbitfield mask)
2090{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002091 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002092 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002093 {
Jamie Madill437fa652016-05-03 15:13:24 -04002094 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002095 return false;
2096 }
2097
2098 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05002101 return false;
2102 }
2103
Geoff Lang76e65652017-03-27 14:58:02 -04002104 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2105 {
2106 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2107 GL_SIGNED_NORMALIZED};
2108
2109 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2110 drawBufferIdx++)
2111 {
2112 if (!ValidateWebGLFramebufferAttachmentClearType(
2113 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2114 {
2115 return false;
2116 }
2117 }
2118 }
2119
Jamie Madillc29968b2016-01-20 11:17:23 -05002120 return true;
2121}
2122
2123bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2124{
2125 if (!context->getExtensions().drawBuffers)
2126 {
Jamie Madill437fa652016-05-03 15:13:24 -04002127 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002128 return false;
2129 }
2130
2131 return ValidateDrawBuffersBase(context, n, bufs);
2132}
2133
Jamie Madill73a84962016-02-12 09:27:23 -05002134bool ValidateTexImage2D(Context *context,
2135 GLenum target,
2136 GLint level,
2137 GLint internalformat,
2138 GLsizei width,
2139 GLsizei height,
2140 GLint border,
2141 GLenum format,
2142 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002143 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002144{
Martin Radev1be913c2016-07-11 17:59:16 +03002145 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002146 {
2147 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002148 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002149 }
2150
Martin Radev1be913c2016-07-11 17:59:16 +03002151 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002152 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002153 0, 0, width, height, 1, border, format, type, -1,
2154 pixels);
2155}
2156
2157bool ValidateTexImage2DRobust(Context *context,
2158 GLenum target,
2159 GLint level,
2160 GLint internalformat,
2161 GLsizei width,
2162 GLsizei height,
2163 GLint border,
2164 GLenum format,
2165 GLenum type,
2166 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002167 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002168{
2169 if (!ValidateRobustEntryPoint(context, bufSize))
2170 {
2171 return false;
2172 }
2173
2174 if (context->getClientMajorVersion() < 3)
2175 {
2176 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2177 0, 0, width, height, border, format, type, bufSize,
2178 pixels);
2179 }
2180
2181 ASSERT(context->getClientMajorVersion() >= 3);
2182 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2183 0, 0, width, height, 1, border, format, type, bufSize,
2184 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002185}
2186
2187bool ValidateTexSubImage2D(Context *context,
2188 GLenum target,
2189 GLint level,
2190 GLint xoffset,
2191 GLint yoffset,
2192 GLsizei width,
2193 GLsizei height,
2194 GLenum format,
2195 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002196 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002197{
2198
Martin Radev1be913c2016-07-11 17:59:16 +03002199 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002200 {
2201 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002202 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002203 }
2204
Martin Radev1be913c2016-07-11 17:59:16 +03002205 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002206 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002207 yoffset, 0, width, height, 1, 0, format, type, -1,
2208 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002209}
2210
Geoff Langc52f6f12016-10-14 10:18:00 -04002211bool ValidateTexSubImage2DRobustANGLE(Context *context,
2212 GLenum target,
2213 GLint level,
2214 GLint xoffset,
2215 GLint yoffset,
2216 GLsizei width,
2217 GLsizei height,
2218 GLenum format,
2219 GLenum type,
2220 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002221 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002222{
2223 if (!ValidateRobustEntryPoint(context, bufSize))
2224 {
2225 return false;
2226 }
2227
2228 if (context->getClientMajorVersion() < 3)
2229 {
2230 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2231 yoffset, width, height, 0, format, type, bufSize,
2232 pixels);
2233 }
2234
2235 ASSERT(context->getClientMajorVersion() >= 3);
2236 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2237 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2238 pixels);
2239}
2240
Jamie Madill73a84962016-02-12 09:27:23 -05002241bool ValidateCompressedTexImage2D(Context *context,
2242 GLenum target,
2243 GLint level,
2244 GLenum internalformat,
2245 GLsizei width,
2246 GLsizei height,
2247 GLint border,
2248 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002249 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002250{
Martin Radev1be913c2016-07-11 17:59:16 +03002251 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002252 {
2253 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002254 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002255 {
2256 return false;
2257 }
2258 }
2259 else
2260 {
Martin Radev1be913c2016-07-11 17:59:16 +03002261 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002262 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002263 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002264 data))
2265 {
2266 return false;
2267 }
2268 }
2269
Geoff Langca271392017-04-05 12:30:00 -04002270 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002271 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002272 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002273 if (blockSizeOrErr.isError())
2274 {
2275 context->handleError(blockSizeOrErr.getError());
2276 return false;
2277 }
2278
2279 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002280 {
Jamie Madill437fa652016-05-03 15:13:24 -04002281 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002282 return false;
2283 }
2284
2285 return true;
2286}
2287
Corentin Wallezb2931602017-04-11 15:58:57 -04002288bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2289 GLenum target,
2290 GLint level,
2291 GLenum internalformat,
2292 GLsizei width,
2293 GLsizei height,
2294 GLint border,
2295 GLsizei imageSize,
2296 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002297 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002298{
2299 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2300 {
2301 return false;
2302 }
2303
2304 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2305 border, imageSize, data);
2306}
2307bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2308 GLenum target,
2309 GLint level,
2310 GLint xoffset,
2311 GLint yoffset,
2312 GLsizei width,
2313 GLsizei height,
2314 GLenum format,
2315 GLsizei imageSize,
2316 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002317 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002318{
2319 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2320 {
2321 return false;
2322 }
2323
2324 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2325 format, imageSize, data);
2326}
2327
Jamie Madill73a84962016-02-12 09:27:23 -05002328bool ValidateCompressedTexSubImage2D(Context *context,
2329 GLenum target,
2330 GLint level,
2331 GLint xoffset,
2332 GLint yoffset,
2333 GLsizei width,
2334 GLsizei height,
2335 GLenum format,
2336 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002337 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002338{
Martin Radev1be913c2016-07-11 17:59:16 +03002339 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002340 {
2341 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002342 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002343 {
2344 return false;
2345 }
2346 }
2347 else
2348 {
Martin Radev1be913c2016-07-11 17:59:16 +03002349 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002350 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002351 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002352 data))
2353 {
2354 return false;
2355 }
2356 }
2357
Geoff Langca271392017-04-05 12:30:00 -04002358 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002359 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002360 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002361 if (blockSizeOrErr.isError())
2362 {
2363 context->handleError(blockSizeOrErr.getError());
2364 return false;
2365 }
2366
2367 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002368 {
Jamie Madill437fa652016-05-03 15:13:24 -04002369 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002370 return false;
2371 }
2372
2373 return true;
2374}
2375
Olli Etuaho4f667482016-03-30 15:56:35 +03002376bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2377{
Geoff Lang496c02d2016-10-20 11:38:11 -07002378 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002379}
2380
2381bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2382{
2383 if (!context->getExtensions().mapBuffer)
2384 {
Jamie Madill437fa652016-05-03 15:13:24 -04002385 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002386 return false;
2387 }
2388
2389 if (!ValidBufferTarget(context, target))
2390 {
Jamie Madill437fa652016-05-03 15:13:24 -04002391 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002392 return false;
2393 }
2394
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002395 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002396
2397 if (buffer == nullptr)
2398 {
Jamie Madill437fa652016-05-03 15:13:24 -04002399 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002400 return false;
2401 }
2402
2403 if (access != GL_WRITE_ONLY_OES)
2404 {
Jamie Madill437fa652016-05-03 15:13:24 -04002405 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002406 return false;
2407 }
2408
2409 if (buffer->isMapped())
2410 {
Jamie Madill437fa652016-05-03 15:13:24 -04002411 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002412 return false;
2413 }
2414
2415 return true;
2416}
2417
2418bool ValidateUnmapBufferOES(Context *context, GLenum target)
2419{
2420 if (!context->getExtensions().mapBuffer)
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002423 return false;
2424 }
2425
2426 return ValidateUnmapBufferBase(context, target);
2427}
2428
2429bool ValidateMapBufferRangeEXT(Context *context,
2430 GLenum target,
2431 GLintptr offset,
2432 GLsizeiptr length,
2433 GLbitfield access)
2434{
2435 if (!context->getExtensions().mapBufferRange)
2436 {
Jamie Madill437fa652016-05-03 15:13:24 -04002437 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002438 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2439 return false;
2440 }
2441
2442 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2443}
2444
2445bool ValidateFlushMappedBufferRangeEXT(Context *context,
2446 GLenum target,
2447 GLintptr offset,
2448 GLsizeiptr length)
2449{
2450 if (!context->getExtensions().mapBufferRange)
2451 {
Jamie Madill437fa652016-05-03 15:13:24 -04002452 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002453 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2454 return false;
2455 }
2456
2457 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2458}
2459
Ian Ewell54f87462016-03-10 13:47:21 -05002460bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2461{
2462 Texture *textureObject = context->getTexture(texture);
2463 if (textureObject && textureObject->getTarget() != target && texture != 0)
2464 {
Jamie Madill437fa652016-05-03 15:13:24 -04002465 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002466 return false;
2467 }
2468
Geoff Langf41a7152016-09-19 15:11:17 -04002469 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2470 !context->isTextureGenerated(texture))
2471 {
2472 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2473 return false;
2474 }
2475
Ian Ewell54f87462016-03-10 13:47:21 -05002476 switch (target)
2477 {
2478 case GL_TEXTURE_2D:
2479 case GL_TEXTURE_CUBE_MAP:
2480 break;
2481
2482 case GL_TEXTURE_3D:
2483 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002484 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002485 {
Jamie Madill437fa652016-05-03 15:13:24 -04002486 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002487 return false;
2488 }
2489 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002490
2491 case GL_TEXTURE_2D_MULTISAMPLE:
2492 if (context->getClientVersion() < Version(3, 1))
2493 {
2494 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2495 return false;
2496 }
Geoff Lang3b573612016-10-31 14:08:10 -04002497 break;
2498
Ian Ewell54f87462016-03-10 13:47:21 -05002499 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002500 if (!context->getExtensions().eglImageExternal &&
2501 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002502 {
Jamie Madill437fa652016-05-03 15:13:24 -04002503 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002504 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2505 return false;
2506 }
2507 break;
2508 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002509 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002510 return false;
2511 }
2512
2513 return true;
2514}
2515
Geoff Langd8605522016-04-13 10:19:12 -04002516bool ValidateBindUniformLocationCHROMIUM(Context *context,
2517 GLuint program,
2518 GLint location,
2519 const GLchar *name)
2520{
2521 if (!context->getExtensions().bindUniformLocation)
2522 {
Jamie Madill437fa652016-05-03 15:13:24 -04002523 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002524 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2525 return false;
2526 }
2527
2528 Program *programObject = GetValidProgram(context, program);
2529 if (!programObject)
2530 {
2531 return false;
2532 }
2533
2534 if (location < 0)
2535 {
Jamie Madill437fa652016-05-03 15:13:24 -04002536 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002537 return false;
2538 }
2539
2540 const Caps &caps = context->getCaps();
2541 if (static_cast<size_t>(location) >=
2542 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2543 {
Jamie Madill437fa652016-05-03 15:13:24 -04002544 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002545 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2546 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2547 return false;
2548 }
2549
2550 if (strncmp(name, "gl_", 3) == 0)
2551 {
Jamie Madill437fa652016-05-03 15:13:24 -04002552 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002553 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2554 return false;
2555 }
2556
2557 return true;
2558}
2559
Jamie Madille2e406c2016-06-02 13:04:10 -04002560bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002561{
2562 if (!context->getExtensions().framebufferMixedSamples)
2563 {
2564 context->handleError(
2565 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2566 return false;
2567 }
2568 switch (components)
2569 {
2570 case GL_RGB:
2571 case GL_RGBA:
2572 case GL_ALPHA:
2573 case GL_NONE:
2574 break;
2575 default:
2576 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002577 Error(GL_INVALID_ENUM,
2578 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002579 return false;
2580 }
2581
2582 return true;
2583}
2584
Sami Väisänene45e53b2016-05-25 10:36:04 +03002585// CHROMIUM_path_rendering
2586
2587bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2588{
2589 if (!context->getExtensions().pathRendering)
2590 {
2591 context->handleError(
2592 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2593 return false;
2594 }
2595 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2596 {
2597 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2598 return false;
2599 }
2600 if (matrix == nullptr)
2601 {
2602 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2603 return false;
2604 }
2605 return true;
2606}
2607
2608bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2609{
2610 if (!context->getExtensions().pathRendering)
2611 {
2612 context->handleError(
2613 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2614 return false;
2615 }
2616 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2617 {
2618 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2619 return false;
2620 }
2621 return true;
2622}
2623
2624bool ValidateGenPaths(Context *context, GLsizei range)
2625{
2626 if (!context->getExtensions().pathRendering)
2627 {
2628 context->handleError(
2629 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2630 return false;
2631 }
2632
2633 // range = 0 is undefined in NV_path_rendering.
2634 // we add stricter semantic check here and require a non zero positive range.
2635 if (range <= 0)
2636 {
2637 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2638 return false;
2639 }
2640
2641 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2642 {
2643 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2644 return false;
2645 }
2646
2647 return true;
2648}
2649
2650bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2651{
2652 if (!context->getExtensions().pathRendering)
2653 {
2654 context->handleError(
2655 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2656 return false;
2657 }
2658
2659 // range = 0 is undefined in NV_path_rendering.
2660 // we add stricter semantic check here and require a non zero positive range.
2661 if (range <= 0)
2662 {
2663 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2664 return false;
2665 }
2666
2667 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2668 checkedRange += range;
2669
2670 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2671 {
2672 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2673 return false;
2674 }
2675 return true;
2676}
2677
2678bool ValidatePathCommands(Context *context,
2679 GLuint path,
2680 GLsizei numCommands,
2681 const GLubyte *commands,
2682 GLsizei numCoords,
2683 GLenum coordType,
2684 const void *coords)
2685{
2686 if (!context->getExtensions().pathRendering)
2687 {
2688 context->handleError(
2689 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2690 return false;
2691 }
2692 if (!context->hasPath(path))
2693 {
2694 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2695 return false;
2696 }
2697
2698 if (numCommands < 0)
2699 {
2700 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2701 return false;
2702 }
2703 else if (numCommands > 0)
2704 {
2705 if (!commands)
2706 {
2707 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2708 return false;
2709 }
2710 }
2711
2712 if (numCoords < 0)
2713 {
2714 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2715 return false;
2716 }
2717 else if (numCoords > 0)
2718 {
2719 if (!coords)
2720 {
2721 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2722 return false;
2723 }
2724 }
2725
2726 std::uint32_t coordTypeSize = 0;
2727 switch (coordType)
2728 {
2729 case GL_BYTE:
2730 coordTypeSize = sizeof(GLbyte);
2731 break;
2732
2733 case GL_UNSIGNED_BYTE:
2734 coordTypeSize = sizeof(GLubyte);
2735 break;
2736
2737 case GL_SHORT:
2738 coordTypeSize = sizeof(GLshort);
2739 break;
2740
2741 case GL_UNSIGNED_SHORT:
2742 coordTypeSize = sizeof(GLushort);
2743 break;
2744
2745 case GL_FLOAT:
2746 coordTypeSize = sizeof(GLfloat);
2747 break;
2748
2749 default:
2750 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2751 return false;
2752 }
2753
2754 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2755 checkedSize += (coordTypeSize * numCoords);
2756 if (!checkedSize.IsValid())
2757 {
2758 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2759 return false;
2760 }
2761
2762 // early return skips command data validation when it doesn't exist.
2763 if (!commands)
2764 return true;
2765
2766 GLsizei expectedNumCoords = 0;
2767 for (GLsizei i = 0; i < numCommands; ++i)
2768 {
2769 switch (commands[i])
2770 {
2771 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2772 break;
2773 case GL_MOVE_TO_CHROMIUM:
2774 case GL_LINE_TO_CHROMIUM:
2775 expectedNumCoords += 2;
2776 break;
2777 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2778 expectedNumCoords += 4;
2779 break;
2780 case GL_CUBIC_CURVE_TO_CHROMIUM:
2781 expectedNumCoords += 6;
2782 break;
2783 case GL_CONIC_CURVE_TO_CHROMIUM:
2784 expectedNumCoords += 5;
2785 break;
2786 default:
2787 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2788 return false;
2789 }
2790 }
2791 if (expectedNumCoords != numCoords)
2792 {
2793 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2794 return false;
2795 }
2796
2797 return true;
2798}
2799
2800bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2801{
2802 if (!context->getExtensions().pathRendering)
2803 {
2804 context->handleError(
2805 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2806 return false;
2807 }
2808 if (!context->hasPath(path))
2809 {
2810 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2811 return false;
2812 }
2813
2814 switch (pname)
2815 {
2816 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2817 if (value < 0.0f)
2818 {
2819 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2820 return false;
2821 }
2822 break;
2823 case GL_PATH_END_CAPS_CHROMIUM:
2824 switch (static_cast<GLenum>(value))
2825 {
2826 case GL_FLAT_CHROMIUM:
2827 case GL_SQUARE_CHROMIUM:
2828 case GL_ROUND_CHROMIUM:
2829 break;
2830 default:
2831 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2832 return false;
2833 }
2834 break;
2835 case GL_PATH_JOIN_STYLE_CHROMIUM:
2836 switch (static_cast<GLenum>(value))
2837 {
2838 case GL_MITER_REVERT_CHROMIUM:
2839 case GL_BEVEL_CHROMIUM:
2840 case GL_ROUND_CHROMIUM:
2841 break;
2842 default:
2843 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2844 return false;
2845 }
2846 case GL_PATH_MITER_LIMIT_CHROMIUM:
2847 if (value < 0.0f)
2848 {
2849 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2850 return false;
2851 }
2852 break;
2853
2854 case GL_PATH_STROKE_BOUND_CHROMIUM:
2855 // no errors, only clamping.
2856 break;
2857
2858 default:
2859 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2860 return false;
2861 }
2862 return true;
2863}
2864
2865bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2866{
2867 if (!context->getExtensions().pathRendering)
2868 {
2869 context->handleError(
2870 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2871 return false;
2872 }
2873
2874 if (!context->hasPath(path))
2875 {
2876 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2877 return false;
2878 }
2879 if (!value)
2880 {
2881 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2882 return false;
2883 }
2884
2885 switch (pname)
2886 {
2887 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2888 case GL_PATH_END_CAPS_CHROMIUM:
2889 case GL_PATH_JOIN_STYLE_CHROMIUM:
2890 case GL_PATH_MITER_LIMIT_CHROMIUM:
2891 case GL_PATH_STROKE_BOUND_CHROMIUM:
2892 break;
2893
2894 default:
2895 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2896 return false;
2897 }
2898
2899 return true;
2900}
2901
2902bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2903{
2904 if (!context->getExtensions().pathRendering)
2905 {
2906 context->handleError(
2907 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2908 return false;
2909 }
2910
2911 switch (func)
2912 {
2913 case GL_NEVER:
2914 case GL_ALWAYS:
2915 case GL_LESS:
2916 case GL_LEQUAL:
2917 case GL_EQUAL:
2918 case GL_GEQUAL:
2919 case GL_GREATER:
2920 case GL_NOTEQUAL:
2921 break;
2922 default:
2923 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2924 return false;
2925 }
2926
2927 return true;
2928}
2929
2930// Note that the spec specifies that for the path drawing commands
2931// if the path object is not an existing path object the command
2932// does nothing and no error is generated.
2933// However if the path object exists but has not been specified any
2934// commands then an error is generated.
2935
2936bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2937{
2938 if (!context->getExtensions().pathRendering)
2939 {
2940 context->handleError(
2941 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2942 return false;
2943 }
2944 if (context->hasPath(path) && !context->hasPathData(path))
2945 {
2946 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2947 return false;
2948 }
2949
2950 switch (fillMode)
2951 {
2952 case GL_COUNT_UP_CHROMIUM:
2953 case GL_COUNT_DOWN_CHROMIUM:
2954 break;
2955 default:
2956 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2957 return false;
2958 }
2959
2960 if (!isPow2(mask + 1))
2961 {
2962 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2963 return false;
2964 }
2965
2966 return true;
2967}
2968
2969bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2970{
2971 if (!context->getExtensions().pathRendering)
2972 {
2973 context->handleError(
2974 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2975 return false;
2976 }
2977 if (context->hasPath(path) && !context->hasPathData(path))
2978 {
2979 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2980 return false;
2981 }
2982
2983 return true;
2984}
2985
2986bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2987{
2988 if (!context->getExtensions().pathRendering)
2989 {
2990 context->handleError(
2991 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2992 return false;
2993 }
2994 if (context->hasPath(path) && !context->hasPathData(path))
2995 {
2996 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2997 return false;
2998 }
2999
3000 switch (coverMode)
3001 {
3002 case GL_CONVEX_HULL_CHROMIUM:
3003 case GL_BOUNDING_BOX_CHROMIUM:
3004 break;
3005 default:
3006 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3007 return false;
3008 }
3009 return true;
3010}
3011
3012bool ValidateStencilThenCoverFillPath(Context *context,
3013 GLuint path,
3014 GLenum fillMode,
3015 GLuint mask,
3016 GLenum coverMode)
3017{
3018 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3019 ValidateCoverPath(context, path, coverMode);
3020}
3021
3022bool ValidateStencilThenCoverStrokePath(Context *context,
3023 GLuint path,
3024 GLint reference,
3025 GLuint mask,
3026 GLenum coverMode)
3027{
3028 return ValidateStencilStrokePath(context, path, reference, mask) &&
3029 ValidateCoverPath(context, path, coverMode);
3030}
3031
3032bool ValidateIsPath(Context *context)
3033{
3034 if (!context->getExtensions().pathRendering)
3035 {
3036 context->handleError(
3037 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3038 return false;
3039 }
3040 return true;
3041}
3042
Sami Väisänend59ca052016-06-21 16:10:00 +03003043bool ValidateCoverFillPathInstanced(Context *context,
3044 GLsizei numPaths,
3045 GLenum pathNameType,
3046 const void *paths,
3047 GLuint pathBase,
3048 GLenum coverMode,
3049 GLenum transformType,
3050 const GLfloat *transformValues)
3051{
3052 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3053 transformType, transformValues))
3054 return false;
3055
3056 switch (coverMode)
3057 {
3058 case GL_CONVEX_HULL_CHROMIUM:
3059 case GL_BOUNDING_BOX_CHROMIUM:
3060 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3061 break;
3062 default:
3063 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3064 return false;
3065 }
3066
3067 return true;
3068}
3069
3070bool ValidateCoverStrokePathInstanced(Context *context,
3071 GLsizei numPaths,
3072 GLenum pathNameType,
3073 const void *paths,
3074 GLuint pathBase,
3075 GLenum coverMode,
3076 GLenum transformType,
3077 const GLfloat *transformValues)
3078{
3079 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3080 transformType, transformValues))
3081 return false;
3082
3083 switch (coverMode)
3084 {
3085 case GL_CONVEX_HULL_CHROMIUM:
3086 case GL_BOUNDING_BOX_CHROMIUM:
3087 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3088 break;
3089 default:
3090 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3091 return false;
3092 }
3093
3094 return true;
3095}
3096
3097bool ValidateStencilFillPathInstanced(Context *context,
3098 GLsizei numPaths,
3099 GLenum pathNameType,
3100 const void *paths,
3101 GLuint pathBase,
3102 GLenum fillMode,
3103 GLuint mask,
3104 GLenum transformType,
3105 const GLfloat *transformValues)
3106{
3107
3108 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3109 transformType, transformValues))
3110 return false;
3111
3112 switch (fillMode)
3113 {
3114 case GL_COUNT_UP_CHROMIUM:
3115 case GL_COUNT_DOWN_CHROMIUM:
3116 break;
3117 default:
3118 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3119 return false;
3120 }
3121 if (!isPow2(mask + 1))
3122 {
3123 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3124 return false;
3125 }
3126 return true;
3127}
3128
3129bool ValidateStencilStrokePathInstanced(Context *context,
3130 GLsizei numPaths,
3131 GLenum pathNameType,
3132 const void *paths,
3133 GLuint pathBase,
3134 GLint reference,
3135 GLuint mask,
3136 GLenum transformType,
3137 const GLfloat *transformValues)
3138{
3139 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3140 transformType, transformValues))
3141 return false;
3142
3143 // no more validation here.
3144
3145 return true;
3146}
3147
3148bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3149 GLsizei numPaths,
3150 GLenum pathNameType,
3151 const void *paths,
3152 GLuint pathBase,
3153 GLenum fillMode,
3154 GLuint mask,
3155 GLenum coverMode,
3156 GLenum transformType,
3157 const GLfloat *transformValues)
3158{
3159 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3160 transformType, transformValues))
3161 return false;
3162
3163 switch (coverMode)
3164 {
3165 case GL_CONVEX_HULL_CHROMIUM:
3166 case GL_BOUNDING_BOX_CHROMIUM:
3167 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3168 break;
3169 default:
3170 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3171 return false;
3172 }
3173
3174 switch (fillMode)
3175 {
3176 case GL_COUNT_UP_CHROMIUM:
3177 case GL_COUNT_DOWN_CHROMIUM:
3178 break;
3179 default:
3180 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3181 return false;
3182 }
3183 if (!isPow2(mask + 1))
3184 {
3185 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3186 return false;
3187 }
3188
3189 return true;
3190}
3191
3192bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3193 GLsizei numPaths,
3194 GLenum pathNameType,
3195 const void *paths,
3196 GLuint pathBase,
3197 GLint reference,
3198 GLuint mask,
3199 GLenum coverMode,
3200 GLenum transformType,
3201 const GLfloat *transformValues)
3202{
3203 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3204 transformType, transformValues))
3205 return false;
3206
3207 switch (coverMode)
3208 {
3209 case GL_CONVEX_HULL_CHROMIUM:
3210 case GL_BOUNDING_BOX_CHROMIUM:
3211 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3212 break;
3213 default:
3214 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3215 return false;
3216 }
3217
3218 return true;
3219}
3220
Sami Väisänen46eaa942016-06-29 10:26:37 +03003221bool ValidateBindFragmentInputLocation(Context *context,
3222 GLuint program,
3223 GLint location,
3224 const GLchar *name)
3225{
3226 if (!context->getExtensions().pathRendering)
3227 {
3228 context->handleError(
3229 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3230 return false;
3231 }
3232
3233 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3234 if (location >= MaxLocation)
3235 {
3236 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3237 return false;
3238 }
3239
3240 const auto *programObject = context->getProgram(program);
3241 if (!programObject)
3242 {
3243 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3244 return false;
3245 }
3246
3247 if (!name)
3248 {
3249 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3250 return false;
3251 }
3252
3253 if (angle::BeginsWith(name, "gl_"))
3254 {
3255 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3256 return false;
3257 }
3258
3259 return true;
3260}
3261
3262bool ValidateProgramPathFragmentInputGen(Context *context,
3263 GLuint program,
3264 GLint location,
3265 GLenum genMode,
3266 GLint components,
3267 const GLfloat *coeffs)
3268{
3269 if (!context->getExtensions().pathRendering)
3270 {
3271 context->handleError(
3272 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3273 return false;
3274 }
3275
3276 const auto *programObject = context->getProgram(program);
3277 if (!programObject || programObject->isFlaggedForDeletion())
3278 {
3279 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3280 return false;
3281 }
3282
3283 if (!programObject->isLinked())
3284 {
3285 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3286 return false;
3287 }
3288
3289 switch (genMode)
3290 {
3291 case GL_NONE:
3292 if (components != 0)
3293 {
3294 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3295 return false;
3296 }
3297 break;
3298
3299 case GL_OBJECT_LINEAR_CHROMIUM:
3300 case GL_EYE_LINEAR_CHROMIUM:
3301 case GL_CONSTANT_CHROMIUM:
3302 if (components < 1 || components > 4)
3303 {
3304 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3305 return false;
3306 }
3307 if (!coeffs)
3308 {
3309 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3310 return false;
3311 }
3312 break;
3313
3314 default:
3315 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3316 return false;
3317 }
3318
3319 // If the location is -1 then the command is silently ignored
3320 // and no further validation is needed.
3321 if (location == -1)
3322 return true;
3323
3324 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3325
3326 if (!binding.valid)
3327 {
3328 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3329 return false;
3330 }
3331
3332 if (binding.type != GL_NONE)
3333 {
3334 GLint expectedComponents = 0;
3335 switch (binding.type)
3336 {
3337 case GL_FLOAT:
3338 expectedComponents = 1;
3339 break;
3340 case GL_FLOAT_VEC2:
3341 expectedComponents = 2;
3342 break;
3343 case GL_FLOAT_VEC3:
3344 expectedComponents = 3;
3345 break;
3346 case GL_FLOAT_VEC4:
3347 expectedComponents = 4;
3348 break;
3349 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003350 context->handleError(
3351 Error(GL_INVALID_OPERATION,
3352 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003353 return false;
3354 }
3355 if (expectedComponents != components && genMode != GL_NONE)
3356 {
3357 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3358 return false;
3359 }
3360 }
3361 return true;
3362}
3363
Geoff Lang97073d12016-04-20 10:42:34 -07003364bool ValidateCopyTextureCHROMIUM(Context *context,
3365 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003366 GLint sourceLevel,
3367 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003368 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003369 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003370 GLint internalFormat,
3371 GLenum destType,
3372 GLboolean unpackFlipY,
3373 GLboolean unpackPremultiplyAlpha,
3374 GLboolean unpackUnmultiplyAlpha)
3375{
3376 if (!context->getExtensions().copyTexture)
3377 {
3378 context->handleError(
3379 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3380 return false;
3381 }
3382
3383 const gl::Texture *source = context->getTexture(sourceId);
3384 if (source == nullptr)
3385 {
3386 context->handleError(
3387 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3388 return false;
3389 }
3390
3391 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3392 {
3393 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3394 return false;
3395 }
3396
3397 GLenum sourceTarget = source->getTarget();
3398 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3399 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3400 {
3401 context->handleError(
3402 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3403 return false;
3404 }
3405
Geoff Langca271392017-04-05 12:30:00 -04003406 const gl::InternalFormat &sourceFormat = *source->getFormat(sourceTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003407 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3408 {
3409 context->handleError(
3410 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3411 return false;
3412 }
3413
3414 const gl::Texture *dest = context->getTexture(destId);
3415 if (dest == nullptr)
3416 {
3417 context->handleError(
3418 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3419 return false;
3420 }
3421
3422 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3423 {
3424 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3425 return false;
3426 }
3427
3428 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3429 {
3430 context->handleError(
3431 Error(GL_INVALID_OPERATION,
3432 "Destination internal format and type combination is not valid."));
3433 return false;
3434 }
3435
3436 if (dest->getImmutableFormat())
3437 {
3438 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3439 return false;
3440 }
3441
3442 return true;
3443}
3444
3445bool ValidateCopySubTextureCHROMIUM(Context *context,
3446 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003447 GLint sourceLevel,
3448 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003449 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003450 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003451 GLint xoffset,
3452 GLint yoffset,
3453 GLint x,
3454 GLint y,
3455 GLsizei width,
3456 GLsizei height,
3457 GLboolean unpackFlipY,
3458 GLboolean unpackPremultiplyAlpha,
3459 GLboolean unpackUnmultiplyAlpha)
3460{
3461 if (!context->getExtensions().copyTexture)
3462 {
3463 context->handleError(
3464 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3465 return false;
3466 }
3467
3468 const gl::Texture *source = context->getTexture(sourceId);
3469 if (source == nullptr)
3470 {
3471 context->handleError(
3472 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3473 return false;
3474 }
3475
3476 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3477 {
3478 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3479 return false;
3480 }
3481
3482 GLenum sourceTarget = source->getTarget();
3483 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3484 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3485 {
3486 context->handleError(
3487 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3488 return false;
3489 }
3490
3491 if (x < 0 || y < 0)
3492 {
3493 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3494 return false;
3495 }
3496
3497 if (width < 0 || height < 0)
3498 {
3499 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3500 return false;
3501 }
3502
3503 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3504 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3505 {
3506 context->handleError(
3507 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3508 return false;
3509 }
3510
3511 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
Geoff Langca271392017-04-05 12:30:00 -04003512 if (!IsValidCopyTextureFormat(context, sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003513 {
3514 context->handleError(
3515 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3516 return false;
3517 }
3518
3519 const gl::Texture *dest = context->getTexture(destId);
3520 if (dest == nullptr)
3521 {
3522 context->handleError(
3523 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3524 return false;
3525 }
3526
3527 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3528 {
3529 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3530 return false;
3531 }
3532
Geoff Lang97073d12016-04-20 10:42:34 -07003533 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3534 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3535 {
3536 context->handleError(
3537 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3538 return false;
3539 }
3540
Geoff Langca271392017-04-05 12:30:00 -04003541 const gl::InternalFormat &destFormat = *dest->getFormat(destTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003542 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3543 {
3544 context->handleError(
3545 Error(GL_INVALID_OPERATION,
3546 "Destination internal format and type combination is not valid."));
3547 return false;
3548 }
3549
3550 if (xoffset < 0 || yoffset < 0)
3551 {
3552 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3553 return false;
3554 }
3555
3556 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3557 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3558 {
3559 context->handleError(
3560 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3561 return false;
3562 }
3563
3564 return true;
3565}
3566
Geoff Lang47110bf2016-04-20 11:13:22 -07003567bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3568{
3569 if (!context->getExtensions().copyCompressedTexture)
3570 {
3571 context->handleError(Error(GL_INVALID_OPERATION,
3572 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3573 return false;
3574 }
3575
3576 const gl::Texture *source = context->getTexture(sourceId);
3577 if (source == nullptr)
3578 {
3579 context->handleError(
3580 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3581 return false;
3582 }
3583
3584 if (source->getTarget() != GL_TEXTURE_2D)
3585 {
3586 context->handleError(
3587 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3588 return false;
3589 }
3590
3591 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3592 {
3593 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3594 return false;
3595 }
3596
3597 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3598 if (!sourceFormat.info->compressed)
3599 {
3600 context->handleError(
3601 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3602 return false;
3603 }
3604
3605 const gl::Texture *dest = context->getTexture(destId);
3606 if (dest == nullptr)
3607 {
3608 context->handleError(
3609 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3610 return false;
3611 }
3612
3613 if (dest->getTarget() != GL_TEXTURE_2D)
3614 {
3615 context->handleError(
3616 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3617 return false;
3618 }
3619
3620 if (dest->getImmutableFormat())
3621 {
3622 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3623 return false;
3624 }
3625
3626 return true;
3627}
3628
Martin Radev4c4c8e72016-08-04 12:25:34 +03003629bool ValidateCreateShader(Context *context, GLenum type)
3630{
3631 switch (type)
3632 {
3633 case GL_VERTEX_SHADER:
3634 case GL_FRAGMENT_SHADER:
3635 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003636
Martin Radev4c4c8e72016-08-04 12:25:34 +03003637 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003638 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003639 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003640 context->handleError(
3641 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3642 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003643 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003644 break;
3645
Martin Radev4c4c8e72016-08-04 12:25:34 +03003646 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003647 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003648 return false;
3649 }
Jamie Madill29639852016-09-02 15:00:09 -04003650
3651 return true;
3652}
3653
3654bool ValidateBufferData(ValidationContext *context,
3655 GLenum target,
3656 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003657 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003658 GLenum usage)
3659{
3660 if (size < 0)
3661 {
3662 context->handleError(Error(GL_INVALID_VALUE));
3663 return false;
3664 }
3665
3666 switch (usage)
3667 {
3668 case GL_STREAM_DRAW:
3669 case GL_STATIC_DRAW:
3670 case GL_DYNAMIC_DRAW:
3671 break;
3672
3673 case GL_STREAM_READ:
3674 case GL_STREAM_COPY:
3675 case GL_STATIC_READ:
3676 case GL_STATIC_COPY:
3677 case GL_DYNAMIC_READ:
3678 case GL_DYNAMIC_COPY:
3679 if (context->getClientMajorVersion() < 3)
3680 {
3681 context->handleError(Error(GL_INVALID_ENUM));
3682 return false;
3683 }
3684 break;
3685
3686 default:
3687 context->handleError(Error(GL_INVALID_ENUM));
3688 return false;
3689 }
3690
3691 if (!ValidBufferTarget(context, target))
3692 {
3693 context->handleError(Error(GL_INVALID_ENUM));
3694 return false;
3695 }
3696
3697 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3698
3699 if (!buffer)
3700 {
3701 context->handleError(Error(GL_INVALID_OPERATION));
3702 return false;
3703 }
3704
3705 return true;
3706}
3707
3708bool ValidateBufferSubData(ValidationContext *context,
3709 GLenum target,
3710 GLintptr offset,
3711 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003712 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003713{
3714 if (size < 0 || offset < 0)
3715 {
3716 context->handleError(Error(GL_INVALID_VALUE));
3717 return false;
3718 }
3719
3720 if (!ValidBufferTarget(context, target))
3721 {
3722 context->handleError(Error(GL_INVALID_ENUM));
3723 return false;
3724 }
3725
3726 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3727
3728 if (!buffer)
3729 {
3730 context->handleError(Error(GL_INVALID_OPERATION));
3731 return false;
3732 }
3733
3734 if (buffer->isMapped())
3735 {
3736 context->handleError(Error(GL_INVALID_OPERATION));
3737 return false;
3738 }
3739
3740 // Check for possible overflow of size + offset
3741 angle::CheckedNumeric<size_t> checkedSize(size);
3742 checkedSize += offset;
3743 if (!checkedSize.IsValid())
3744 {
3745 context->handleError(Error(GL_OUT_OF_MEMORY));
3746 return false;
3747 }
3748
3749 if (size + offset > buffer->getSize())
3750 {
3751 context->handleError(Error(GL_INVALID_VALUE));
3752 return false;
3753 }
3754
Martin Radev4c4c8e72016-08-04 12:25:34 +03003755 return true;
3756}
3757
Geoff Langc339c4e2016-11-29 10:37:36 -05003758bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003759{
Geoff Langc339c4e2016-11-29 10:37:36 -05003760 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003761 {
3762 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003763 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003764 return false;
3765 }
3766
3767 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3768 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003769 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003770 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003771 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003772 return false;
3773 }
3774
3775 return true;
3776}
3777
Jamie Madillef300b12016-10-07 15:12:09 -04003778bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3779{
3780 if (texture < GL_TEXTURE0 ||
3781 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3782 {
3783 context->handleError(Error(GL_INVALID_ENUM));
3784 return false;
3785 }
3786
3787 return true;
3788}
3789
3790bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3791{
3792 Program *programObject = GetValidProgram(context, program);
3793 if (!programObject)
3794 {
3795 return false;
3796 }
3797
3798 Shader *shaderObject = GetValidShader(context, shader);
3799 if (!shaderObject)
3800 {
3801 return false;
3802 }
3803
3804 switch (shaderObject->getType())
3805 {
3806 case GL_VERTEX_SHADER:
3807 {
3808 if (programObject->getAttachedVertexShader())
3809 {
3810 context->handleError(Error(GL_INVALID_OPERATION));
3811 return false;
3812 }
3813 break;
3814 }
3815 case GL_FRAGMENT_SHADER:
3816 {
3817 if (programObject->getAttachedFragmentShader())
3818 {
3819 context->handleError(Error(GL_INVALID_OPERATION));
3820 return false;
3821 }
3822 break;
3823 }
3824 case GL_COMPUTE_SHADER:
3825 {
3826 if (programObject->getAttachedComputeShader())
3827 {
3828 context->handleError(Error(GL_INVALID_OPERATION));
3829 return false;
3830 }
3831 break;
3832 }
3833 default:
3834 UNREACHABLE();
3835 break;
3836 }
3837
3838 return true;
3839}
3840
Jamie Madill01a80ee2016-11-07 12:06:18 -05003841bool ValidateBindAttribLocation(ValidationContext *context,
3842 GLuint program,
3843 GLuint index,
3844 const GLchar *name)
3845{
3846 if (index >= MAX_VERTEX_ATTRIBS)
3847 {
3848 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3849 return false;
3850 }
3851
3852 if (strncmp(name, "gl_", 3) == 0)
3853 {
3854 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3855 return false;
3856 }
3857
3858 return GetValidProgram(context, program) != nullptr;
3859}
3860
3861bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3862{
3863 if (!ValidBufferTarget(context, target))
3864 {
3865 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3866 return false;
3867 }
3868
3869 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3870 !context->isBufferGenerated(buffer))
3871 {
3872 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3873 return false;
3874 }
3875
3876 return true;
3877}
3878
3879bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3880{
3881 if (!ValidFramebufferTarget(target))
3882 {
3883 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3884 return false;
3885 }
3886
3887 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3888 !context->isFramebufferGenerated(framebuffer))
3889 {
3890 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3891 return false;
3892 }
3893
3894 return true;
3895}
3896
3897bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3898{
3899 if (target != GL_RENDERBUFFER)
3900 {
3901 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3902 return false;
3903 }
3904
3905 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3906 !context->isRenderbufferGenerated(renderbuffer))
3907 {
3908 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3909 return false;
3910 }
3911
3912 return true;
3913}
3914
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003915static bool ValidBlendEquationMode(GLenum mode)
3916{
3917 switch (mode)
3918 {
3919 case GL_FUNC_ADD:
3920 case GL_FUNC_SUBTRACT:
3921 case GL_FUNC_REVERSE_SUBTRACT:
3922 case GL_MIN:
3923 case GL_MAX:
3924 return true;
3925
3926 default:
3927 return false;
3928 }
3929}
3930
Jamie Madillc1d770e2017-04-13 17:31:24 -04003931bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04003932 GLfloat red,
3933 GLfloat green,
3934 GLfloat blue,
3935 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04003936{
3937 return true;
3938}
3939
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003940bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3941{
3942 if (!ValidBlendEquationMode(mode))
3943 {
3944 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3945 return false;
3946 }
3947
3948 return true;
3949}
3950
3951bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3952{
3953 if (!ValidBlendEquationMode(modeRGB))
3954 {
3955 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3956 return false;
3957 }
3958
3959 if (!ValidBlendEquationMode(modeAlpha))
3960 {
3961 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3962 return false;
3963 }
3964
3965 return true;
3966}
3967
3968bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3969{
3970 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3971}
3972
3973static bool ValidSrcBlendFunc(GLenum srcBlend)
3974{
3975 switch (srcBlend)
3976 {
3977 case GL_ZERO:
3978 case GL_ONE:
3979 case GL_SRC_COLOR:
3980 case GL_ONE_MINUS_SRC_COLOR:
3981 case GL_DST_COLOR:
3982 case GL_ONE_MINUS_DST_COLOR:
3983 case GL_SRC_ALPHA:
3984 case GL_ONE_MINUS_SRC_ALPHA:
3985 case GL_DST_ALPHA:
3986 case GL_ONE_MINUS_DST_ALPHA:
3987 case GL_CONSTANT_COLOR:
3988 case GL_ONE_MINUS_CONSTANT_COLOR:
3989 case GL_CONSTANT_ALPHA:
3990 case GL_ONE_MINUS_CONSTANT_ALPHA:
3991 case GL_SRC_ALPHA_SATURATE:
3992 return true;
3993
3994 default:
3995 return false;
3996 }
3997}
3998
3999static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4000{
4001 switch (dstBlend)
4002 {
4003 case GL_ZERO:
4004 case GL_ONE:
4005 case GL_SRC_COLOR:
4006 case GL_ONE_MINUS_SRC_COLOR:
4007 case GL_DST_COLOR:
4008 case GL_ONE_MINUS_DST_COLOR:
4009 case GL_SRC_ALPHA:
4010 case GL_ONE_MINUS_SRC_ALPHA:
4011 case GL_DST_ALPHA:
4012 case GL_ONE_MINUS_DST_ALPHA:
4013 case GL_CONSTANT_COLOR:
4014 case GL_ONE_MINUS_CONSTANT_COLOR:
4015 case GL_CONSTANT_ALPHA:
4016 case GL_ONE_MINUS_CONSTANT_ALPHA:
4017 return true;
4018
4019 case GL_SRC_ALPHA_SATURATE:
4020 return (contextMajorVersion >= 3);
4021
4022 default:
4023 return false;
4024 }
4025}
4026
4027bool ValidateBlendFuncSeparate(ValidationContext *context,
4028 GLenum srcRGB,
4029 GLenum dstRGB,
4030 GLenum srcAlpha,
4031 GLenum dstAlpha)
4032{
4033 if (!ValidSrcBlendFunc(srcRGB))
4034 {
4035 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4036 return false;
4037 }
4038
4039 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4040 {
4041 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4042 return false;
4043 }
4044
4045 if (!ValidSrcBlendFunc(srcAlpha))
4046 {
4047 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4048 return false;
4049 }
4050
4051 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4052 {
4053 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4054 return false;
4055 }
4056
Frank Henigman146e8a12017-03-02 23:22:37 -05004057 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4058 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004059 {
4060 bool constantColorUsed =
4061 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4062 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4063
4064 bool constantAlphaUsed =
4065 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4066 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4067
4068 if (constantColorUsed && constantAlphaUsed)
4069 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004070 const char *msg;
4071 if (context->getExtensions().webglCompatibility)
4072 {
4073 msg =
4074 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4075 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4076 }
4077 else
4078 {
4079 msg =
4080 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4081 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4082 "implementation.";
4083 ERR() << msg;
4084 }
4085 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004086 return false;
4087 }
4088 }
4089
4090 return true;
4091}
4092
Geoff Langc339c4e2016-11-29 10:37:36 -05004093bool ValidateGetString(Context *context, GLenum name)
4094{
4095 switch (name)
4096 {
4097 case GL_VENDOR:
4098 case GL_RENDERER:
4099 case GL_VERSION:
4100 case GL_SHADING_LANGUAGE_VERSION:
4101 case GL_EXTENSIONS:
4102 break;
4103
4104 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4105 if (!context->getExtensions().requestExtension)
4106 {
4107 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4108 return false;
4109 }
4110 break;
4111
4112 default:
4113 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4114 return false;
4115 }
4116
4117 return true;
4118}
4119
Geoff Lang47c48082016-12-07 15:38:13 -05004120bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4121{
4122 if (width <= 0.0f || isNaN(width))
4123 {
4124 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
4125 return false;
4126 }
4127
4128 return true;
4129}
4130
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004131bool ValidateVertexAttribPointer(ValidationContext *context,
4132 GLuint index,
4133 GLint size,
4134 GLenum type,
4135 GLboolean normalized,
4136 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004137 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004138{
Shao80957d92017-02-20 21:25:59 +08004139 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004140 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004141 return false;
4142 }
4143
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004144 if (stride < 0)
4145 {
Shao80957d92017-02-20 21:25:59 +08004146 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004147 return false;
4148 }
4149
Shao80957d92017-02-20 21:25:59 +08004150 const Caps &caps = context->getCaps();
4151 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004152 {
Shao80957d92017-02-20 21:25:59 +08004153 if (stride > caps.maxVertexAttribStride)
4154 {
4155 context->handleError(
4156 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
4157 return false;
4158 }
4159
4160 if (index >= caps.maxVertexAttribBindings)
4161 {
4162 context->handleError(
4163 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
4164 return false;
4165 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004166 }
4167
4168 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4169 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4170 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4171 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004172 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4173 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004174 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004175 {
4176 context->handleError(
4177 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08004178 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004179 return false;
4180 }
4181
4182 if (context->getExtensions().webglCompatibility)
4183 {
4184 // WebGL 1.0 [Section 6.14] Fixed point support
4185 // The WebGL API does not support the GL_FIXED data type.
4186 if (type == GL_FIXED)
4187 {
4188 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4189 return false;
4190 }
4191
Geoff Lang2d62ab72017-03-23 16:54:40 -04004192 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004193 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004194 return false;
4195 }
4196 }
4197
4198 return true;
4199}
4200
Jamie Madill876429b2017-04-20 15:46:24 -04004201bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004202{
4203 if (context->getExtensions().webglCompatibility && zNear > zFar)
4204 {
4205 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4206 return false;
4207 }
4208
4209 return true;
4210}
4211
Jamie Madille8fb6402017-02-14 17:56:40 -05004212bool ValidateRenderbufferStorage(ValidationContext *context,
4213 GLenum target,
4214 GLenum internalformat,
4215 GLsizei width,
4216 GLsizei height)
4217{
4218 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4219 height);
4220}
4221
4222bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4223 GLenum target,
4224 GLsizei samples,
4225 GLenum internalformat,
4226 GLsizei width,
4227 GLsizei height)
4228{
4229 if (!context->getExtensions().framebufferMultisample)
4230 {
4231 context->handleError(
4232 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4233 return false;
4234 }
4235
4236 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4237 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4238 // generated.
4239 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4240 {
4241 context->handleError(Error(GL_INVALID_VALUE));
4242 return false;
4243 }
4244
4245 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4246 // the specified storage. This is different than ES 3.0 in which a sample number higher
4247 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4248 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4249 if (context->getClientMajorVersion() >= 3)
4250 {
4251 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4252 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4253 {
4254 context->handleError(Error(GL_OUT_OF_MEMORY));
4255 return false;
4256 }
4257 }
4258
4259 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4260 width, height);
4261}
4262
Jamie Madillc1d770e2017-04-13 17:31:24 -04004263bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4264{
4265 if (!ValidFramebufferTarget(target))
4266 {
4267 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4268 return false;
4269 }
4270
4271 return true;
4272}
4273
4274bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004275 GLfloat red,
4276 GLfloat green,
4277 GLfloat blue,
4278 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004279{
4280 return true;
4281}
4282
Jamie Madill876429b2017-04-20 15:46:24 -04004283bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004284{
4285 return true;
4286}
4287
4288bool ValidateClearStencil(ValidationContext *context, GLint s)
4289{
4290 return true;
4291}
4292
4293bool ValidateColorMask(ValidationContext *context,
4294 GLboolean red,
4295 GLboolean green,
4296 GLboolean blue,
4297 GLboolean alpha)
4298{
4299 return true;
4300}
4301
4302bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4303{
4304 return true;
4305}
4306
4307bool ValidateCreateProgram(ValidationContext *context)
4308{
4309 return true;
4310}
4311
4312bool ValidateCullFace(ValidationContext *context, GLenum mode)
4313{
4314 switch (mode)
4315 {
4316 case GL_FRONT:
4317 case GL_BACK:
4318 case GL_FRONT_AND_BACK:
4319 break;
4320
4321 default:
4322 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
4323 return false;
4324 }
4325
4326 return true;
4327}
4328
4329bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4330{
4331 if (program == 0)
4332 {
4333 return false;
4334 }
4335
4336 if (!context->getProgram(program))
4337 {
4338 if (context->getShader(program))
4339 {
4340 context->handleError(
4341 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
4342 return false;
4343 }
4344 else
4345 {
4346 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4347 return false;
4348 }
4349 }
4350
4351 return true;
4352}
4353
4354bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4355{
4356 if (shader == 0)
4357 {
4358 return false;
4359 }
4360
4361 if (!context->getShader(shader))
4362 {
4363 if (context->getProgram(shader))
4364 {
4365 context->handleError(
4366 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4367 return false;
4368 }
4369 else
4370 {
4371 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4372 return false;
4373 }
4374 }
4375
4376 return true;
4377}
4378
4379bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4380{
4381 switch (func)
4382 {
4383 case GL_NEVER:
4384 case GL_ALWAYS:
4385 case GL_LESS:
4386 case GL_LEQUAL:
4387 case GL_EQUAL:
4388 case GL_GREATER:
4389 case GL_GEQUAL:
4390 case GL_NOTEQUAL:
4391 break;
4392
4393 default:
4394 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4395 return false;
4396 }
4397
4398 return true;
4399}
4400
4401bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4402{
4403 return true;
4404}
4405
4406bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4407{
4408 Program *programObject = GetValidProgram(context, program);
4409 if (!programObject)
4410 {
4411 return false;
4412 }
4413
4414 Shader *shaderObject = GetValidShader(context, shader);
4415 if (!shaderObject)
4416 {
4417 return false;
4418 }
4419
4420 const Shader *attachedShader = nullptr;
4421
4422 switch (shaderObject->getType())
4423 {
4424 case GL_VERTEX_SHADER:
4425 {
4426 attachedShader = programObject->getAttachedVertexShader();
4427 break;
4428 }
4429 case GL_FRAGMENT_SHADER:
4430 {
4431 attachedShader = programObject->getAttachedFragmentShader();
4432 break;
4433 }
4434 case GL_COMPUTE_SHADER:
4435 {
4436 attachedShader = programObject->getAttachedComputeShader();
4437 break;
4438 }
4439 default:
4440 UNREACHABLE();
4441 return false;
4442 }
4443
4444 if (attachedShader != shaderObject)
4445 {
4446 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4447 return false;
4448 }
4449
4450 return true;
4451}
4452
4453bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4454{
4455 if (index >= MAX_VERTEX_ATTRIBS)
4456 {
4457 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4458 return false;
4459 }
4460
4461 return true;
4462}
4463
4464bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4465{
4466 if (index >= MAX_VERTEX_ATTRIBS)
4467 {
4468 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4469 return false;
4470 }
4471
4472 return true;
4473}
4474
4475bool ValidateFinish(ValidationContext *context)
4476{
4477 return true;
4478}
4479
4480bool ValidateFlush(ValidationContext *context)
4481{
4482 return true;
4483}
4484
4485bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4486{
4487 switch (mode)
4488 {
4489 case GL_CW:
4490 case GL_CCW:
4491 break;
4492 default:
4493 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4494 return false;
4495 }
4496
4497 return true;
4498}
4499
4500bool ValidateGetActiveAttrib(ValidationContext *context,
4501 GLuint program,
4502 GLuint index,
4503 GLsizei bufsize,
4504 GLsizei *length,
4505 GLint *size,
4506 GLenum *type,
4507 GLchar *name)
4508{
4509 if (bufsize < 0)
4510 {
4511 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4512 return false;
4513 }
4514
4515 Program *programObject = GetValidProgram(context, program);
4516
4517 if (!programObject)
4518 {
4519 return false;
4520 }
4521
4522 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4523 {
4524 context->handleError(
4525 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4526 return false;
4527 }
4528
4529 return true;
4530}
4531
4532bool ValidateGetActiveUniform(ValidationContext *context,
4533 GLuint program,
4534 GLuint index,
4535 GLsizei bufsize,
4536 GLsizei *length,
4537 GLint *size,
4538 GLenum *type,
4539 GLchar *name)
4540{
4541 if (bufsize < 0)
4542 {
4543 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4544 return false;
4545 }
4546
4547 Program *programObject = GetValidProgram(context, program);
4548
4549 if (!programObject)
4550 {
4551 return false;
4552 }
4553
4554 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4555 {
4556 context->handleError(
4557 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4558 return false;
4559 }
4560
4561 return true;
4562}
4563
4564bool ValidateGetAttachedShaders(ValidationContext *context,
4565 GLuint program,
4566 GLsizei maxcount,
4567 GLsizei *count,
4568 GLuint *shaders)
4569{
4570 if (maxcount < 0)
4571 {
4572 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4573 return false;
4574 }
4575
4576 Program *programObject = GetValidProgram(context, program);
4577
4578 if (!programObject)
4579 {
4580 return false;
4581 }
4582
4583 return true;
4584}
4585
4586bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4587{
4588 Program *programObject = GetValidProgram(context, program);
4589
4590 if (!programObject)
4591 {
4592 return false;
4593 }
4594
4595 if (!programObject->isLinked())
4596 {
4597 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4598 return false;
4599 }
4600
4601 return true;
4602}
4603
4604bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4605{
4606 GLenum nativeType;
4607 unsigned int numParams = 0;
4608 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4609}
4610
4611bool ValidateGetError(ValidationContext *context)
4612{
4613 return true;
4614}
4615
4616bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4617{
4618 GLenum nativeType;
4619 unsigned int numParams = 0;
4620 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4621}
4622
4623bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4624{
4625 GLenum nativeType;
4626 unsigned int numParams = 0;
4627 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4628}
4629
4630bool ValidateGetProgramInfoLog(ValidationContext *context,
4631 GLuint program,
4632 GLsizei bufsize,
4633 GLsizei *length,
4634 GLchar *infolog)
4635{
4636 if (bufsize < 0)
4637 {
4638 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4639 return false;
4640 }
4641
4642 Program *programObject = GetValidProgram(context, program);
4643 if (!programObject)
4644 {
4645 return false;
4646 }
4647
4648 return true;
4649}
4650
4651bool ValidateGetShaderInfoLog(ValidationContext *context,
4652 GLuint shader,
4653 GLsizei bufsize,
4654 GLsizei *length,
4655 GLchar *infolog)
4656{
4657 if (bufsize < 0)
4658 {
4659 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4660 return false;
4661 }
4662
4663 Shader *shaderObject = GetValidShader(context, shader);
4664 if (!shaderObject)
4665 {
4666 return false;
4667 }
4668
4669 return true;
4670}
4671
4672bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4673 GLenum shadertype,
4674 GLenum precisiontype,
4675 GLint *range,
4676 GLint *precision)
4677{
4678 switch (shadertype)
4679 {
4680 case GL_VERTEX_SHADER:
4681 case GL_FRAGMENT_SHADER:
4682 break;
4683 case GL_COMPUTE_SHADER:
4684 context->handleError(
4685 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4686 return false;
4687 default:
4688 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4689 return false;
4690 }
4691
4692 switch (precisiontype)
4693 {
4694 case GL_LOW_FLOAT:
4695 case GL_MEDIUM_FLOAT:
4696 case GL_HIGH_FLOAT:
4697 case GL_LOW_INT:
4698 case GL_MEDIUM_INT:
4699 case GL_HIGH_INT:
4700 break;
4701
4702 default:
4703 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4704 return false;
4705 }
4706
4707 return true;
4708}
4709
4710bool ValidateGetShaderSource(ValidationContext *context,
4711 GLuint shader,
4712 GLsizei bufsize,
4713 GLsizei *length,
4714 GLchar *source)
4715{
4716 if (bufsize < 0)
4717 {
4718 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4719 return false;
4720 }
4721
4722 Shader *shaderObject = GetValidShader(context, shader);
4723 if (!shaderObject)
4724 {
4725 return false;
4726 }
4727
4728 return true;
4729}
4730
4731bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4732{
4733 if (strstr(name, "gl_") == name)
4734 {
4735 return false;
4736 }
4737
4738 Program *programObject = GetValidProgram(context, program);
4739
4740 if (!programObject)
4741 {
4742 return false;
4743 }
4744
4745 if (!programObject->isLinked())
4746 {
4747 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4748 return false;
4749 }
4750
4751 return true;
4752}
4753
4754bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4755{
4756 switch (mode)
4757 {
4758 case GL_FASTEST:
4759 case GL_NICEST:
4760 case GL_DONT_CARE:
4761 break;
4762
4763 default:
4764 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4765 return false;
4766 }
4767
4768 switch (target)
4769 {
4770 case GL_GENERATE_MIPMAP_HINT:
4771 break;
4772
4773 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4774 if (!context->getExtensions().standardDerivatives)
4775 {
4776 context->handleError(
4777 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4778 return false;
4779 }
4780 break;
4781
4782 default:
4783 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4784 return false;
4785 }
4786
4787 return true;
4788}
4789
4790bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4791{
4792 return true;
4793}
4794
4795bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4796{
4797 return true;
4798}
4799
4800bool ValidateIsProgram(ValidationContext *context, GLuint program)
4801{
4802 return true;
4803}
4804
4805bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4806{
4807 return true;
4808}
4809
4810bool ValidateIsShader(ValidationContext *context, GLuint shader)
4811{
4812 return true;
4813}
4814
4815bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4816{
4817 return true;
4818}
4819
4820bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4821{
4822 if (context->getClientMajorVersion() < 3)
4823 {
4824 switch (pname)
4825 {
4826 case GL_UNPACK_IMAGE_HEIGHT:
4827 case GL_UNPACK_SKIP_IMAGES:
4828 context->handleError(Error(GL_INVALID_ENUM));
4829 return false;
4830
4831 case GL_UNPACK_ROW_LENGTH:
4832 case GL_UNPACK_SKIP_ROWS:
4833 case GL_UNPACK_SKIP_PIXELS:
4834 if (!context->getExtensions().unpackSubimage)
4835 {
4836 context->handleError(Error(GL_INVALID_ENUM));
4837 return false;
4838 }
4839 break;
4840
4841 case GL_PACK_ROW_LENGTH:
4842 case GL_PACK_SKIP_ROWS:
4843 case GL_PACK_SKIP_PIXELS:
4844 if (!context->getExtensions().packSubimage)
4845 {
4846 context->handleError(Error(GL_INVALID_ENUM));
4847 return false;
4848 }
4849 break;
4850 }
4851 }
4852
4853 if (param < 0)
4854 {
4855 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4856 return false;
4857 }
4858
4859 switch (pname)
4860 {
4861 case GL_UNPACK_ALIGNMENT:
4862 if (param != 1 && param != 2 && param != 4 && param != 8)
4863 {
4864 context->handleError(Error(GL_INVALID_VALUE));
4865 return false;
4866 }
4867 break;
4868
4869 case GL_PACK_ALIGNMENT:
4870 if (param != 1 && param != 2 && param != 4 && param != 8)
4871 {
4872 context->handleError(Error(GL_INVALID_VALUE));
4873 return false;
4874 }
4875 break;
4876
4877 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4878 case GL_UNPACK_ROW_LENGTH:
4879 case GL_UNPACK_IMAGE_HEIGHT:
4880 case GL_UNPACK_SKIP_IMAGES:
4881 case GL_UNPACK_SKIP_ROWS:
4882 case GL_UNPACK_SKIP_PIXELS:
4883 case GL_PACK_ROW_LENGTH:
4884 case GL_PACK_SKIP_ROWS:
4885 case GL_PACK_SKIP_PIXELS:
4886 break;
4887
4888 default:
4889 context->handleError(Error(GL_INVALID_ENUM));
4890 return false;
4891 }
4892
4893 return true;
4894}
4895
4896bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4897{
4898 return true;
4899}
4900
4901bool ValidateReleaseShaderCompiler(ValidationContext *context)
4902{
4903 return true;
4904}
4905
Jamie Madill876429b2017-04-20 15:46:24 -04004906bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004907{
4908 return true;
4909}
4910
4911bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4912{
4913 if (width < 0 || height < 0)
4914 {
4915 context->handleError(
4916 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4917 return false;
4918 }
4919
4920 return true;
4921}
4922
4923bool ValidateShaderBinary(ValidationContext *context,
4924 GLsizei n,
4925 const GLuint *shaders,
4926 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04004927 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04004928 GLsizei length)
4929{
4930 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4931 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4932 shaderBinaryFormats.end())
4933 {
4934 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4935 return false;
4936 }
4937
4938 return true;
4939}
4940
4941bool ValidateShaderSource(ValidationContext *context,
4942 GLuint shader,
4943 GLsizei count,
4944 const GLchar *const *string,
4945 const GLint *length)
4946{
4947 if (count < 0)
4948 {
4949 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4950 return false;
4951 }
4952
4953 Shader *shaderObject = GetValidShader(context, shader);
4954 if (!shaderObject)
4955 {
4956 return false;
4957 }
4958
4959 return true;
4960}
4961
4962bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4963{
4964 if (!IsValidStencilFunc(func))
4965 {
4966 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4967 return false;
4968 }
4969
4970 return true;
4971}
4972
4973bool ValidateStencilFuncSeparate(ValidationContext *context,
4974 GLenum face,
4975 GLenum func,
4976 GLint ref,
4977 GLuint mask)
4978{
4979 if (!IsValidStencilFace(face))
4980 {
4981 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4982 return false;
4983 }
4984
4985 if (!IsValidStencilFunc(func))
4986 {
4987 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4988 return false;
4989 }
4990
4991 return true;
4992}
4993
4994bool ValidateStencilMask(ValidationContext *context, GLuint mask)
4995{
4996 return true;
4997}
4998
4999bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5000{
5001 if (!IsValidStencilFace(face))
5002 {
5003 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5004 return false;
5005 }
5006
5007 return true;
5008}
5009
5010bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5011{
5012 if (!IsValidStencilOp(fail))
5013 {
5014 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
5015 return false;
5016 }
5017
5018 if (!IsValidStencilOp(zfail))
5019 {
5020 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
5021 return false;
5022 }
5023
5024 if (!IsValidStencilOp(zpass))
5025 {
5026 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
5027 return false;
5028 }
5029
5030 return true;
5031}
5032
5033bool ValidateStencilOpSeparate(ValidationContext *context,
5034 GLenum face,
5035 GLenum fail,
5036 GLenum zfail,
5037 GLenum zpass)
5038{
5039 if (!IsValidStencilFace(face))
5040 {
5041 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5042 return false;
5043 }
5044
5045 return ValidateStencilOp(context, fail, zfail, zpass);
5046}
5047
5048bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5049{
5050 return ValidateUniform(context, GL_FLOAT, location, 1);
5051}
5052
5053bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5054{
5055 return ValidateUniform(context, GL_FLOAT, location, count);
5056}
5057
Jamie Madillbe849e42017-05-02 15:49:00 -04005058bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5059{
5060 return ValidateUniform1iv(context, location, 1, &x);
5061}
5062
Jamie Madillc1d770e2017-04-13 17:31:24 -04005063bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5064{
5065 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5066}
5067
5068bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5069{
5070 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5071}
5072
5073bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5074{
5075 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5076}
5077
5078bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5079{
5080 return ValidateUniform(context, GL_INT_VEC2, location, count);
5081}
5082
5083bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5084{
5085 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5086}
5087
5088bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5089{
5090 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5091}
5092
5093bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5094{
5095 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5096}
5097
5098bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5099{
5100 return ValidateUniform(context, GL_INT_VEC3, location, count);
5101}
5102
5103bool ValidateUniform4f(ValidationContext *context,
5104 GLint location,
5105 GLfloat x,
5106 GLfloat y,
5107 GLfloat z,
5108 GLfloat w)
5109{
5110 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5111}
5112
5113bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5114{
5115 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5116}
5117
5118bool ValidateUniform4i(ValidationContext *context,
5119 GLint location,
5120 GLint x,
5121 GLint y,
5122 GLint z,
5123 GLint w)
5124{
5125 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5126}
5127
5128bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5129{
5130 return ValidateUniform(context, GL_INT_VEC4, location, count);
5131}
5132
5133bool ValidateUniformMatrix2fv(ValidationContext *context,
5134 GLint location,
5135 GLsizei count,
5136 GLboolean transpose,
5137 const GLfloat *value)
5138{
5139 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5140}
5141
5142bool ValidateUniformMatrix3fv(ValidationContext *context,
5143 GLint location,
5144 GLsizei count,
5145 GLboolean transpose,
5146 const GLfloat *value)
5147{
5148 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5149}
5150
5151bool ValidateUniformMatrix4fv(ValidationContext *context,
5152 GLint location,
5153 GLsizei count,
5154 GLboolean transpose,
5155 const GLfloat *value)
5156{
5157 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5158}
5159
5160bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5161{
5162 Program *programObject = GetValidProgram(context, program);
5163
5164 if (!programObject)
5165 {
5166 return false;
5167 }
5168
5169 return true;
5170}
5171
5172bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5173{
5174 if (index >= MAX_VERTEX_ATTRIBS)
5175 {
5176 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
5177 return false;
5178 }
5179
5180 return true;
5181}
5182
5183bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5184{
5185 return ValidateVertexAttribIndex(context, index);
5186}
5187
5188bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5189{
5190 return ValidateVertexAttribIndex(context, index);
5191}
5192
5193bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5194{
5195 return ValidateVertexAttribIndex(context, index);
5196}
5197
5198bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5199{
5200 return ValidateVertexAttribIndex(context, index);
5201}
5202
5203bool ValidateVertexAttrib3f(ValidationContext *context,
5204 GLuint index,
5205 GLfloat x,
5206 GLfloat y,
5207 GLfloat z)
5208{
5209 return ValidateVertexAttribIndex(context, index);
5210}
5211
5212bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5213{
5214 return ValidateVertexAttribIndex(context, index);
5215}
5216
5217bool ValidateVertexAttrib4f(ValidationContext *context,
5218 GLuint index,
5219 GLfloat x,
5220 GLfloat y,
5221 GLfloat z,
5222 GLfloat w)
5223{
5224 return ValidateVertexAttribIndex(context, index);
5225}
5226
5227bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5228{
5229 return ValidateVertexAttribIndex(context, index);
5230}
5231
5232bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5233{
5234 if (width < 0 || height < 0)
5235 {
5236 context->handleError(
5237 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
5238 return false;
5239 }
5240
5241 return true;
5242}
5243
5244bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5245{
5246 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5247}
5248
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005249bool ValidateDrawElements(ValidationContext *context,
5250 GLenum mode,
5251 GLsizei count,
5252 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005253 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005254{
5255 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5256}
5257
Jamie Madillbe849e42017-05-02 15:49:00 -04005258bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5259 GLenum target,
5260 GLenum attachment,
5261 GLenum pname,
5262 GLint *params)
5263{
5264 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5265 nullptr);
5266}
5267
5268bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5269{
5270 return ValidateGetProgramivBase(context, program, pname, nullptr);
5271}
5272
5273bool ValidateCopyTexImage2D(ValidationContext *context,
5274 GLenum target,
5275 GLint level,
5276 GLenum internalformat,
5277 GLint x,
5278 GLint y,
5279 GLsizei width,
5280 GLsizei height,
5281 GLint border)
5282{
5283 if (context->getClientMajorVersion() < 3)
5284 {
5285 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5286 0, x, y, width, height, border);
5287 }
5288
5289 ASSERT(context->getClientMajorVersion() == 3);
5290 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5291 0, x, y, width, height, border);
5292}
5293
5294bool ValidateCopyTexSubImage2D(Context *context,
5295 GLenum target,
5296 GLint level,
5297 GLint xoffset,
5298 GLint yoffset,
5299 GLint x,
5300 GLint y,
5301 GLsizei width,
5302 GLsizei height)
5303{
5304 if (context->getClientMajorVersion() < 3)
5305 {
5306 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5307 yoffset, x, y, width, height, 0);
5308 }
5309
5310 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5311 yoffset, 0, x, y, width, height, 0);
5312}
5313
5314bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5315{
5316 return ValidateGenOrDelete(context, n);
5317}
5318
5319bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5320{
5321 return ValidateGenOrDelete(context, n);
5322}
5323
5324bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5325{
5326 return ValidateGenOrDelete(context, n);
5327}
5328
5329bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5330{
5331 return ValidateGenOrDelete(context, n);
5332}
5333
5334bool ValidateDisable(Context *context, GLenum cap)
5335{
5336 if (!ValidCap(context, cap, false))
5337 {
5338 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5339 return false;
5340 }
5341
5342 return true;
5343}
5344
5345bool ValidateEnable(Context *context, GLenum cap)
5346{
5347 if (!ValidCap(context, cap, false))
5348 {
5349 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5350 return false;
5351 }
5352
5353 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5354 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5355 {
5356 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5357 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5358
5359 // We also output an error message to the debugger window if tracing is active, so that
5360 // developers can see the error message.
5361 ERR() << errorMessage;
5362 return false;
5363 }
5364
5365 return true;
5366}
5367
5368bool ValidateFramebufferRenderbuffer(Context *context,
5369 GLenum target,
5370 GLenum attachment,
5371 GLenum renderbuffertarget,
5372 GLuint renderbuffer)
5373{
5374 if (!ValidFramebufferTarget(target) ||
5375 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5376 {
5377 context->handleError(Error(GL_INVALID_ENUM));
5378 return false;
5379 }
5380
5381 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5382 renderbuffertarget, renderbuffer);
5383}
5384
5385bool ValidateFramebufferTexture2D(Context *context,
5386 GLenum target,
5387 GLenum attachment,
5388 GLenum textarget,
5389 GLuint texture,
5390 GLint level)
5391{
5392 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5393 // extension
5394 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5395 level != 0)
5396 {
5397 context->handleError(Error(GL_INVALID_VALUE));
5398 return false;
5399 }
5400
5401 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5402 {
5403 return false;
5404 }
5405
5406 if (texture != 0)
5407 {
5408 gl::Texture *tex = context->getTexture(texture);
5409 ASSERT(tex);
5410
5411 const gl::Caps &caps = context->getCaps();
5412
5413 switch (textarget)
5414 {
5415 case GL_TEXTURE_2D:
5416 {
5417 if (level > gl::log2(caps.max2DTextureSize))
5418 {
5419 context->handleError(Error(GL_INVALID_VALUE));
5420 return false;
5421 }
5422 if (tex->getTarget() != GL_TEXTURE_2D)
5423 {
5424 context->handleError(Error(GL_INVALID_OPERATION,
5425 "Textarget must match the texture target type."));
5426 return false;
5427 }
5428 }
5429 break;
5430
5431 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5432 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5433 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5434 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5435 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5436 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5437 {
5438 if (level > gl::log2(caps.maxCubeMapTextureSize))
5439 {
5440 context->handleError(Error(GL_INVALID_VALUE));
5441 return false;
5442 }
5443 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5444 {
5445 context->handleError(Error(GL_INVALID_OPERATION,
5446 "Textarget must match the texture target type."));
5447 return false;
5448 }
5449 }
5450 break;
5451
5452 case GL_TEXTURE_2D_MULTISAMPLE:
5453 {
5454 if (context->getClientVersion() < ES_3_1)
5455 {
5456 context->handleError(Error(GL_INVALID_OPERATION,
5457 "Texture target requires at least OpenGL ES 3.1."));
5458 return false;
5459 }
5460
5461 if (level != 0)
5462 {
5463 context->handleError(
5464 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
5465 return false;
5466 }
5467 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5468 {
5469 context->handleError(Error(GL_INVALID_OPERATION,
5470 "Textarget must match the texture target type."));
5471 return false;
5472 }
5473 }
5474 break;
5475
5476 default:
5477 context->handleError(Error(GL_INVALID_ENUM));
5478 return false;
5479 }
5480
5481 const Format &format = tex->getFormat(textarget, level);
5482 if (format.info->compressed)
5483 {
5484 context->handleError(Error(GL_INVALID_OPERATION));
5485 return false;
5486 }
5487 }
5488
5489 return true;
5490}
5491
5492bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5493{
5494 return ValidateGenOrDelete(context, n);
5495}
5496
5497bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5498{
5499 return ValidateGenOrDelete(context, n);
5500}
5501
5502bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5503{
5504 return ValidateGenOrDelete(context, n);
5505}
5506
5507bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5508{
5509 return ValidateGenOrDelete(context, n);
5510}
5511
5512bool ValidateGenerateMipmap(Context *context, GLenum target)
5513{
5514 if (!ValidTextureTarget(context, target))
5515 {
5516 context->handleError(Error(GL_INVALID_ENUM));
5517 return false;
5518 }
5519
5520 Texture *texture = context->getTargetTexture(target);
5521
5522 if (texture == nullptr)
5523 {
5524 context->handleError(Error(GL_INVALID_OPERATION));
5525 return false;
5526 }
5527
5528 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5529
5530 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5531 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5532 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5533 {
5534 context->handleError(Error(GL_INVALID_OPERATION));
5535 return false;
5536 }
5537
5538 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5539 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5540 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5541
5542 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5543 // unsized formats or that are color renderable and filterable. Since we do not track if
5544 // the texture was created with sized or unsized format (only sized formats are stored),
5545 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5546 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5547 // textures since they're the only texture format that can be created with unsized formats
5548 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5549 // was the last version to use add them.
5550 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5551 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5552 {
5553 context->handleError(Error(GL_INVALID_OPERATION));
5554 return false;
5555 }
5556
Geoff Lang65ac5b92017-05-01 13:16:30 -04005557 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5558 bool supportsSRGBMipmapGeneration =
5559 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5560 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005561 {
Geoff Lang65ac5b92017-05-01 13:16:30 -04005562 context->handleError(
5563 Error(GL_INVALID_OPERATION, "Mipmap generation of sRGB textures is not allowed."));
Jamie Madillbe849e42017-05-02 15:49:00 -04005564 return false;
5565 }
5566
5567 // Non-power of 2 ES2 check
5568 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5569 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5570 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5571 {
5572 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
5573 context->handleError(Error(GL_INVALID_OPERATION));
5574 return false;
5575 }
5576
5577 // Cube completeness check
5578 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5579 {
5580 context->handleError(Error(GL_INVALID_OPERATION));
5581 return false;
5582 }
5583
5584 return true;
5585}
5586
5587bool ValidateGetBufferParameteriv(ValidationContext *context,
5588 GLenum target,
5589 GLenum pname,
5590 GLint *params)
5591{
5592 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5593}
5594
5595bool ValidateGetRenderbufferParameteriv(Context *context,
5596 GLenum target,
5597 GLenum pname,
5598 GLint *params)
5599{
5600 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5601}
5602
5603bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5604{
5605 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5606}
5607
5608bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5609{
5610 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5611}
5612
5613bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5614{
5615 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5616}
5617
5618bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5619{
5620 return ValidateGetUniformBase(context, program, location);
5621}
5622
5623bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5624{
5625 return ValidateGetUniformBase(context, program, location);
5626}
5627
5628bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5629{
5630 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5631}
5632
5633bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5634{
5635 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5636}
5637
5638bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5639{
5640 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5641}
5642
5643bool ValidateIsEnabled(Context *context, GLenum cap)
5644{
5645 if (!ValidCap(context, cap, true))
5646 {
5647 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5648 return false;
5649 }
5650
5651 return true;
5652}
5653
5654bool ValidateLinkProgram(Context *context, GLuint program)
5655{
5656 if (context->hasActiveTransformFeedback(program))
5657 {
5658 // ES 3.0.4 section 2.15 page 91
5659 context->handleError(Error(GL_INVALID_OPERATION,
5660 "Cannot link program while program is associated with an active "
5661 "transform feedback object."));
5662 return false;
5663 }
5664
5665 Program *programObject = GetValidProgram(context, program);
5666 if (!programObject)
5667 {
5668 return false;
5669 }
5670
5671 return true;
5672}
5673
5674bool ValidateReadPixels(ValidationContext *context,
5675 GLint x,
5676 GLint y,
5677 GLsizei width,
5678 GLsizei height,
5679 GLenum format,
5680 GLenum type,
5681 void *pixels)
5682{
5683 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5684 nullptr, pixels);
5685}
5686
5687bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5688{
5689 return ValidateTexParameterBase(context, target, pname, -1, &param);
5690}
5691
5692bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5693{
5694 return ValidateTexParameterBase(context, target, pname, -1, params);
5695}
5696
5697bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5698{
5699 return ValidateTexParameterBase(context, target, pname, -1, &param);
5700}
5701
5702bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5703{
5704 return ValidateTexParameterBase(context, target, pname, -1, params);
5705}
5706
5707bool ValidateUseProgram(Context *context, GLuint program)
5708{
5709 if (program != 0)
5710 {
5711 Program *programObject = context->getProgram(program);
5712 if (!programObject)
5713 {
5714 // ES 3.1.0 section 7.3 page 72
5715 if (context->getShader(program))
5716 {
5717 context->handleError(
5718 Error(GL_INVALID_OPERATION,
5719 "Attempted to use a single shader instead of a shader program."));
5720 return false;
5721 }
5722 else
5723 {
5724 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
5725 return false;
5726 }
5727 }
5728 if (!programObject->isLinked())
5729 {
5730 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
5731 return false;
5732 }
5733 }
5734 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5735 {
5736 // ES 3.0.4 section 2.15 page 91
5737 context->handleError(
5738 Error(GL_INVALID_OPERATION,
5739 "Cannot change active program while transform feedback is unpaused."));
5740 return false;
5741 }
5742
5743 return true;
5744}
5745
Jamie Madillc29968b2016-01-20 11:17:23 -05005746} // namespace gl