blob: 1a76d219401c5da1f84616a0e4f7d4249c21d793 [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 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400383 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
384 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400385 {
386 context->handleError(Error(GL_INVALID_OPERATION));
387 return false;
388 }
389 break;
390 case GL_LUMINANCE:
391 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
392 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
393 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400394 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
395 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400396 {
397 context->handleError(Error(GL_INVALID_OPERATION));
398 return false;
399 }
400 break;
401 case GL_RED_EXT:
402 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
403 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
404 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
405 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
406 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400407 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
408 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400409 {
410 context->handleError(Error(GL_INVALID_OPERATION));
411 return false;
412 }
413 break;
414 case GL_RG_EXT:
415 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
416 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
417 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
418 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400419 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
420 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400421 {
422 context->handleError(Error(GL_INVALID_OPERATION));
423 return false;
424 }
425 break;
426 case GL_RGB:
427 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
428 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
429 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400430 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
431 colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400432 {
433 context->handleError(Error(GL_INVALID_OPERATION));
434 return false;
435 }
436 break;
437 case GL_LUMINANCE_ALPHA:
438 case GL_RGBA:
439 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
Geoff Lang0c09e262017-05-03 09:43:13 -0400440 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
441 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
Jamie Madillbe849e42017-05-02 15:49:00 -0400442 {
443 context->handleError(Error(GL_INVALID_OPERATION));
444 return false;
445 }
446 break;
447 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
448 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
449 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
450 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
451 case GL_ETC1_RGB8_OES:
452 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
453 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
454 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
455 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
456 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
457 context->handleError(Error(GL_INVALID_OPERATION));
458 return false;
459 case GL_DEPTH_COMPONENT:
460 case GL_DEPTH_STENCIL_OES:
461 context->handleError(Error(GL_INVALID_OPERATION));
462 return false;
463 default:
464 context->handleError(Error(GL_INVALID_OPERATION));
465 return false;
466 }
467
468 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
469 {
470 context->handleError(Error(GL_INVALID_OPERATION));
471 return false;
472 }
473 }
474 else
475 {
476 switch (internalformat)
477 {
478 case GL_ALPHA:
479 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
480 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
481 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
482 {
483 context->handleError(Error(GL_INVALID_OPERATION));
484 return false;
485 }
486 break;
487 case GL_LUMINANCE:
488 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
489 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
490 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
491 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
492 colorbufferFormat != GL_BGR5_A1_ANGLEX)
493 {
494 context->handleError(Error(GL_INVALID_OPERATION));
495 return false;
496 }
497 break;
498 case GL_RED_EXT:
499 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
500 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
501 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
502 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
503 colorbufferFormat != GL_BGR5_A1_ANGLEX)
504 {
505 context->handleError(Error(GL_INVALID_OPERATION));
506 return false;
507 }
508 break;
509 case GL_RG_EXT:
510 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
511 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
512 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
513 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
514 {
515 context->handleError(Error(GL_INVALID_OPERATION));
516 return false;
517 }
518 break;
519 case GL_RGB:
520 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
521 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
522 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
523 colorbufferFormat != GL_BGR5_A1_ANGLEX)
524 {
525 context->handleError(Error(GL_INVALID_OPERATION));
526 return false;
527 }
528 break;
529 case GL_LUMINANCE_ALPHA:
530 case GL_RGBA:
531 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
532 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
533 colorbufferFormat != GL_BGR5_A1_ANGLEX)
534 {
535 context->handleError(Error(GL_INVALID_OPERATION));
536 return false;
537 }
538 break;
539 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
540 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
541 if (context->getExtensions().textureCompressionDXT1)
542 {
543 context->handleError(Error(GL_INVALID_OPERATION));
544 return false;
545 }
546 else
547 {
548 context->handleError(Error(GL_INVALID_ENUM));
549 return false;
550 }
551 break;
552 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
553 if (context->getExtensions().textureCompressionDXT3)
554 {
555 context->handleError(Error(GL_INVALID_OPERATION));
556 return false;
557 }
558 else
559 {
560 context->handleError(Error(GL_INVALID_ENUM));
561 return false;
562 }
563 break;
564 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
565 if (context->getExtensions().textureCompressionDXT5)
566 {
567 context->handleError(Error(GL_INVALID_OPERATION));
568 return false;
569 }
570 else
571 {
572 context->handleError(Error(GL_INVALID_ENUM));
573 return false;
574 }
575 break;
576 case GL_ETC1_RGB8_OES:
577 if (context->getExtensions().compressedETC1RGB8Texture)
578 {
579 context->handleError(Error(GL_INVALID_OPERATION));
580 return false;
581 }
582 else
583 {
584 context->handleError(Error(GL_INVALID_ENUM));
585 return false;
586 }
587 break;
588 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
589 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
590 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
591 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
592 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
593 if (context->getExtensions().lossyETCDecode)
594 {
595 context->handleError(Error(GL_INVALID_OPERATION,
596 "ETC lossy decode formats can't be copied to."));
597 return false;
598 }
599 else
600 {
601 context->handleError(Error(
602 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
603 return false;
604 }
605 break;
606 case GL_DEPTH_COMPONENT:
607 case GL_DEPTH_COMPONENT16:
608 case GL_DEPTH_COMPONENT32_OES:
609 case GL_DEPTH_STENCIL_OES:
610 case GL_DEPTH24_STENCIL8_OES:
611 if (context->getExtensions().depthTextures)
612 {
613 context->handleError(Error(GL_INVALID_OPERATION));
614 return false;
615 }
616 else
617 {
618 context->handleError(Error(GL_INVALID_ENUM));
619 return false;
620 }
621 default:
622 context->handleError(Error(GL_INVALID_ENUM));
623 return false;
624 }
625 }
626
627 // If width or height is zero, it is a no-op. Return false without setting an error.
628 return (width > 0 && height > 0);
629}
630
631bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
632{
633 switch (cap)
634 {
635 // EXT_multisample_compatibility
636 case GL_MULTISAMPLE_EXT:
637 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
638 return context->getExtensions().multisampleCompatibility;
639
640 case GL_CULL_FACE:
641 case GL_POLYGON_OFFSET_FILL:
642 case GL_SAMPLE_ALPHA_TO_COVERAGE:
643 case GL_SAMPLE_COVERAGE:
644 case GL_SCISSOR_TEST:
645 case GL_STENCIL_TEST:
646 case GL_DEPTH_TEST:
647 case GL_BLEND:
648 case GL_DITHER:
649 return true;
650
651 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
652 case GL_RASTERIZER_DISCARD:
653 return (context->getClientMajorVersion() >= 3);
654
655 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
656 case GL_DEBUG_OUTPUT:
657 return context->getExtensions().debug;
658
659 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
660 return queryOnly && context->getExtensions().bindGeneratesResource;
661
662 case GL_CLIENT_ARRAYS_ANGLE:
663 return queryOnly && context->getExtensions().clientArrays;
664
665 case GL_FRAMEBUFFER_SRGB_EXT:
666 return context->getExtensions().sRGBWriteControl;
667
668 case GL_SAMPLE_MASK:
669 return context->getClientVersion() >= Version(3, 1);
670
671 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
672 return queryOnly && context->getExtensions().robustResourceInitialization;
673
674 default:
675 return false;
676 }
677}
678
Jamie Madillc29968b2016-01-20 11:17:23 -0500679} // anonymous namespace
680
Geoff Langff5b2d52016-09-07 11:32:23 -0400681bool ValidateES2TexImageParameters(Context *context,
682 GLenum target,
683 GLint level,
684 GLenum internalformat,
685 bool isCompressed,
686 bool isSubImage,
687 GLint xoffset,
688 GLint yoffset,
689 GLsizei width,
690 GLsizei height,
691 GLint border,
692 GLenum format,
693 GLenum type,
694 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400695 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696{
Jamie Madill6f38f822014-06-06 17:12:20 -0400697 if (!ValidTexture2DDestinationTarget(context, target))
698 {
Jamie Madill437fa652016-05-03 15:13:24 -0400699 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400700 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400701 }
702
Austin Kinross08528e12015-10-07 16:24:40 -0700703 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400704 {
Jamie Madill437fa652016-05-03 15:13:24 -0400705 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400706 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400707 }
708
He Yunchaoced53ae2016-11-29 15:00:51 +0800709 if (level < 0 || xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400710 std::numeric_limits<GLsizei>::max() - yoffset < height)
711 {
Jamie Madill437fa652016-05-03 15:13:24 -0400712 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400713 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400714 }
715
Geoff Lang005df412013-10-16 14:12:50 -0400716 if (!isSubImage && !isCompressed && internalformat != format)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400717 {
Jamie Madill437fa652016-05-03 15:13:24 -0400718 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400719 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400720 }
721
Geoff Langaae65a42014-05-26 12:43:44 -0400722 const gl::Caps &caps = context->getCaps();
723
Geoff Langa9be0dc2014-12-17 12:34:40 -0500724 if (target == GL_TEXTURE_2D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400725 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500726 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
727 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400728 {
Jamie Madill437fa652016-05-03 15:13:24 -0400729 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400731 }
Geoff Langa9be0dc2014-12-17 12:34:40 -0500732 }
Geoff Lang691e58c2014-12-19 17:03:25 -0500733 else if (IsCubeMapTextureTarget(target))
Geoff Langa9be0dc2014-12-17 12:34:40 -0500734 {
735 if (!isSubImage && width != height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400736 {
Jamie Madill437fa652016-05-03 15:13:24 -0400737 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500738 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400739 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400740
Geoff Langa9be0dc2014-12-17 12:34:40 -0500741 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
742 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
743 {
Jamie Madill437fa652016-05-03 15:13:24 -0400744 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500745 return false;
746 }
747 }
748 else
749 {
Jamie Madill437fa652016-05-03 15:13:24 -0400750 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400751 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400752 }
753
He Yunchaoced53ae2016-11-29 15:00:51 +0800754 gl::Texture *texture =
755 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400756 if (!texture)
757 {
Jamie Madill437fa652016-05-03 15:13:24 -0400758 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 }
761
Geoff Langa9be0dc2014-12-17 12:34:40 -0500762 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400763 {
Geoff Langca271392017-04-05 12:30:00 -0400764 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
765 if (textureInternalFormat.internalFormat == GL_NONE)
Geoff Langc51642b2016-11-14 16:18:26 -0500766 {
767 context->handleError(Error(GL_INVALID_OPERATION, "Texture level does not exist."));
768 return false;
769 }
770
Geoff Langa9be0dc2014-12-17 12:34:40 -0500771 if (format != GL_NONE)
772 {
Geoff Langca271392017-04-05 12:30:00 -0400773 if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
774 textureInternalFormat.sizedInternalFormat)
Geoff Langa9be0dc2014-12-17 12:34:40 -0500775 {
Jamie Madill437fa652016-05-03 15:13:24 -0400776 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500777 return false;
778 }
779 }
780
781 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
782 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
783 {
Jamie Madill437fa652016-05-03 15:13:24 -0400784 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500785 return false;
786 }
787 }
788 else
789 {
Geoff Lang69cce582015-09-17 13:20:36 -0400790 if (texture->getImmutableFormat())
Geoff Langa9be0dc2014-12-17 12:34:40 -0500791 {
Jamie Madill437fa652016-05-03 15:13:24 -0400792 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -0500793 return false;
794 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796
797 // Verify zero border
798 if (border != 0)
799 {
Jamie Madill437fa652016-05-03 15:13:24 -0400800 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400801 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400802 }
803
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 if (isCompressed)
805 {
tmartino0ccd5ae2015-10-01 14:33:14 -0400806 GLenum actualInternalFormat =
Geoff Langca271392017-04-05 12:30:00 -0400807 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
808 : internalformat;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400809 switch (actualInternalFormat)
810 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800811 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
812 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
813 if (!context->getExtensions().textureCompressionDXT1)
814 {
815 context->handleError(Error(GL_INVALID_ENUM));
816 return false;
817 }
818 break;
819 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
820 if (!context->getExtensions().textureCompressionDXT1)
821 {
822 context->handleError(Error(GL_INVALID_ENUM));
823 return false;
824 }
825 break;
826 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
827 if (!context->getExtensions().textureCompressionDXT5)
828 {
829 context->handleError(Error(GL_INVALID_ENUM));
830 return false;
831 }
832 break;
Kai Ninomiya02f075c2016-12-22 14:55:46 -0800833 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
834 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
835 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
836 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
837 if (!context->getExtensions().textureCompressionS3TCsRGB)
838 {
839 context->handleError(Error(GL_INVALID_ENUM));
840 return false;
841 }
842 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800843 case GL_ETC1_RGB8_OES:
844 if (!context->getExtensions().compressedETC1RGB8Texture)
845 {
846 context->handleError(Error(GL_INVALID_ENUM));
847 return false;
848 }
849 break;
850 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800851 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
852 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
853 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
854 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800855 if (!context->getExtensions().lossyETCDecode)
856 {
857 context->handleError(Error(
858 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
859 return false;
860 }
861 break;
862 default:
863 context->handleError(
864 Error(GL_INVALID_ENUM,
865 "internalformat is not a supported compressed internal format"));
Geoff Langb1196682014-07-23 13:47:29 -0400866 return false;
tmartino0ccd5ae2015-10-01 14:33:14 -0400867 }
Geoff Lang966c9402017-04-18 12:38:27 -0400868
869 if (isSubImage)
tmartino0ccd5ae2015-10-01 14:33:14 -0400870 {
Geoff Lang966c9402017-04-18 12:38:27 -0400871 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
872 height, texture->getWidth(target, level),
873 texture->getHeight(target, level)))
874 {
875 context->handleError(
876 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
877 return false;
878 }
879
880 if (format != actualInternalFormat)
881 {
882 context->handleError(Error(
883 GL_INVALID_OPERATION, "Format must match the internal format of the texture."));
884 return false;
885 }
886 }
887 else
888 {
889 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
890 {
891 context->handleError(
892 Error(GL_INVALID_OPERATION, "Invalid compressed format dimension."));
893 return false;
894 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400895 }
896 }
897 else
898 {
899 // validate <type> by itself (used as secondary key below)
900 switch (type)
901 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800902 case GL_UNSIGNED_BYTE:
903 case GL_UNSIGNED_SHORT_5_6_5:
904 case GL_UNSIGNED_SHORT_4_4_4_4:
905 case GL_UNSIGNED_SHORT_5_5_5_1:
906 case GL_UNSIGNED_SHORT:
907 case GL_UNSIGNED_INT:
908 case GL_UNSIGNED_INT_24_8_OES:
909 case GL_HALF_FLOAT_OES:
910 case GL_FLOAT:
911 break;
912 default:
913 context->handleError(Error(GL_INVALID_ENUM));
914 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400915 }
916
917 // validate <format> + <type> combinations
918 // - invalid <format> -> sets INVALID_ENUM
919 // - invalid <format>+<type> combination -> sets INVALID_OPERATION
920 switch (format)
921 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800922 case GL_ALPHA:
923 case GL_LUMINANCE:
924 case GL_LUMINANCE_ALPHA:
925 switch (type)
926 {
927 case GL_UNSIGNED_BYTE:
928 case GL_FLOAT:
929 case GL_HALF_FLOAT_OES:
930 break;
931 default:
932 context->handleError(Error(GL_INVALID_OPERATION));
933 return false;
934 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400935 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800936 case GL_RED:
937 case GL_RG:
938 if (!context->getExtensions().textureRG)
939 {
940 context->handleError(Error(GL_INVALID_ENUM));
941 return false;
942 }
943 switch (type)
944 {
945 case GL_UNSIGNED_BYTE:
946 case GL_FLOAT:
947 case GL_HALF_FLOAT_OES:
948 break;
949 default:
950 context->handleError(Error(GL_INVALID_OPERATION));
951 return false;
952 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800954 case GL_RGB:
955 switch (type)
956 {
957 case GL_UNSIGNED_BYTE:
958 case GL_UNSIGNED_SHORT_5_6_5:
959 case GL_FLOAT:
960 case GL_HALF_FLOAT_OES:
961 break;
962 default:
963 context->handleError(Error(GL_INVALID_OPERATION));
964 return false;
965 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 case GL_RGBA:
968 switch (type)
969 {
970 case GL_UNSIGNED_BYTE:
971 case GL_UNSIGNED_SHORT_4_4_4_4:
972 case GL_UNSIGNED_SHORT_5_5_5_1:
973 case GL_FLOAT:
974 case GL_HALF_FLOAT_OES:
975 break;
976 default:
977 context->handleError(Error(GL_INVALID_OPERATION));
978 return false;
979 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 case GL_BGRA_EXT:
982 switch (type)
983 {
984 case GL_UNSIGNED_BYTE:
985 break;
986 default:
987 context->handleError(Error(GL_INVALID_OPERATION));
988 return false;
989 }
990 break;
991 case GL_SRGB_EXT:
992 case GL_SRGB_ALPHA_EXT:
993 if (!context->getExtensions().sRGB)
994 {
995 context->handleError(Error(GL_INVALID_ENUM));
996 return false;
997 }
998 switch (type)
999 {
1000 case GL_UNSIGNED_BYTE:
1001 break;
1002 default:
1003 context->handleError(Error(GL_INVALID_OPERATION));
1004 return false;
1005 }
1006 break;
1007 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
1008 // handled below
1009 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1010 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1011 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1012 break;
1013 case GL_DEPTH_COMPONENT:
1014 switch (type)
1015 {
1016 case GL_UNSIGNED_SHORT:
1017 case GL_UNSIGNED_INT:
1018 break;
1019 default:
1020 context->handleError(Error(GL_INVALID_OPERATION));
1021 return false;
1022 }
1023 break;
1024 case GL_DEPTH_STENCIL_OES:
1025 switch (type)
1026 {
1027 case GL_UNSIGNED_INT_24_8_OES:
1028 break;
1029 default:
1030 context->handleError(Error(GL_INVALID_OPERATION));
1031 return false;
1032 }
1033 break;
1034 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001035 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001036 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 }
1038
1039 switch (format)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1042 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1043 if (context->getExtensions().textureCompressionDXT1)
1044 {
1045 context->handleError(Error(GL_INVALID_OPERATION));
1046 return false;
1047 }
1048 else
1049 {
1050 context->handleError(Error(GL_INVALID_ENUM));
1051 return false;
1052 }
1053 break;
1054 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1055 if (context->getExtensions().textureCompressionDXT3)
1056 {
1057 context->handleError(Error(GL_INVALID_OPERATION));
1058 return false;
1059 }
1060 else
1061 {
1062 context->handleError(Error(GL_INVALID_ENUM));
1063 return false;
1064 }
1065 break;
1066 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1067 if (context->getExtensions().textureCompressionDXT5)
1068 {
1069 context->handleError(Error(GL_INVALID_OPERATION));
1070 return false;
1071 }
1072 else
1073 {
1074 context->handleError(Error(GL_INVALID_ENUM));
1075 return false;
1076 }
1077 break;
1078 case GL_ETC1_RGB8_OES:
1079 if (context->getExtensions().compressedETC1RGB8Texture)
1080 {
1081 context->handleError(Error(GL_INVALID_OPERATION));
1082 return false;
1083 }
1084 else
1085 {
1086 context->handleError(Error(GL_INVALID_ENUM));
1087 return false;
1088 }
1089 break;
1090 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001091 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1092 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1093 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1094 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 if (context->getExtensions().lossyETCDecode)
1096 {
1097 context->handleError(
1098 Error(GL_INVALID_OPERATION,
Minmin Gong390208b2017-02-28 18:03:06 -08001099 "ETC lossy decode formats can't work with this type."));
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 return false;
1101 }
1102 else
1103 {
1104 context->handleError(Error(
1105 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1106 return false;
1107 }
1108 break;
1109 case GL_DEPTH_COMPONENT:
1110 case GL_DEPTH_STENCIL_OES:
1111 if (!context->getExtensions().depthTextures)
1112 {
1113 context->handleError(Error(GL_INVALID_VALUE));
1114 return false;
1115 }
1116 if (target != GL_TEXTURE_2D)
1117 {
1118 context->handleError(Error(GL_INVALID_OPERATION));
1119 return false;
1120 }
1121 // OES_depth_texture supports loading depth data and multiple levels,
1122 // but ANGLE_depth_texture does not
Yunchao He4f285442017-04-21 12:15:49 +08001123 if (pixels != nullptr || level != 0)
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 {
1125 context->handleError(Error(GL_INVALID_OPERATION));
1126 return false;
1127 }
1128 break;
1129 default:
1130 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131 }
1132
1133 if (type == GL_FLOAT)
1134 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001135 if (!context->getExtensions().textureFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 {
Jamie Madill437fa652016-05-03 15:13:24 -04001137 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 }
1140 }
1141 else if (type == GL_HALF_FLOAT_OES)
1142 {
Geoff Langc0b9ef42014-07-02 10:02:37 -04001143 if (!context->getExtensions().textureHalfFloat)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 {
Jamie Madill437fa652016-05-03 15:13:24 -04001145 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148 }
1149 }
1150
Geoff Langff5b2d52016-09-07 11:32:23 -04001151 if (!ValidImageDataSize(context, target, width, height, 1, internalformat, type, pixels,
1152 imageSize))
1153 {
1154 return false;
1155 }
1156
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 return true;
1158}
1159
He Yunchaoced53ae2016-11-29 15:00:51 +08001160bool ValidateES2TexStorageParameters(Context *context,
1161 GLenum target,
1162 GLsizei levels,
1163 GLenum internalformat,
1164 GLsizei width,
1165 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001166{
1167 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
1168 {
Jamie Madill437fa652016-05-03 15:13:24 -04001169 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001171 }
1172
1173 if (width < 1 || height < 1 || levels < 1)
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 (target == GL_TEXTURE_CUBE_MAP && width != height)
1180 {
Jamie Madill437fa652016-05-03 15:13:24 -04001181 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001182 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183 }
1184
1185 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
1186 {
Jamie Madill437fa652016-05-03 15:13:24 -04001187 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
Geoff Langca271392017-04-05 12:30:00 -04001191 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001192 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001193 {
Jamie Madill437fa652016-05-03 15:13:24 -04001194 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001195 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001196 }
1197
Geoff Langaae65a42014-05-26 12:43:44 -04001198 const gl::Caps &caps = context->getCaps();
1199
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001200 switch (target)
1201 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 case GL_TEXTURE_2D:
1203 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1204 static_cast<GLuint>(height) > caps.max2DTextureSize)
1205 {
1206 context->handleError(Error(GL_INVALID_VALUE));
1207 return false;
1208 }
1209 break;
1210 case GL_TEXTURE_CUBE_MAP:
1211 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
1212 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
1213 {
1214 context->handleError(Error(GL_INVALID_VALUE));
1215 return false;
1216 }
1217 break;
1218 default:
1219 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001221 }
1222
Geoff Langc0b9ef42014-07-02 10:02:37 -04001223 if (levels != 1 && !context->getExtensions().textureNPOT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001224 {
1225 if (!gl::isPow2(width) || !gl::isPow2(height))
1226 {
Jamie Madill437fa652016-05-03 15:13:24 -04001227 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 }
1230 }
1231
1232 switch (internalformat)
1233 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1235 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1236 if (!context->getExtensions().textureCompressionDXT1)
1237 {
1238 context->handleError(Error(GL_INVALID_ENUM));
1239 return false;
1240 }
1241 break;
1242 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1243 if (!context->getExtensions().textureCompressionDXT3)
1244 {
1245 context->handleError(Error(GL_INVALID_ENUM));
1246 return false;
1247 }
1248 break;
1249 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1250 if (!context->getExtensions().textureCompressionDXT5)
1251 {
1252 context->handleError(Error(GL_INVALID_ENUM));
1253 return false;
1254 }
1255 break;
1256 case GL_ETC1_RGB8_OES:
1257 if (!context->getExtensions().compressedETC1RGB8Texture)
1258 {
1259 context->handleError(Error(GL_INVALID_ENUM));
1260 return false;
1261 }
1262 break;
1263 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001264 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1265 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1266 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1267 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001268 if (!context->getExtensions().lossyETCDecode)
1269 {
1270 context->handleError(
1271 Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1272 return false;
1273 }
1274 break;
1275 case GL_RGBA32F_EXT:
1276 case GL_RGB32F_EXT:
1277 case GL_ALPHA32F_EXT:
1278 case GL_LUMINANCE32F_EXT:
1279 case GL_LUMINANCE_ALPHA32F_EXT:
1280 if (!context->getExtensions().textureFloat)
1281 {
1282 context->handleError(Error(GL_INVALID_ENUM));
1283 return false;
1284 }
1285 break;
1286 case GL_RGBA16F_EXT:
1287 case GL_RGB16F_EXT:
1288 case GL_ALPHA16F_EXT:
1289 case GL_LUMINANCE16F_EXT:
1290 case GL_LUMINANCE_ALPHA16F_EXT:
1291 if (!context->getExtensions().textureHalfFloat)
1292 {
1293 context->handleError(Error(GL_INVALID_ENUM));
1294 return false;
1295 }
1296 break;
1297 case GL_R8_EXT:
1298 case GL_RG8_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001299 if (!context->getExtensions().textureRG)
1300 {
1301 context->handleError(Error(GL_INVALID_ENUM));
1302 return false;
1303 }
1304 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001305 case GL_R16F_EXT:
1306 case GL_RG16F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001307 if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1308 {
1309 context->handleError(Error(GL_INVALID_ENUM));
1310 return false;
1311 }
1312 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001313 case GL_R32F_EXT:
1314 case GL_RG32F_EXT:
Geoff Lang677bb6f2017-04-05 12:40:40 -04001315 if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
He Yunchaoced53ae2016-11-29 15:00:51 +08001316 {
1317 context->handleError(Error(GL_INVALID_ENUM));
1318 return false;
1319 }
1320 break;
1321 case GL_DEPTH_COMPONENT16:
1322 case GL_DEPTH_COMPONENT32_OES:
1323 case GL_DEPTH24_STENCIL8_OES:
1324 if (!context->getExtensions().depthTextures)
1325 {
1326 context->handleError(Error(GL_INVALID_ENUM));
1327 return false;
1328 }
1329 if (target != GL_TEXTURE_2D)
1330 {
1331 context->handleError(Error(GL_INVALID_OPERATION));
1332 return false;
1333 }
1334 // ANGLE_depth_texture only supports 1-level textures
1335 if (levels != 1)
1336 {
1337 context->handleError(Error(GL_INVALID_OPERATION));
1338 return false;
1339 }
1340 break;
1341 default:
1342 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 }
1344
Geoff Lang691e58c2014-12-19 17:03:25 -05001345 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346 if (!texture || texture->id() == 0)
1347 {
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
Geoff Lang69cce582015-09-17 13:20:36 -04001352 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 {
Jamie Madill437fa652016-05-03 15:13:24 -04001354 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001355 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 }
1357
1358 return true;
1359}
1360
He Yunchaoced53ae2016-11-29 15:00:51 +08001361bool ValidateDiscardFramebufferEXT(Context *context,
1362 GLenum target,
1363 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001364 const GLenum *attachments)
1365{
Jamie Madillc29968b2016-01-20 11:17:23 -05001366 if (!context->getExtensions().discardFramebuffer)
1367 {
Jamie Madill437fa652016-05-03 15:13:24 -04001368 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001369 return false;
1370 }
1371
Austin Kinross08332632015-05-05 13:35:47 -07001372 bool defaultFramebuffer = false;
1373
1374 switch (target)
1375 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 case GL_FRAMEBUFFER:
1377 defaultFramebuffer =
1378 (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
1379 break;
1380 default:
1381 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
1382 return false;
Austin Kinross08332632015-05-05 13:35:47 -07001383 }
1384
He Yunchaoced53ae2016-11-29 15:00:51 +08001385 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1386 defaultFramebuffer);
Austin Kinross08332632015-05-05 13:35:47 -07001387}
1388
Austin Kinrossbc781f32015-10-26 09:27:38 -07001389bool ValidateBindVertexArrayOES(Context *context, GLuint array)
1390{
1391 if (!context->getExtensions().vertexArrayObject)
1392 {
Jamie Madill437fa652016-05-03 15:13:24 -04001393 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001394 return false;
1395 }
1396
1397 return ValidateBindVertexArrayBase(context, array);
1398}
1399
1400bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
1401{
1402 if (!context->getExtensions().vertexArrayObject)
1403 {
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001405 return false;
1406 }
1407
Olli Etuaho41997e72016-03-10 13:38:39 +02001408 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001409}
1410
1411bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
1412{
1413 if (!context->getExtensions().vertexArrayObject)
1414 {
Jamie Madill437fa652016-05-03 15:13:24 -04001415 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001416 return false;
1417 }
1418
Olli Etuaho41997e72016-03-10 13:38:39 +02001419 return ValidateGenOrDelete(context, n);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001420}
1421
1422bool ValidateIsVertexArrayOES(Context *context)
1423{
1424 if (!context->getExtensions().vertexArrayObject)
1425 {
Jamie Madill437fa652016-05-03 15:13:24 -04001426 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Austin Kinrossbc781f32015-10-26 09:27:38 -07001427 return false;
1428 }
1429
1430 return true;
1431}
Geoff Langc5629752015-12-07 16:29:04 -05001432
1433bool ValidateProgramBinaryOES(Context *context,
1434 GLuint program,
1435 GLenum binaryFormat,
1436 const void *binary,
1437 GLint length)
1438{
1439 if (!context->getExtensions().getProgramBinary)
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001442 return false;
1443 }
1444
1445 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1446}
1447
1448bool ValidateGetProgramBinaryOES(Context *context,
1449 GLuint program,
1450 GLsizei bufSize,
1451 GLsizei *length,
1452 GLenum *binaryFormat,
1453 void *binary)
1454{
1455 if (!context->getExtensions().getProgramBinary)
1456 {
Jamie Madill437fa652016-05-03 15:13:24 -04001457 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Langc5629752015-12-07 16:29:04 -05001458 return false;
1459 }
1460
1461 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1462}
Geoff Lange102fee2015-12-10 11:23:30 -05001463
Geoff Lang70d0f492015-12-10 17:45:46 -05001464static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1465{
1466 switch (source)
1467 {
1468 case GL_DEBUG_SOURCE_API:
1469 case GL_DEBUG_SOURCE_SHADER_COMPILER:
1470 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1471 case GL_DEBUG_SOURCE_OTHER:
1472 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1473 return !mustBeThirdPartyOrApplication;
1474
1475 case GL_DEBUG_SOURCE_THIRD_PARTY:
1476 case GL_DEBUG_SOURCE_APPLICATION:
1477 return true;
1478
1479 default:
1480 return false;
1481 }
1482}
1483
1484static bool ValidDebugType(GLenum type)
1485{
1486 switch (type)
1487 {
1488 case GL_DEBUG_TYPE_ERROR:
1489 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1490 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1491 case GL_DEBUG_TYPE_PERFORMANCE:
1492 case GL_DEBUG_TYPE_PORTABILITY:
1493 case GL_DEBUG_TYPE_OTHER:
1494 case GL_DEBUG_TYPE_MARKER:
1495 case GL_DEBUG_TYPE_PUSH_GROUP:
1496 case GL_DEBUG_TYPE_POP_GROUP:
1497 return true;
1498
1499 default:
1500 return false;
1501 }
1502}
1503
1504static bool ValidDebugSeverity(GLenum severity)
1505{
1506 switch (severity)
1507 {
1508 case GL_DEBUG_SEVERITY_HIGH:
1509 case GL_DEBUG_SEVERITY_MEDIUM:
1510 case GL_DEBUG_SEVERITY_LOW:
1511 case GL_DEBUG_SEVERITY_NOTIFICATION:
1512 return true;
1513
1514 default:
1515 return false;
1516 }
1517}
1518
Geoff Lange102fee2015-12-10 11:23:30 -05001519bool ValidateDebugMessageControlKHR(Context *context,
1520 GLenum source,
1521 GLenum type,
1522 GLenum severity,
1523 GLsizei count,
1524 const GLuint *ids,
1525 GLboolean enabled)
1526{
1527 if (!context->getExtensions().debug)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001530 return false;
1531 }
1532
Geoff Lang70d0f492015-12-10 17:45:46 -05001533 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
1534 {
Jamie Madill437fa652016-05-03 15:13:24 -04001535 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001536 return false;
1537 }
1538
1539 if (!ValidDebugType(type) && type != GL_DONT_CARE)
1540 {
Jamie Madill437fa652016-05-03 15:13:24 -04001541 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001542 return false;
1543 }
1544
1545 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
1546 {
Jamie Madill437fa652016-05-03 15:13:24 -04001547 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001548 return false;
1549 }
1550
1551 if (count > 0)
1552 {
1553 if (source == GL_DONT_CARE || type == GL_DONT_CARE)
1554 {
Jamie Madill437fa652016-05-03 15:13:24 -04001555 context->handleError(Error(
Geoff Lang70d0f492015-12-10 17:45:46 -05001556 GL_INVALID_OPERATION,
1557 "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
1558 return false;
1559 }
1560
1561 if (severity != GL_DONT_CARE)
1562 {
Jamie Madill437fa652016-05-03 15:13:24 -04001563 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001564 Error(GL_INVALID_OPERATION,
1565 "If count is greater than zero, severity must be GL_DONT_CARE."));
1566 return false;
1567 }
1568 }
1569
Geoff Lange102fee2015-12-10 11:23:30 -05001570 return true;
1571}
1572
1573bool ValidateDebugMessageInsertKHR(Context *context,
1574 GLenum source,
1575 GLenum type,
1576 GLuint id,
1577 GLenum severity,
1578 GLsizei length,
1579 const GLchar *buf)
1580{
1581 if (!context->getExtensions().debug)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001584 return false;
1585 }
1586
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001587 if (!context->getGLState().getDebug().isOutputEnabled())
Geoff Lang70d0f492015-12-10 17:45:46 -05001588 {
1589 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
1590 // not generate an error.
1591 return false;
1592 }
1593
1594 if (!ValidDebugSeverity(severity))
1595 {
Jamie Madill437fa652016-05-03 15:13:24 -04001596 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001597 return false;
1598 }
1599
1600 if (!ValidDebugType(type))
1601 {
Jamie Madill437fa652016-05-03 15:13:24 -04001602 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug type."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001603 return false;
1604 }
1605
1606 if (!ValidDebugSource(source, true))
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001609 return false;
1610 }
1611
1612 size_t messageLength = (length < 0) ? strlen(buf) : length;
1613 if (messageLength > context->getExtensions().maxDebugMessageLength)
1614 {
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001616 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1617 return false;
1618 }
1619
Geoff Lange102fee2015-12-10 11:23:30 -05001620 return true;
1621}
1622
1623bool ValidateDebugMessageCallbackKHR(Context *context,
1624 GLDEBUGPROCKHR callback,
1625 const void *userParam)
1626{
1627 if (!context->getExtensions().debug)
1628 {
Jamie Madill437fa652016-05-03 15:13:24 -04001629 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001630 return false;
1631 }
1632
Geoff Lange102fee2015-12-10 11:23:30 -05001633 return true;
1634}
1635
1636bool ValidateGetDebugMessageLogKHR(Context *context,
1637 GLuint count,
1638 GLsizei bufSize,
1639 GLenum *sources,
1640 GLenum *types,
1641 GLuint *ids,
1642 GLenum *severities,
1643 GLsizei *lengths,
1644 GLchar *messageLog)
1645{
1646 if (!context->getExtensions().debug)
1647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001649 return false;
1650 }
1651
Geoff Lang70d0f492015-12-10 17:45:46 -05001652 if (bufSize < 0 && messageLog != nullptr)
1653 {
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001655 Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
1656 return false;
1657 }
1658
Geoff Lange102fee2015-12-10 11:23:30 -05001659 return true;
1660}
1661
1662bool ValidatePushDebugGroupKHR(Context *context,
1663 GLenum source,
1664 GLuint id,
1665 GLsizei length,
1666 const GLchar *message)
1667{
1668 if (!context->getExtensions().debug)
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001671 return false;
1672 }
1673
Geoff Lang70d0f492015-12-10 17:45:46 -05001674 if (!ValidDebugSource(source, true))
1675 {
Jamie Madill437fa652016-05-03 15:13:24 -04001676 context->handleError(Error(GL_INVALID_ENUM, "Invalid debug source."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001677 return false;
1678 }
1679
1680 size_t messageLength = (length < 0) ? strlen(message) : length;
1681 if (messageLength > context->getExtensions().maxDebugMessageLength)
1682 {
Jamie Madill437fa652016-05-03 15:13:24 -04001683 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001684 Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
1685 return false;
1686 }
1687
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001688 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001689 if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
1690 {
Jamie Madill437fa652016-05-03 15:13:24 -04001691 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001692 Error(GL_STACK_OVERFLOW,
1693 "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
1694 return false;
1695 }
1696
Geoff Lange102fee2015-12-10 11:23:30 -05001697 return true;
1698}
1699
1700bool ValidatePopDebugGroupKHR(Context *context)
1701{
1702 if (!context->getExtensions().debug)
1703 {
Jamie Madill437fa652016-05-03 15:13:24 -04001704 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001705 return false;
1706 }
1707
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001708 size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
Geoff Lang70d0f492015-12-10 17:45:46 -05001709 if (currentStackSize <= 1)
1710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001712 return false;
1713 }
1714
1715 return true;
1716}
1717
1718static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
1719{
1720 switch (identifier)
1721 {
1722 case GL_BUFFER:
1723 if (context->getBuffer(name) == nullptr)
1724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001726 return false;
1727 }
1728 return true;
1729
1730 case GL_SHADER:
1731 if (context->getShader(name) == nullptr)
1732 {
Jamie Madill437fa652016-05-03 15:13:24 -04001733 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001734 return false;
1735 }
1736 return true;
1737
1738 case GL_PROGRAM:
1739 if (context->getProgram(name) == nullptr)
1740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid program."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001742 return false;
1743 }
1744 return true;
1745
1746 case GL_VERTEX_ARRAY:
1747 if (context->getVertexArray(name) == nullptr)
1748 {
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001750 return false;
1751 }
1752 return true;
1753
1754 case GL_QUERY:
1755 if (context->getQuery(name) == nullptr)
1756 {
Jamie Madill437fa652016-05-03 15:13:24 -04001757 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid query."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001758 return false;
1759 }
1760 return true;
1761
1762 case GL_TRANSFORM_FEEDBACK:
1763 if (context->getTransformFeedback(name) == nullptr)
1764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(
Geoff Lang70d0f492015-12-10 17:45:46 -05001766 Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
1767 return false;
1768 }
1769 return true;
1770
1771 case GL_SAMPLER:
1772 if (context->getSampler(name) == nullptr)
1773 {
Jamie Madill437fa652016-05-03 15:13:24 -04001774 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001775 return false;
1776 }
1777 return true;
1778
1779 case GL_TEXTURE:
1780 if (context->getTexture(name) == nullptr)
1781 {
Jamie Madill437fa652016-05-03 15:13:24 -04001782 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001783 return false;
1784 }
1785 return true;
1786
1787 case GL_RENDERBUFFER:
1788 if (context->getRenderbuffer(name) == nullptr)
1789 {
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001791 return false;
1792 }
1793 return true;
1794
1795 case GL_FRAMEBUFFER:
1796 if (context->getFramebuffer(name) == nullptr)
1797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001799 return false;
1800 }
1801 return true;
1802
1803 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001804 context->handleError(Error(GL_INVALID_ENUM, "Invalid identifier."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001805 return false;
1806 }
Geoff Lange102fee2015-12-10 11:23:30 -05001807}
1808
Martin Radev9d901792016-07-15 15:58:58 +03001809static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
1810{
1811 size_t labelLength = 0;
1812
1813 if (length < 0)
1814 {
1815 if (label != nullptr)
1816 {
1817 labelLength = strlen(label);
1818 }
1819 }
1820 else
1821 {
1822 labelLength = static_cast<size_t>(length);
1823 }
1824
1825 if (labelLength > context->getExtensions().maxLabelLength)
1826 {
1827 context->handleError(
1828 Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
1829 return false;
1830 }
1831
1832 return true;
1833}
1834
Geoff Lange102fee2015-12-10 11:23:30 -05001835bool ValidateObjectLabelKHR(Context *context,
1836 GLenum identifier,
1837 GLuint name,
1838 GLsizei length,
1839 const GLchar *label)
1840{
1841 if (!context->getExtensions().debug)
1842 {
Jamie Madill437fa652016-05-03 15:13:24 -04001843 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001844 return false;
1845 }
1846
Geoff Lang70d0f492015-12-10 17:45:46 -05001847 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1848 {
1849 return false;
1850 }
1851
Martin Radev9d901792016-07-15 15:58:58 +03001852 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001853 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001854 return false;
1855 }
1856
Geoff Lange102fee2015-12-10 11:23:30 -05001857 return true;
1858}
1859
1860bool ValidateGetObjectLabelKHR(Context *context,
1861 GLenum identifier,
1862 GLuint name,
1863 GLsizei bufSize,
1864 GLsizei *length,
1865 GLchar *label)
1866{
1867 if (!context->getExtensions().debug)
1868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001870 return false;
1871 }
1872
Geoff Lang70d0f492015-12-10 17:45:46 -05001873 if (bufSize < 0)
1874 {
Jamie Madill437fa652016-05-03 15:13:24 -04001875 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001876 return false;
1877 }
1878
1879 if (!ValidateObjectIdentifierAndName(context, identifier, name))
1880 {
1881 return false;
1882 }
1883
Martin Radev9d901792016-07-15 15:58:58 +03001884 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -05001885}
1886
1887static bool ValidateObjectPtrName(Context *context, const void *ptr)
1888{
1889 if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
1890 {
Jamie Madill437fa652016-05-03 15:13:24 -04001891 context->handleError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001892 return false;
1893 }
1894
Geoff Lange102fee2015-12-10 11:23:30 -05001895 return true;
1896}
1897
1898bool ValidateObjectPtrLabelKHR(Context *context,
1899 const void *ptr,
1900 GLsizei length,
1901 const GLchar *label)
1902{
1903 if (!context->getExtensions().debug)
1904 {
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001906 return false;
1907 }
1908
Geoff Lang70d0f492015-12-10 17:45:46 -05001909 if (!ValidateObjectPtrName(context, ptr))
1910 {
1911 return false;
1912 }
1913
Martin Radev9d901792016-07-15 15:58:58 +03001914 if (!ValidateLabelLength(context, length, label))
Geoff Lang70d0f492015-12-10 17:45:46 -05001915 {
Geoff Lang70d0f492015-12-10 17:45:46 -05001916 return false;
1917 }
1918
Geoff Lange102fee2015-12-10 11:23:30 -05001919 return true;
1920}
1921
1922bool ValidateGetObjectPtrLabelKHR(Context *context,
1923 const void *ptr,
1924 GLsizei bufSize,
1925 GLsizei *length,
1926 GLchar *label)
1927{
1928 if (!context->getExtensions().debug)
1929 {
Jamie Madill437fa652016-05-03 15:13:24 -04001930 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001931 return false;
1932 }
1933
Geoff Lang70d0f492015-12-10 17:45:46 -05001934 if (bufSize < 0)
1935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001937 return false;
1938 }
1939
1940 if (!ValidateObjectPtrName(context, ptr))
1941 {
1942 return false;
1943 }
1944
Martin Radev9d901792016-07-15 15:58:58 +03001945 return true;
Geoff Lange102fee2015-12-10 11:23:30 -05001946}
1947
1948bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
1949{
1950 if (!context->getExtensions().debug)
1951 {
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
Geoff Lange102fee2015-12-10 11:23:30 -05001953 return false;
1954 }
1955
Geoff Lang70d0f492015-12-10 17:45:46 -05001956 // TODO: represent this in Context::getQueryParameterInfo.
1957 switch (pname)
1958 {
1959 case GL_DEBUG_CALLBACK_FUNCTION:
1960 case GL_DEBUG_CALLBACK_USER_PARAM:
1961 break;
1962
1963 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001964 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname."));
Geoff Lang70d0f492015-12-10 17:45:46 -05001965 return false;
1966 }
1967
Geoff Lange102fee2015-12-10 11:23:30 -05001968 return true;
1969}
Jamie Madillc29968b2016-01-20 11:17:23 -05001970
1971bool ValidateBlitFramebufferANGLE(Context *context,
1972 GLint srcX0,
1973 GLint srcY0,
1974 GLint srcX1,
1975 GLint srcY1,
1976 GLint dstX0,
1977 GLint dstY0,
1978 GLint dstX1,
1979 GLint dstY1,
1980 GLbitfield mask,
1981 GLenum filter)
1982{
1983 if (!context->getExtensions().framebufferBlit)
1984 {
Jamie Madill437fa652016-05-03 15:13:24 -04001985 context->handleError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001986 return false;
1987 }
1988
1989 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
1990 {
1991 // TODO(jmadill): Determine if this should be available on other implementations.
Jamie Madill437fa652016-05-03 15:13:24 -04001992 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05001993 GL_INVALID_OPERATION,
1994 "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
1995 return false;
1996 }
1997
1998 if (filter == GL_LINEAR)
1999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002001 return false;
2002 }
2003
Jamie Madill51f40ec2016-06-15 14:06:00 -04002004 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2005 Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madillc29968b2016-01-20 11:17:23 -05002006
2007 if (mask & GL_COLOR_BUFFER_BIT)
2008 {
2009 const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
2010 const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
2011
2012 if (readColorAttachment && drawColorAttachment)
2013 {
2014 if (!(readColorAttachment->type() == GL_TEXTURE &&
2015 readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2016 readColorAttachment->type() != GL_RENDERBUFFER &&
2017 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002020 return false;
2021 }
2022
Geoff Langa15472a2015-08-11 11:48:03 -04002023 for (size_t drawbufferIdx = 0;
2024 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Jamie Madillc29968b2016-01-20 11:17:23 -05002025 {
Geoff Langa15472a2015-08-11 11:48:03 -04002026 const FramebufferAttachment *attachment =
2027 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2028 if (attachment)
Jamie Madillc29968b2016-01-20 11:17:23 -05002029 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002030 if (!(attachment->type() == GL_TEXTURE &&
2031 attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
2032 attachment->type() != GL_RENDERBUFFER &&
2033 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002036 return false;
2037 }
2038
2039 // Return an error if the destination formats do not match
Jamie Madilla3944d42016-07-22 22:13:26 -04002040 if (!Format::SameSized(attachment->getFormat(),
2041 readColorAttachment->getFormat()))
Jamie Madillc29968b2016-01-20 11:17:23 -05002042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002044 return false;
2045 }
2046 }
2047 }
2048
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002049 if (readFramebuffer->getSamples(context) != 0 &&
Jamie Madillc29968b2016-01-20 11:17:23 -05002050 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2051 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002054 return false;
2055 }
2056 }
2057 }
2058
2059 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2060 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2061 for (size_t i = 0; i < 2; i++)
2062 {
2063 if (mask & masks[i])
2064 {
2065 const FramebufferAttachment *readBuffer =
2066 readFramebuffer->getAttachment(attachments[i]);
2067 const FramebufferAttachment *drawBuffer =
2068 drawFramebuffer->getAttachment(attachments[i]);
2069
2070 if (readBuffer && drawBuffer)
2071 {
2072 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2073 dstX0, dstY0, dstX1, dstY1))
2074 {
2075 // only whole-buffer copies are permitted
Yuly Novikov72e27b02017-02-03 15:43:24 -05002076 context->handleError(Error(GL_INVALID_OPERATION,
2077 "Only whole-buffer depth and stencil blits are "
2078 "supported by this extension."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002079 return false;
2080 }
2081
2082 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
2083 {
Jamie Madill437fa652016-05-03 15:13:24 -04002084 context->handleError(Error(GL_INVALID_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002085 return false;
2086 }
2087 }
2088 }
2089 }
2090
2091 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2092 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002093}
Jamie Madillc29968b2016-01-20 11:17:23 -05002094
2095bool ValidateClear(ValidationContext *context, GLbitfield mask)
2096{
Jamie Madill51f40ec2016-06-15 14:06:00 -04002097 auto fbo = context->getGLState().getDrawFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002098 if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madillc29968b2016-01-20 11:17:23 -05002099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madillc29968b2016-01-20 11:17:23 -05002101 return false;
2102 }
2103
2104 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2105 {
Jamie Madill437fa652016-05-03 15:13:24 -04002106 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madillc29968b2016-01-20 11:17:23 -05002107 return false;
2108 }
2109
Geoff Lang76e65652017-03-27 14:58:02 -04002110 if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2111 {
2112 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2113 GL_SIGNED_NORMALIZED};
2114
2115 for (GLuint drawBufferIdx = 0; drawBufferIdx < context->getCaps().maxDrawBuffers;
2116 drawBufferIdx++)
2117 {
2118 if (!ValidateWebGLFramebufferAttachmentClearType(
2119 context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2120 {
2121 return false;
2122 }
2123 }
2124 }
2125
Jamie Madillc29968b2016-01-20 11:17:23 -05002126 return true;
2127}
2128
2129bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
2130{
2131 if (!context->getExtensions().drawBuffers)
2132 {
Jamie Madill437fa652016-05-03 15:13:24 -04002133 context->handleError(Error(GL_INVALID_OPERATION, "Extension not supported."));
Jamie Madillc29968b2016-01-20 11:17:23 -05002134 return false;
2135 }
2136
2137 return ValidateDrawBuffersBase(context, n, bufs);
2138}
2139
Jamie Madill73a84962016-02-12 09:27:23 -05002140bool ValidateTexImage2D(Context *context,
2141 GLenum target,
2142 GLint level,
2143 GLint internalformat,
2144 GLsizei width,
2145 GLsizei height,
2146 GLint border,
2147 GLenum format,
2148 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002149 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002150{
Martin Radev1be913c2016-07-11 17:59:16 +03002151 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002152 {
2153 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
Geoff Langff5b2d52016-09-07 11:32:23 -04002154 0, 0, width, height, border, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002155 }
2156
Martin Radev1be913c2016-07-11 17:59:16 +03002157 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002158 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002159 0, 0, width, height, 1, border, format, type, -1,
2160 pixels);
2161}
2162
2163bool ValidateTexImage2DRobust(Context *context,
2164 GLenum target,
2165 GLint level,
2166 GLint internalformat,
2167 GLsizei width,
2168 GLsizei height,
2169 GLint border,
2170 GLenum format,
2171 GLenum type,
2172 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002173 const void *pixels)
Geoff Langff5b2d52016-09-07 11:32:23 -04002174{
2175 if (!ValidateRobustEntryPoint(context, bufSize))
2176 {
2177 return false;
2178 }
2179
2180 if (context->getClientMajorVersion() < 3)
2181 {
2182 return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2183 0, 0, width, height, border, format, type, bufSize,
2184 pixels);
2185 }
2186
2187 ASSERT(context->getClientMajorVersion() >= 3);
2188 return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2189 0, 0, width, height, 1, border, format, type, bufSize,
2190 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002191}
2192
2193bool ValidateTexSubImage2D(Context *context,
2194 GLenum target,
2195 GLint level,
2196 GLint xoffset,
2197 GLint yoffset,
2198 GLsizei width,
2199 GLsizei height,
2200 GLenum format,
2201 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002202 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002203{
2204
Martin Radev1be913c2016-07-11 17:59:16 +03002205 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002206 {
2207 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002208 yoffset, width, height, 0, format, type, -1, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002209 }
2210
Martin Radev1be913c2016-07-11 17:59:16 +03002211 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002212 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
Geoff Langff5b2d52016-09-07 11:32:23 -04002213 yoffset, 0, width, height, 1, 0, format, type, -1,
2214 pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002215}
2216
Geoff Langc52f6f12016-10-14 10:18:00 -04002217bool ValidateTexSubImage2DRobustANGLE(Context *context,
2218 GLenum target,
2219 GLint level,
2220 GLint xoffset,
2221 GLint yoffset,
2222 GLsizei width,
2223 GLsizei height,
2224 GLenum format,
2225 GLenum type,
2226 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002227 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002228{
2229 if (!ValidateRobustEntryPoint(context, bufSize))
2230 {
2231 return false;
2232 }
2233
2234 if (context->getClientMajorVersion() < 3)
2235 {
2236 return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2237 yoffset, width, height, 0, format, type, bufSize,
2238 pixels);
2239 }
2240
2241 ASSERT(context->getClientMajorVersion() >= 3);
2242 return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2243 yoffset, 0, width, height, 1, 0, format, type, bufSize,
2244 pixels);
2245}
2246
Jamie Madill73a84962016-02-12 09:27:23 -05002247bool ValidateCompressedTexImage2D(Context *context,
2248 GLenum target,
2249 GLint level,
2250 GLenum internalformat,
2251 GLsizei width,
2252 GLsizei height,
2253 GLint border,
2254 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002255 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002256{
Martin Radev1be913c2016-07-11 17:59:16 +03002257 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002258 {
2259 if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002260 0, width, height, border, GL_NONE, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002261 {
2262 return false;
2263 }
2264 }
2265 else
2266 {
Martin Radev1be913c2016-07-11 17:59:16 +03002267 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002268 if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
Geoff Langff5b2d52016-09-07 11:32:23 -04002269 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002270 data))
2271 {
2272 return false;
2273 }
2274 }
2275
Geoff Langca271392017-04-05 12:30:00 -04002276 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill513558d2016-06-02 13:04:11 -04002277 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002278 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002279 if (blockSizeOrErr.isError())
2280 {
2281 context->handleError(blockSizeOrErr.getError());
2282 return false;
2283 }
2284
2285 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002286 {
Jamie Madill437fa652016-05-03 15:13:24 -04002287 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002288 return false;
2289 }
2290
2291 return true;
2292}
2293
Corentin Wallezb2931602017-04-11 15:58:57 -04002294bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
2295 GLenum target,
2296 GLint level,
2297 GLenum internalformat,
2298 GLsizei width,
2299 GLsizei height,
2300 GLint border,
2301 GLsizei imageSize,
2302 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002303 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002304{
2305 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2306 {
2307 return false;
2308 }
2309
2310 return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2311 border, imageSize, data);
2312}
2313bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
2314 GLenum target,
2315 GLint level,
2316 GLint xoffset,
2317 GLint yoffset,
2318 GLsizei width,
2319 GLsizei height,
2320 GLenum format,
2321 GLsizei imageSize,
2322 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002323 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002324{
2325 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2326 {
2327 return false;
2328 }
2329
2330 return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2331 format, imageSize, data);
2332}
2333
Jamie Madill73a84962016-02-12 09:27:23 -05002334bool ValidateCompressedTexSubImage2D(Context *context,
2335 GLenum target,
2336 GLint level,
2337 GLint xoffset,
2338 GLint yoffset,
2339 GLsizei width,
2340 GLsizei height,
2341 GLenum format,
2342 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002343 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002344{
Martin Radev1be913c2016-07-11 17:59:16 +03002345 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002346 {
2347 if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002348 yoffset, width, height, 0, format, GL_NONE, -1, data))
Jamie Madill73a84962016-02-12 09:27:23 -05002349 {
2350 return false;
2351 }
2352 }
2353 else
2354 {
Martin Radev1be913c2016-07-11 17:59:16 +03002355 ASSERT(context->getClientMajorVersion() >= 3);
Jamie Madill73a84962016-02-12 09:27:23 -05002356 if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
Geoff Lang966c9402017-04-18 12:38:27 -04002357 yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002358 data))
2359 {
2360 return false;
2361 }
2362 }
2363
Geoff Langca271392017-04-05 12:30:00 -04002364 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Jamie Madill513558d2016-06-02 13:04:11 -04002365 auto blockSizeOrErr =
Jamie Madill4b4cdff2016-06-06 13:53:38 -07002366 formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
Jamie Madille2e406c2016-06-02 13:04:10 -04002367 if (blockSizeOrErr.isError())
2368 {
2369 context->handleError(blockSizeOrErr.getError());
2370 return false;
2371 }
2372
2373 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
Jamie Madill73a84962016-02-12 09:27:23 -05002374 {
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(Error(GL_INVALID_VALUE));
Jamie Madill73a84962016-02-12 09:27:23 -05002376 return false;
2377 }
2378
2379 return true;
2380}
2381
Olli Etuaho4f667482016-03-30 15:56:35 +03002382bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
2383{
Geoff Lang496c02d2016-10-20 11:38:11 -07002384 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
Olli Etuaho4f667482016-03-30 15:56:35 +03002385}
2386
2387bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
2388{
2389 if (!context->getExtensions().mapBuffer)
2390 {
Jamie Madill437fa652016-05-03 15:13:24 -04002391 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002392 return false;
2393 }
2394
2395 if (!ValidBufferTarget(context, target))
2396 {
Jamie Madill437fa652016-05-03 15:13:24 -04002397 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002398 return false;
2399 }
2400
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002401 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002402
2403 if (buffer == nullptr)
2404 {
Jamie Madill437fa652016-05-03 15:13:24 -04002405 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002406 return false;
2407 }
2408
2409 if (access != GL_WRITE_ONLY_OES)
2410 {
Jamie Madill437fa652016-05-03 15:13:24 -04002411 context->handleError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002412 return false;
2413 }
2414
2415 if (buffer->isMapped())
2416 {
Jamie Madill437fa652016-05-03 15:13:24 -04002417 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002418 return false;
2419 }
2420
2421 return true;
2422}
2423
2424bool ValidateUnmapBufferOES(Context *context, GLenum target)
2425{
2426 if (!context->getExtensions().mapBuffer)
2427 {
Jamie Madill437fa652016-05-03 15:13:24 -04002428 context->handleError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
Olli Etuaho4f667482016-03-30 15:56:35 +03002429 return false;
2430 }
2431
2432 return ValidateUnmapBufferBase(context, target);
2433}
2434
2435bool ValidateMapBufferRangeEXT(Context *context,
2436 GLenum target,
2437 GLintptr offset,
2438 GLsizeiptr length,
2439 GLbitfield access)
2440{
2441 if (!context->getExtensions().mapBufferRange)
2442 {
Jamie Madill437fa652016-05-03 15:13:24 -04002443 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002444 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2445 return false;
2446 }
2447
2448 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2449}
2450
2451bool ValidateFlushMappedBufferRangeEXT(Context *context,
2452 GLenum target,
2453 GLintptr offset,
2454 GLsizeiptr length)
2455{
2456 if (!context->getExtensions().mapBufferRange)
2457 {
Jamie Madill437fa652016-05-03 15:13:24 -04002458 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002459 Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
2460 return false;
2461 }
2462
2463 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2464}
2465
Ian Ewell54f87462016-03-10 13:47:21 -05002466bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
2467{
2468 Texture *textureObject = context->getTexture(texture);
2469 if (textureObject && textureObject->getTarget() != target && texture != 0)
2470 {
Jamie Madill437fa652016-05-03 15:13:24 -04002471 context->handleError(Error(GL_INVALID_OPERATION, "Invalid texture"));
Ian Ewell54f87462016-03-10 13:47:21 -05002472 return false;
2473 }
2474
Geoff Langf41a7152016-09-19 15:11:17 -04002475 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
2476 !context->isTextureGenerated(texture))
2477 {
2478 context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
2479 return false;
2480 }
2481
Ian Ewell54f87462016-03-10 13:47:21 -05002482 switch (target)
2483 {
2484 case GL_TEXTURE_2D:
2485 case GL_TEXTURE_CUBE_MAP:
2486 break;
2487
2488 case GL_TEXTURE_3D:
2489 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03002490 if (context->getClientMajorVersion() < 3)
Ian Ewell54f87462016-03-10 13:47:21 -05002491 {
Jamie Madill437fa652016-05-03 15:13:24 -04002492 context->handleError(Error(GL_INVALID_ENUM, "GLES 3.0 disabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002493 return false;
2494 }
2495 break;
Geoff Lang3b573612016-10-31 14:08:10 -04002496
2497 case GL_TEXTURE_2D_MULTISAMPLE:
2498 if (context->getClientVersion() < Version(3, 1))
2499 {
2500 context->handleError(Error(GL_INVALID_ENUM, "Context does not support GLES3.1"));
2501 return false;
2502 }
Geoff Lang3b573612016-10-31 14:08:10 -04002503 break;
2504
Ian Ewell54f87462016-03-10 13:47:21 -05002505 case GL_TEXTURE_EXTERNAL_OES:
Geoff Langb66a9092016-05-16 15:59:14 -04002506 if (!context->getExtensions().eglImageExternal &&
2507 !context->getExtensions().eglStreamConsumerExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002508 {
Jamie Madill437fa652016-05-03 15:13:24 -04002509 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05002510 Error(GL_INVALID_ENUM, "External texture extension not enabled"));
2511 return false;
2512 }
2513 break;
2514 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002515 context->handleError(Error(GL_INVALID_ENUM, "Invalid target"));
Ian Ewell54f87462016-03-10 13:47:21 -05002516 return false;
2517 }
2518
2519 return true;
2520}
2521
Geoff Langd8605522016-04-13 10:19:12 -04002522bool ValidateBindUniformLocationCHROMIUM(Context *context,
2523 GLuint program,
2524 GLint location,
2525 const GLchar *name)
2526{
2527 if (!context->getExtensions().bindUniformLocation)
2528 {
Jamie Madill437fa652016-05-03 15:13:24 -04002529 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002530 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_bind_uniform_location is not available."));
2531 return false;
2532 }
2533
2534 Program *programObject = GetValidProgram(context, program);
2535 if (!programObject)
2536 {
2537 return false;
2538 }
2539
2540 if (location < 0)
2541 {
Jamie Madill437fa652016-05-03 15:13:24 -04002542 context->handleError(Error(GL_INVALID_VALUE, "Location cannot be less than 0."));
Geoff Langd8605522016-04-13 10:19:12 -04002543 return false;
2544 }
2545
2546 const Caps &caps = context->getCaps();
2547 if (static_cast<size_t>(location) >=
2548 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
2549 {
Jamie Madill437fa652016-05-03 15:13:24 -04002550 context->handleError(Error(GL_INVALID_VALUE,
Geoff Langd8605522016-04-13 10:19:12 -04002551 "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + "
2552 "MAX_FRAGMENT_UNIFORM_VECTORS) * 4"));
2553 return false;
2554 }
2555
2556 if (strncmp(name, "gl_", 3) == 0)
2557 {
Jamie Madill437fa652016-05-03 15:13:24 -04002558 context->handleError(
Geoff Langd8605522016-04-13 10:19:12 -04002559 Error(GL_INVALID_OPERATION, "Name cannot start with the reserved \"gl_\" prefix."));
2560 return false;
2561 }
2562
2563 return true;
2564}
2565
Jamie Madille2e406c2016-06-02 13:04:10 -04002566bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
Sami Väisänena797e062016-05-12 15:23:40 +03002567{
2568 if (!context->getExtensions().framebufferMixedSamples)
2569 {
2570 context->handleError(
2571 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_framebuffer_mixed_samples is not available."));
2572 return false;
2573 }
2574 switch (components)
2575 {
2576 case GL_RGB:
2577 case GL_RGBA:
2578 case GL_ALPHA:
2579 case GL_NONE:
2580 break;
2581 default:
2582 context->handleError(
Jamie Madille2e406c2016-06-02 13:04:10 -04002583 Error(GL_INVALID_ENUM,
2584 "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE."));
Sami Väisänena797e062016-05-12 15:23:40 +03002585 return false;
2586 }
2587
2588 return true;
2589}
2590
Sami Väisänene45e53b2016-05-25 10:36:04 +03002591// CHROMIUM_path_rendering
2592
2593bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
2594{
2595 if (!context->getExtensions().pathRendering)
2596 {
2597 context->handleError(
2598 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2599 return false;
2600 }
2601 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2602 {
2603 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2604 return false;
2605 }
2606 if (matrix == nullptr)
2607 {
2608 context->handleError(Error(GL_INVALID_OPERATION, "Invalid matrix."));
2609 return false;
2610 }
2611 return true;
2612}
2613
2614bool ValidateMatrixMode(Context *context, GLenum matrixMode)
2615{
2616 if (!context->getExtensions().pathRendering)
2617 {
2618 context->handleError(
2619 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2620 return false;
2621 }
2622 if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
2623 {
2624 context->handleError(Error(GL_INVALID_ENUM, "Invalid matrix mode."));
2625 return false;
2626 }
2627 return true;
2628}
2629
2630bool ValidateGenPaths(Context *context, GLsizei range)
2631{
2632 if (!context->getExtensions().pathRendering)
2633 {
2634 context->handleError(
2635 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2636 return false;
2637 }
2638
2639 // range = 0 is undefined in NV_path_rendering.
2640 // we add stricter semantic check here and require a non zero positive range.
2641 if (range <= 0)
2642 {
2643 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2644 return false;
2645 }
2646
2647 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
2648 {
2649 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2650 return false;
2651 }
2652
2653 return true;
2654}
2655
2656bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
2657{
2658 if (!context->getExtensions().pathRendering)
2659 {
2660 context->handleError(
2661 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2662 return false;
2663 }
2664
2665 // range = 0 is undefined in NV_path_rendering.
2666 // we add stricter semantic check here and require a non zero positive range.
2667 if (range <= 0)
2668 {
2669 context->handleError(Error(GL_INVALID_VALUE, "Invalid range."));
2670 return false;
2671 }
2672
2673 angle::CheckedNumeric<std::uint32_t> checkedRange(path);
2674 checkedRange += range;
2675
2676 if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
2677 {
2678 context->handleError(Error(GL_INVALID_OPERATION, "Range overflow."));
2679 return false;
2680 }
2681 return true;
2682}
2683
2684bool ValidatePathCommands(Context *context,
2685 GLuint path,
2686 GLsizei numCommands,
2687 const GLubyte *commands,
2688 GLsizei numCoords,
2689 GLenum coordType,
2690 const void *coords)
2691{
2692 if (!context->getExtensions().pathRendering)
2693 {
2694 context->handleError(
2695 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2696 return false;
2697 }
2698 if (!context->hasPath(path))
2699 {
2700 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2701 return false;
2702 }
2703
2704 if (numCommands < 0)
2705 {
2706 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of commands."));
2707 return false;
2708 }
2709 else if (numCommands > 0)
2710 {
2711 if (!commands)
2712 {
2713 context->handleError(Error(GL_INVALID_VALUE, "No commands array given."));
2714 return false;
2715 }
2716 }
2717
2718 if (numCoords < 0)
2719 {
2720 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2721 return false;
2722 }
2723 else if (numCoords > 0)
2724 {
2725 if (!coords)
2726 {
2727 context->handleError(Error(GL_INVALID_VALUE, "No coordinate array given."));
2728 return false;
2729 }
2730 }
2731
2732 std::uint32_t coordTypeSize = 0;
2733 switch (coordType)
2734 {
2735 case GL_BYTE:
2736 coordTypeSize = sizeof(GLbyte);
2737 break;
2738
2739 case GL_UNSIGNED_BYTE:
2740 coordTypeSize = sizeof(GLubyte);
2741 break;
2742
2743 case GL_SHORT:
2744 coordTypeSize = sizeof(GLshort);
2745 break;
2746
2747 case GL_UNSIGNED_SHORT:
2748 coordTypeSize = sizeof(GLushort);
2749 break;
2750
2751 case GL_FLOAT:
2752 coordTypeSize = sizeof(GLfloat);
2753 break;
2754
2755 default:
2756 context->handleError(Error(GL_INVALID_ENUM, "Invalid coordinate type."));
2757 return false;
2758 }
2759
2760 angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
2761 checkedSize += (coordTypeSize * numCoords);
2762 if (!checkedSize.IsValid())
2763 {
2764 context->handleError(Error(GL_INVALID_OPERATION, "Coord size overflow."));
2765 return false;
2766 }
2767
2768 // early return skips command data validation when it doesn't exist.
2769 if (!commands)
2770 return true;
2771
2772 GLsizei expectedNumCoords = 0;
2773 for (GLsizei i = 0; i < numCommands; ++i)
2774 {
2775 switch (commands[i])
2776 {
2777 case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
2778 break;
2779 case GL_MOVE_TO_CHROMIUM:
2780 case GL_LINE_TO_CHROMIUM:
2781 expectedNumCoords += 2;
2782 break;
2783 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
2784 expectedNumCoords += 4;
2785 break;
2786 case GL_CUBIC_CURVE_TO_CHROMIUM:
2787 expectedNumCoords += 6;
2788 break;
2789 case GL_CONIC_CURVE_TO_CHROMIUM:
2790 expectedNumCoords += 5;
2791 break;
2792 default:
2793 context->handleError(Error(GL_INVALID_ENUM, "Invalid command."));
2794 return false;
2795 }
2796 }
2797 if (expectedNumCoords != numCoords)
2798 {
2799 context->handleError(Error(GL_INVALID_VALUE, "Invalid number of coordinates."));
2800 return false;
2801 }
2802
2803 return true;
2804}
2805
2806bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
2807{
2808 if (!context->getExtensions().pathRendering)
2809 {
2810 context->handleError(
2811 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2812 return false;
2813 }
2814 if (!context->hasPath(path))
2815 {
2816 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2817 return false;
2818 }
2819
2820 switch (pname)
2821 {
2822 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2823 if (value < 0.0f)
2824 {
2825 context->handleError(Error(GL_INVALID_VALUE, "Invalid stroke width."));
2826 return false;
2827 }
2828 break;
2829 case GL_PATH_END_CAPS_CHROMIUM:
2830 switch (static_cast<GLenum>(value))
2831 {
2832 case GL_FLAT_CHROMIUM:
2833 case GL_SQUARE_CHROMIUM:
2834 case GL_ROUND_CHROMIUM:
2835 break;
2836 default:
2837 context->handleError(Error(GL_INVALID_ENUM, "Invalid end caps."));
2838 return false;
2839 }
2840 break;
2841 case GL_PATH_JOIN_STYLE_CHROMIUM:
2842 switch (static_cast<GLenum>(value))
2843 {
2844 case GL_MITER_REVERT_CHROMIUM:
2845 case GL_BEVEL_CHROMIUM:
2846 case GL_ROUND_CHROMIUM:
2847 break;
2848 default:
2849 context->handleError(Error(GL_INVALID_ENUM, "Invalid join style."));
2850 return false;
2851 }
2852 case GL_PATH_MITER_LIMIT_CHROMIUM:
2853 if (value < 0.0f)
2854 {
2855 context->handleError(Error(GL_INVALID_VALUE, "Invalid miter limit."));
2856 return false;
2857 }
2858 break;
2859
2860 case GL_PATH_STROKE_BOUND_CHROMIUM:
2861 // no errors, only clamping.
2862 break;
2863
2864 default:
2865 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2866 return false;
2867 }
2868 return true;
2869}
2870
2871bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
2872{
2873 if (!context->getExtensions().pathRendering)
2874 {
2875 context->handleError(
2876 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2877 return false;
2878 }
2879
2880 if (!context->hasPath(path))
2881 {
2882 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2883 return false;
2884 }
2885 if (!value)
2886 {
2887 context->handleError(Error(GL_INVALID_VALUE, "No value array."));
2888 return false;
2889 }
2890
2891 switch (pname)
2892 {
2893 case GL_PATH_STROKE_WIDTH_CHROMIUM:
2894 case GL_PATH_END_CAPS_CHROMIUM:
2895 case GL_PATH_JOIN_STYLE_CHROMIUM:
2896 case GL_PATH_MITER_LIMIT_CHROMIUM:
2897 case GL_PATH_STROKE_BOUND_CHROMIUM:
2898 break;
2899
2900 default:
2901 context->handleError(Error(GL_INVALID_ENUM, "Invalid path parameter."));
2902 return false;
2903 }
2904
2905 return true;
2906}
2907
2908bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
2909{
2910 if (!context->getExtensions().pathRendering)
2911 {
2912 context->handleError(
2913 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2914 return false;
2915 }
2916
2917 switch (func)
2918 {
2919 case GL_NEVER:
2920 case GL_ALWAYS:
2921 case GL_LESS:
2922 case GL_LEQUAL:
2923 case GL_EQUAL:
2924 case GL_GEQUAL:
2925 case GL_GREATER:
2926 case GL_NOTEQUAL:
2927 break;
2928 default:
2929 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
2930 return false;
2931 }
2932
2933 return true;
2934}
2935
2936// Note that the spec specifies that for the path drawing commands
2937// if the path object is not an existing path object the command
2938// does nothing and no error is generated.
2939// However if the path object exists but has not been specified any
2940// commands then an error is generated.
2941
2942bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
2943{
2944 if (!context->getExtensions().pathRendering)
2945 {
2946 context->handleError(
2947 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2948 return false;
2949 }
2950 if (context->hasPath(path) && !context->hasPathData(path))
2951 {
2952 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
2953 return false;
2954 }
2955
2956 switch (fillMode)
2957 {
2958 case GL_COUNT_UP_CHROMIUM:
2959 case GL_COUNT_DOWN_CHROMIUM:
2960 break;
2961 default:
2962 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
2963 return false;
2964 }
2965
2966 if (!isPow2(mask + 1))
2967 {
2968 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
2969 return false;
2970 }
2971
2972 return true;
2973}
2974
2975bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
2976{
2977 if (!context->getExtensions().pathRendering)
2978 {
2979 context->handleError(
2980 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2981 return false;
2982 }
2983 if (context->hasPath(path) && !context->hasPathData(path))
2984 {
2985 context->handleError(Error(GL_INVALID_OPERATION, "No such path or path has no data."));
2986 return false;
2987 }
2988
2989 return true;
2990}
2991
2992bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
2993{
2994 if (!context->getExtensions().pathRendering)
2995 {
2996 context->handleError(
2997 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
2998 return false;
2999 }
3000 if (context->hasPath(path) && !context->hasPathData(path))
3001 {
3002 context->handleError(Error(GL_INVALID_OPERATION, "No such path object."));
3003 return false;
3004 }
3005
3006 switch (coverMode)
3007 {
3008 case GL_CONVEX_HULL_CHROMIUM:
3009 case GL_BOUNDING_BOX_CHROMIUM:
3010 break;
3011 default:
3012 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3013 return false;
3014 }
3015 return true;
3016}
3017
3018bool ValidateStencilThenCoverFillPath(Context *context,
3019 GLuint path,
3020 GLenum fillMode,
3021 GLuint mask,
3022 GLenum coverMode)
3023{
3024 return ValidateStencilFillPath(context, path, fillMode, mask) &&
3025 ValidateCoverPath(context, path, coverMode);
3026}
3027
3028bool ValidateStencilThenCoverStrokePath(Context *context,
3029 GLuint path,
3030 GLint reference,
3031 GLuint mask,
3032 GLenum coverMode)
3033{
3034 return ValidateStencilStrokePath(context, path, reference, mask) &&
3035 ValidateCoverPath(context, path, coverMode);
3036}
3037
3038bool ValidateIsPath(Context *context)
3039{
3040 if (!context->getExtensions().pathRendering)
3041 {
3042 context->handleError(
3043 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3044 return false;
3045 }
3046 return true;
3047}
3048
Sami Väisänend59ca052016-06-21 16:10:00 +03003049bool ValidateCoverFillPathInstanced(Context *context,
3050 GLsizei numPaths,
3051 GLenum pathNameType,
3052 const void *paths,
3053 GLuint pathBase,
3054 GLenum coverMode,
3055 GLenum transformType,
3056 const GLfloat *transformValues)
3057{
3058 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3059 transformType, transformValues))
3060 return false;
3061
3062 switch (coverMode)
3063 {
3064 case GL_CONVEX_HULL_CHROMIUM:
3065 case GL_BOUNDING_BOX_CHROMIUM:
3066 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3067 break;
3068 default:
3069 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3070 return false;
3071 }
3072
3073 return true;
3074}
3075
3076bool ValidateCoverStrokePathInstanced(Context *context,
3077 GLsizei numPaths,
3078 GLenum pathNameType,
3079 const void *paths,
3080 GLuint pathBase,
3081 GLenum coverMode,
3082 GLenum transformType,
3083 const GLfloat *transformValues)
3084{
3085 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3086 transformType, transformValues))
3087 return false;
3088
3089 switch (coverMode)
3090 {
3091 case GL_CONVEX_HULL_CHROMIUM:
3092 case GL_BOUNDING_BOX_CHROMIUM:
3093 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3094 break;
3095 default:
3096 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3097 return false;
3098 }
3099
3100 return true;
3101}
3102
3103bool ValidateStencilFillPathInstanced(Context *context,
3104 GLsizei numPaths,
3105 GLenum pathNameType,
3106 const void *paths,
3107 GLuint pathBase,
3108 GLenum fillMode,
3109 GLuint mask,
3110 GLenum transformType,
3111 const GLfloat *transformValues)
3112{
3113
3114 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3115 transformType, transformValues))
3116 return false;
3117
3118 switch (fillMode)
3119 {
3120 case GL_COUNT_UP_CHROMIUM:
3121 case GL_COUNT_DOWN_CHROMIUM:
3122 break;
3123 default:
3124 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3125 return false;
3126 }
3127 if (!isPow2(mask + 1))
3128 {
3129 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3130 return false;
3131 }
3132 return true;
3133}
3134
3135bool ValidateStencilStrokePathInstanced(Context *context,
3136 GLsizei numPaths,
3137 GLenum pathNameType,
3138 const void *paths,
3139 GLuint pathBase,
3140 GLint reference,
3141 GLuint mask,
3142 GLenum transformType,
3143 const GLfloat *transformValues)
3144{
3145 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3146 transformType, transformValues))
3147 return false;
3148
3149 // no more validation here.
3150
3151 return true;
3152}
3153
3154bool ValidateStencilThenCoverFillPathInstanced(Context *context,
3155 GLsizei numPaths,
3156 GLenum pathNameType,
3157 const void *paths,
3158 GLuint pathBase,
3159 GLenum fillMode,
3160 GLuint mask,
3161 GLenum coverMode,
3162 GLenum transformType,
3163 const GLfloat *transformValues)
3164{
3165 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3166 transformType, transformValues))
3167 return false;
3168
3169 switch (coverMode)
3170 {
3171 case GL_CONVEX_HULL_CHROMIUM:
3172 case GL_BOUNDING_BOX_CHROMIUM:
3173 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3174 break;
3175 default:
3176 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3177 return false;
3178 }
3179
3180 switch (fillMode)
3181 {
3182 case GL_COUNT_UP_CHROMIUM:
3183 case GL_COUNT_DOWN_CHROMIUM:
3184 break;
3185 default:
3186 context->handleError(Error(GL_INVALID_ENUM, "Invalid fill mode."));
3187 return false;
3188 }
3189 if (!isPow2(mask + 1))
3190 {
3191 context->handleError(Error(GL_INVALID_VALUE, "Invalid stencil bit mask."));
3192 return false;
3193 }
3194
3195 return true;
3196}
3197
3198bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
3199 GLsizei numPaths,
3200 GLenum pathNameType,
3201 const void *paths,
3202 GLuint pathBase,
3203 GLint reference,
3204 GLuint mask,
3205 GLenum coverMode,
3206 GLenum transformType,
3207 const GLfloat *transformValues)
3208{
3209 if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
3210 transformType, transformValues))
3211 return false;
3212
3213 switch (coverMode)
3214 {
3215 case GL_CONVEX_HULL_CHROMIUM:
3216 case GL_BOUNDING_BOX_CHROMIUM:
3217 case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
3218 break;
3219 default:
3220 context->handleError(Error(GL_INVALID_ENUM, "Invalid cover mode."));
3221 return false;
3222 }
3223
3224 return true;
3225}
3226
Sami Väisänen46eaa942016-06-29 10:26:37 +03003227bool ValidateBindFragmentInputLocation(Context *context,
3228 GLuint program,
3229 GLint location,
3230 const GLchar *name)
3231{
3232 if (!context->getExtensions().pathRendering)
3233 {
3234 context->handleError(
3235 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3236 return false;
3237 }
3238
3239 const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
3240 if (location >= MaxLocation)
3241 {
3242 context->handleError(Error(GL_INVALID_VALUE, "Location exceeds max varying."));
3243 return false;
3244 }
3245
3246 const auto *programObject = context->getProgram(program);
3247 if (!programObject)
3248 {
3249 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3250 return false;
3251 }
3252
3253 if (!name)
3254 {
3255 context->handleError(Error(GL_INVALID_VALUE, "No name given."));
3256 return false;
3257 }
3258
3259 if (angle::BeginsWith(name, "gl_"))
3260 {
3261 context->handleError(Error(GL_INVALID_OPERATION, "Cannot bind a built-in variable."));
3262 return false;
3263 }
3264
3265 return true;
3266}
3267
3268bool ValidateProgramPathFragmentInputGen(Context *context,
3269 GLuint program,
3270 GLint location,
3271 GLenum genMode,
3272 GLint components,
3273 const GLfloat *coeffs)
3274{
3275 if (!context->getExtensions().pathRendering)
3276 {
3277 context->handleError(
3278 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_path_rendering is not available."));
3279 return false;
3280 }
3281
3282 const auto *programObject = context->getProgram(program);
3283 if (!programObject || programObject->isFlaggedForDeletion())
3284 {
3285 context->handleError(Error(GL_INVALID_OPERATION, "No such program."));
3286 return false;
3287 }
3288
3289 if (!programObject->isLinked())
3290 {
3291 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
3292 return false;
3293 }
3294
3295 switch (genMode)
3296 {
3297 case GL_NONE:
3298 if (components != 0)
3299 {
3300 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3301 return false;
3302 }
3303 break;
3304
3305 case GL_OBJECT_LINEAR_CHROMIUM:
3306 case GL_EYE_LINEAR_CHROMIUM:
3307 case GL_CONSTANT_CHROMIUM:
3308 if (components < 1 || components > 4)
3309 {
3310 context->handleError(Error(GL_INVALID_VALUE, "Invalid components."));
3311 return false;
3312 }
3313 if (!coeffs)
3314 {
3315 context->handleError(Error(GL_INVALID_VALUE, "No coefficients array given."));
3316 return false;
3317 }
3318 break;
3319
3320 default:
3321 context->handleError(Error(GL_INVALID_ENUM, "Invalid gen mode."));
3322 return false;
3323 }
3324
3325 // If the location is -1 then the command is silently ignored
3326 // and no further validation is needed.
3327 if (location == -1)
3328 return true;
3329
3330 const auto &binding = programObject->getFragmentInputBindingInfo(location);
3331
3332 if (!binding.valid)
3333 {
3334 context->handleError(Error(GL_INVALID_OPERATION, "No such binding."));
3335 return false;
3336 }
3337
3338 if (binding.type != GL_NONE)
3339 {
3340 GLint expectedComponents = 0;
3341 switch (binding.type)
3342 {
3343 case GL_FLOAT:
3344 expectedComponents = 1;
3345 break;
3346 case GL_FLOAT_VEC2:
3347 expectedComponents = 2;
3348 break;
3349 case GL_FLOAT_VEC3:
3350 expectedComponents = 3;
3351 break;
3352 case GL_FLOAT_VEC4:
3353 expectedComponents = 4;
3354 break;
3355 default:
He Yunchaoced53ae2016-11-29 15:00:51 +08003356 context->handleError(
3357 Error(GL_INVALID_OPERATION,
3358 "Fragment input type is not a floating point scalar or vector."));
Sami Väisänen46eaa942016-06-29 10:26:37 +03003359 return false;
3360 }
3361 if (expectedComponents != components && genMode != GL_NONE)
3362 {
3363 context->handleError(Error(GL_INVALID_OPERATION, "Unexpected number of components"));
3364 return false;
3365 }
3366 }
3367 return true;
3368}
3369
Geoff Lang97073d12016-04-20 10:42:34 -07003370bool ValidateCopyTextureCHROMIUM(Context *context,
3371 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003372 GLint sourceLevel,
3373 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003374 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003375 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003376 GLint internalFormat,
3377 GLenum destType,
3378 GLboolean unpackFlipY,
3379 GLboolean unpackPremultiplyAlpha,
3380 GLboolean unpackUnmultiplyAlpha)
3381{
3382 if (!context->getExtensions().copyTexture)
3383 {
3384 context->handleError(
3385 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3386 return false;
3387 }
3388
3389 const gl::Texture *source = context->getTexture(sourceId);
3390 if (source == nullptr)
3391 {
3392 context->handleError(
3393 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3394 return false;
3395 }
3396
3397 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3398 {
3399 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3400 return false;
3401 }
3402
3403 GLenum sourceTarget = source->getTarget();
3404 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3405 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3406 {
3407 context->handleError(
3408 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3409 return false;
3410 }
3411
Geoff Langca271392017-04-05 12:30:00 -04003412 const gl::InternalFormat &sourceFormat = *source->getFormat(sourceTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003413 if (!IsValidCopyTextureFormat(context, sourceFormat.format))
3414 {
3415 context->handleError(
3416 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3417 return false;
3418 }
3419
3420 const gl::Texture *dest = context->getTexture(destId);
3421 if (dest == nullptr)
3422 {
3423 context->handleError(
3424 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3425 return false;
3426 }
3427
3428 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3429 {
3430 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3431 return false;
3432 }
3433
3434 if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3435 {
3436 context->handleError(
3437 Error(GL_INVALID_OPERATION,
3438 "Destination internal format and type combination is not valid."));
3439 return false;
3440 }
3441
3442 if (dest->getImmutableFormat())
3443 {
3444 context->handleError(Error(GL_INVALID_OPERATION, "Destination texture is immutable."));
3445 return false;
3446 }
3447
3448 return true;
3449}
3450
3451bool ValidateCopySubTextureCHROMIUM(Context *context,
3452 GLuint sourceId,
Geoff Langfc72a072017-03-24 14:52:39 -04003453 GLint sourceLevel,
3454 GLenum destTarget,
Geoff Lang97073d12016-04-20 10:42:34 -07003455 GLuint destId,
Geoff Langfc72a072017-03-24 14:52:39 -04003456 GLint destLevel,
Geoff Lang97073d12016-04-20 10:42:34 -07003457 GLint xoffset,
3458 GLint yoffset,
3459 GLint x,
3460 GLint y,
3461 GLsizei width,
3462 GLsizei height,
3463 GLboolean unpackFlipY,
3464 GLboolean unpackPremultiplyAlpha,
3465 GLboolean unpackUnmultiplyAlpha)
3466{
3467 if (!context->getExtensions().copyTexture)
3468 {
3469 context->handleError(
3470 Error(GL_INVALID_OPERATION, "GL_CHROMIUM_copy_texture extension not available."));
3471 return false;
3472 }
3473
3474 const gl::Texture *source = context->getTexture(sourceId);
3475 if (source == nullptr)
3476 {
3477 context->handleError(
3478 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3479 return false;
3480 }
3481
3482 if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
3483 {
3484 context->handleError(Error(GL_INVALID_VALUE, "Source texture a valid texture type."));
3485 return false;
3486 }
3487
3488 GLenum sourceTarget = source->getTarget();
3489 ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
3490 if (source->getWidth(sourceTarget, 0) == 0 || source->getHeight(sourceTarget, 0) == 0)
3491 {
3492 context->handleError(
3493 Error(GL_INVALID_VALUE, "Level 0 of the source texture must be defined."));
3494 return false;
3495 }
3496
3497 if (x < 0 || y < 0)
3498 {
3499 context->handleError(Error(GL_INVALID_VALUE, "x and y cannot be negative."));
3500 return false;
3501 }
3502
3503 if (width < 0 || height < 0)
3504 {
3505 context->handleError(Error(GL_INVALID_VALUE, "width and height cannot be negative."));
3506 return false;
3507 }
3508
3509 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, 0) ||
3510 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, 0))
3511 {
3512 context->handleError(
3513 Error(GL_INVALID_VALUE, "Source texture not large enough to copy from."));
3514 return false;
3515 }
3516
3517 const gl::Format &sourceFormat = source->getFormat(sourceTarget, 0);
Geoff Langca271392017-04-05 12:30:00 -04003518 if (!IsValidCopyTextureFormat(context, sourceFormat.info->internalFormat))
Geoff Lang97073d12016-04-20 10:42:34 -07003519 {
3520 context->handleError(
3521 Error(GL_INVALID_OPERATION, "Source texture internal format is invalid."));
3522 return false;
3523 }
3524
3525 const gl::Texture *dest = context->getTexture(destId);
3526 if (dest == nullptr)
3527 {
3528 context->handleError(
3529 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3530 return false;
3531 }
3532
3533 if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget()))
3534 {
3535 context->handleError(Error(GL_INVALID_VALUE, "Destination texture a valid texture type."));
3536 return false;
3537 }
3538
Geoff Lang97073d12016-04-20 10:42:34 -07003539 ASSERT(destTarget != GL_TEXTURE_CUBE_MAP);
3540 if (dest->getWidth(sourceTarget, 0) == 0 || dest->getHeight(sourceTarget, 0) == 0)
3541 {
3542 context->handleError(
3543 Error(GL_INVALID_VALUE, "Level 0 of the destination texture must be defined."));
3544 return false;
3545 }
3546
Geoff Langca271392017-04-05 12:30:00 -04003547 const gl::InternalFormat &destFormat = *dest->getFormat(destTarget, 0).info;
Geoff Lang97073d12016-04-20 10:42:34 -07003548 if (!IsValidCopyTextureDestinationFormatType(context, destFormat.format, destFormat.type))
3549 {
3550 context->handleError(
3551 Error(GL_INVALID_OPERATION,
3552 "Destination internal format and type combination is not valid."));
3553 return false;
3554 }
3555
3556 if (xoffset < 0 || yoffset < 0)
3557 {
3558 context->handleError(Error(GL_INVALID_VALUE, "xoffset and yoffset cannot be negative."));
3559 return false;
3560 }
3561
3562 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, 0) ||
3563 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, 0))
3564 {
3565 context->handleError(
3566 Error(GL_INVALID_VALUE, "Destination texture not large enough to copy to."));
3567 return false;
3568 }
3569
3570 return true;
3571}
3572
Geoff Lang47110bf2016-04-20 11:13:22 -07003573bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
3574{
3575 if (!context->getExtensions().copyCompressedTexture)
3576 {
3577 context->handleError(Error(GL_INVALID_OPERATION,
3578 "GL_CHROMIUM_copy_compressed_texture extension not available."));
3579 return false;
3580 }
3581
3582 const gl::Texture *source = context->getTexture(sourceId);
3583 if (source == nullptr)
3584 {
3585 context->handleError(
3586 Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
3587 return false;
3588 }
3589
3590 if (source->getTarget() != GL_TEXTURE_2D)
3591 {
3592 context->handleError(
3593 Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
3594 return false;
3595 }
3596
3597 if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
3598 {
3599 context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
3600 return false;
3601 }
3602
3603 const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
3604 if (!sourceFormat.info->compressed)
3605 {
3606 context->handleError(
3607 Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
3608 return false;
3609 }
3610
3611 const gl::Texture *dest = context->getTexture(destId);
3612 if (dest == nullptr)
3613 {
3614 context->handleError(
3615 Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
3616 return false;
3617 }
3618
3619 if (dest->getTarget() != GL_TEXTURE_2D)
3620 {
3621 context->handleError(
3622 Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
3623 return false;
3624 }
3625
3626 if (dest->getImmutableFormat())
3627 {
3628 context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
3629 return false;
3630 }
3631
3632 return true;
3633}
3634
Martin Radev4c4c8e72016-08-04 12:25:34 +03003635bool ValidateCreateShader(Context *context, GLenum type)
3636{
3637 switch (type)
3638 {
3639 case GL_VERTEX_SHADER:
3640 case GL_FRAGMENT_SHADER:
3641 break;
Geoff Langeb66a6e2016-10-31 13:06:12 -04003642
Martin Radev4c4c8e72016-08-04 12:25:34 +03003643 case GL_COMPUTE_SHADER:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003644 if (context->getClientVersion() < Version(3, 1))
Martin Radev4c4c8e72016-08-04 12:25:34 +03003645 {
Geoff Langeb66a6e2016-10-31 13:06:12 -04003646 context->handleError(
3647 Error(GL_INVALID_ENUM, "GL_COMPUTE_SHADER requires OpenGL ES 3.1."));
3648 return false;
Martin Radev4c4c8e72016-08-04 12:25:34 +03003649 }
Geoff Langeb66a6e2016-10-31 13:06:12 -04003650 break;
3651
Martin Radev4c4c8e72016-08-04 12:25:34 +03003652 default:
Geoff Langeb66a6e2016-10-31 13:06:12 -04003653 context->handleError(Error(GL_INVALID_ENUM, "Unknown shader type."));
Martin Radev4c4c8e72016-08-04 12:25:34 +03003654 return false;
3655 }
Jamie Madill29639852016-09-02 15:00:09 -04003656
3657 return true;
3658}
3659
3660bool ValidateBufferData(ValidationContext *context,
3661 GLenum target,
3662 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003663 const void *data,
Jamie Madill29639852016-09-02 15:00:09 -04003664 GLenum usage)
3665{
3666 if (size < 0)
3667 {
3668 context->handleError(Error(GL_INVALID_VALUE));
3669 return false;
3670 }
3671
3672 switch (usage)
3673 {
3674 case GL_STREAM_DRAW:
3675 case GL_STATIC_DRAW:
3676 case GL_DYNAMIC_DRAW:
3677 break;
3678
3679 case GL_STREAM_READ:
3680 case GL_STREAM_COPY:
3681 case GL_STATIC_READ:
3682 case GL_STATIC_COPY:
3683 case GL_DYNAMIC_READ:
3684 case GL_DYNAMIC_COPY:
3685 if (context->getClientMajorVersion() < 3)
3686 {
3687 context->handleError(Error(GL_INVALID_ENUM));
3688 return false;
3689 }
3690 break;
3691
3692 default:
3693 context->handleError(Error(GL_INVALID_ENUM));
3694 return false;
3695 }
3696
3697 if (!ValidBufferTarget(context, target))
3698 {
3699 context->handleError(Error(GL_INVALID_ENUM));
3700 return false;
3701 }
3702
3703 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3704
3705 if (!buffer)
3706 {
3707 context->handleError(Error(GL_INVALID_OPERATION));
3708 return false;
3709 }
3710
3711 return true;
3712}
3713
3714bool ValidateBufferSubData(ValidationContext *context,
3715 GLenum target,
3716 GLintptr offset,
3717 GLsizeiptr size,
Jamie Madill876429b2017-04-20 15:46:24 -04003718 const void *data)
Jamie Madill29639852016-09-02 15:00:09 -04003719{
3720 if (size < 0 || offset < 0)
3721 {
3722 context->handleError(Error(GL_INVALID_VALUE));
3723 return false;
3724 }
3725
3726 if (!ValidBufferTarget(context, target))
3727 {
3728 context->handleError(Error(GL_INVALID_ENUM));
3729 return false;
3730 }
3731
3732 Buffer *buffer = context->getGLState().getTargetBuffer(target);
3733
3734 if (!buffer)
3735 {
3736 context->handleError(Error(GL_INVALID_OPERATION));
3737 return false;
3738 }
3739
3740 if (buffer->isMapped())
3741 {
3742 context->handleError(Error(GL_INVALID_OPERATION));
3743 return false;
3744 }
3745
3746 // Check for possible overflow of size + offset
3747 angle::CheckedNumeric<size_t> checkedSize(size);
3748 checkedSize += offset;
3749 if (!checkedSize.IsValid())
3750 {
3751 context->handleError(Error(GL_OUT_OF_MEMORY));
3752 return false;
3753 }
3754
3755 if (size + offset > buffer->getSize())
3756 {
3757 context->handleError(Error(GL_INVALID_VALUE));
3758 return false;
3759 }
3760
Martin Radev4c4c8e72016-08-04 12:25:34 +03003761 return true;
3762}
3763
Geoff Langc339c4e2016-11-29 10:37:36 -05003764bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
Geoff Langc287ea62016-09-16 14:46:51 -04003765{
Geoff Langc339c4e2016-11-29 10:37:36 -05003766 if (!context->getExtensions().requestExtension)
Geoff Langc287ea62016-09-16 14:46:51 -04003767 {
3768 context->handleError(
Geoff Langc339c4e2016-11-29 10:37:36 -05003769 Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
Geoff Langc287ea62016-09-16 14:46:51 -04003770 return false;
3771 }
3772
3773 const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
3774 auto extension = extensionInfos.find(name);
Geoff Langc339c4e2016-11-29 10:37:36 -05003775 if (extension == extensionInfos.end() || !extension->second.Requestable)
Geoff Langc287ea62016-09-16 14:46:51 -04003776 {
Geoff Langc339c4e2016-11-29 10:37:36 -05003777 context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
Geoff Langc287ea62016-09-16 14:46:51 -04003778 return false;
3779 }
3780
3781 return true;
3782}
3783
Jamie Madillef300b12016-10-07 15:12:09 -04003784bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
3785{
3786 if (texture < GL_TEXTURE0 ||
3787 texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
3788 {
3789 context->handleError(Error(GL_INVALID_ENUM));
3790 return false;
3791 }
3792
3793 return true;
3794}
3795
3796bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
3797{
3798 Program *programObject = GetValidProgram(context, program);
3799 if (!programObject)
3800 {
3801 return false;
3802 }
3803
3804 Shader *shaderObject = GetValidShader(context, shader);
3805 if (!shaderObject)
3806 {
3807 return false;
3808 }
3809
3810 switch (shaderObject->getType())
3811 {
3812 case GL_VERTEX_SHADER:
3813 {
3814 if (programObject->getAttachedVertexShader())
3815 {
3816 context->handleError(Error(GL_INVALID_OPERATION));
3817 return false;
3818 }
3819 break;
3820 }
3821 case GL_FRAGMENT_SHADER:
3822 {
3823 if (programObject->getAttachedFragmentShader())
3824 {
3825 context->handleError(Error(GL_INVALID_OPERATION));
3826 return false;
3827 }
3828 break;
3829 }
3830 case GL_COMPUTE_SHADER:
3831 {
3832 if (programObject->getAttachedComputeShader())
3833 {
3834 context->handleError(Error(GL_INVALID_OPERATION));
3835 return false;
3836 }
3837 break;
3838 }
3839 default:
3840 UNREACHABLE();
3841 break;
3842 }
3843
3844 return true;
3845}
3846
Jamie Madill01a80ee2016-11-07 12:06:18 -05003847bool ValidateBindAttribLocation(ValidationContext *context,
3848 GLuint program,
3849 GLuint index,
3850 const GLchar *name)
3851{
3852 if (index >= MAX_VERTEX_ATTRIBS)
3853 {
3854 context->handleError(Error(GL_INVALID_VALUE, "Index exceeds MAX_VERTEX_ATTRIBS"));
3855 return false;
3856 }
3857
3858 if (strncmp(name, "gl_", 3) == 0)
3859 {
3860 context->handleError(Error(GL_INVALID_OPERATION, "Cannot Bind built-in attributes"));
3861 return false;
3862 }
3863
3864 return GetValidProgram(context, program) != nullptr;
3865}
3866
3867bool ValidateBindBuffer(ValidationContext *context, GLenum target, GLuint buffer)
3868{
3869 if (!ValidBufferTarget(context, target))
3870 {
3871 context->handleError(Error(GL_INVALID_ENUM, "Invalid Buffer target"));
3872 return false;
3873 }
3874
3875 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3876 !context->isBufferGenerated(buffer))
3877 {
3878 context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
3879 return false;
3880 }
3881
3882 return true;
3883}
3884
3885bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
3886{
3887 if (!ValidFramebufferTarget(target))
3888 {
3889 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
3890 return false;
3891 }
3892
3893 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3894 !context->isFramebufferGenerated(framebuffer))
3895 {
3896 context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
3897 return false;
3898 }
3899
3900 return true;
3901}
3902
3903bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
3904{
3905 if (target != GL_RENDERBUFFER)
3906 {
3907 context->handleError(Error(GL_INVALID_ENUM, "Invalid Renderbuffer target"));
3908 return false;
3909 }
3910
3911 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
3912 !context->isRenderbufferGenerated(renderbuffer))
3913 {
3914 context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
3915 return false;
3916 }
3917
3918 return true;
3919}
3920
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003921static bool ValidBlendEquationMode(GLenum mode)
3922{
3923 switch (mode)
3924 {
3925 case GL_FUNC_ADD:
3926 case GL_FUNC_SUBTRACT:
3927 case GL_FUNC_REVERSE_SUBTRACT:
3928 case GL_MIN:
3929 case GL_MAX:
3930 return true;
3931
3932 default:
3933 return false;
3934 }
3935}
3936
Jamie Madillc1d770e2017-04-13 17:31:24 -04003937bool ValidateBlendColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04003938 GLfloat red,
3939 GLfloat green,
3940 GLfloat blue,
3941 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04003942{
3943 return true;
3944}
3945
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05003946bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
3947{
3948 if (!ValidBlendEquationMode(mode))
3949 {
3950 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend equation"));
3951 return false;
3952 }
3953
3954 return true;
3955}
3956
3957bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
3958{
3959 if (!ValidBlendEquationMode(modeRGB))
3960 {
3961 context->handleError(Error(GL_INVALID_ENUM, "Invalid RGB blend equation"));
3962 return false;
3963 }
3964
3965 if (!ValidBlendEquationMode(modeAlpha))
3966 {
3967 context->handleError(Error(GL_INVALID_ENUM, "Invalid alpha blend equation"));
3968 return false;
3969 }
3970
3971 return true;
3972}
3973
3974bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
3975{
3976 return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3977}
3978
3979static bool ValidSrcBlendFunc(GLenum srcBlend)
3980{
3981 switch (srcBlend)
3982 {
3983 case GL_ZERO:
3984 case GL_ONE:
3985 case GL_SRC_COLOR:
3986 case GL_ONE_MINUS_SRC_COLOR:
3987 case GL_DST_COLOR:
3988 case GL_ONE_MINUS_DST_COLOR:
3989 case GL_SRC_ALPHA:
3990 case GL_ONE_MINUS_SRC_ALPHA:
3991 case GL_DST_ALPHA:
3992 case GL_ONE_MINUS_DST_ALPHA:
3993 case GL_CONSTANT_COLOR:
3994 case GL_ONE_MINUS_CONSTANT_COLOR:
3995 case GL_CONSTANT_ALPHA:
3996 case GL_ONE_MINUS_CONSTANT_ALPHA:
3997 case GL_SRC_ALPHA_SATURATE:
3998 return true;
3999
4000 default:
4001 return false;
4002 }
4003}
4004
4005static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
4006{
4007 switch (dstBlend)
4008 {
4009 case GL_ZERO:
4010 case GL_ONE:
4011 case GL_SRC_COLOR:
4012 case GL_ONE_MINUS_SRC_COLOR:
4013 case GL_DST_COLOR:
4014 case GL_ONE_MINUS_DST_COLOR:
4015 case GL_SRC_ALPHA:
4016 case GL_ONE_MINUS_SRC_ALPHA:
4017 case GL_DST_ALPHA:
4018 case GL_ONE_MINUS_DST_ALPHA:
4019 case GL_CONSTANT_COLOR:
4020 case GL_ONE_MINUS_CONSTANT_COLOR:
4021 case GL_CONSTANT_ALPHA:
4022 case GL_ONE_MINUS_CONSTANT_ALPHA:
4023 return true;
4024
4025 case GL_SRC_ALPHA_SATURATE:
4026 return (contextMajorVersion >= 3);
4027
4028 default:
4029 return false;
4030 }
4031}
4032
4033bool ValidateBlendFuncSeparate(ValidationContext *context,
4034 GLenum srcRGB,
4035 GLenum dstRGB,
4036 GLenum srcAlpha,
4037 GLenum dstAlpha)
4038{
4039 if (!ValidSrcBlendFunc(srcRGB))
4040 {
4041 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4042 return false;
4043 }
4044
4045 if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
4046 {
4047 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4048 return false;
4049 }
4050
4051 if (!ValidSrcBlendFunc(srcAlpha))
4052 {
4053 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4054 return false;
4055 }
4056
4057 if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
4058 {
4059 context->handleError(Error(GL_INVALID_ENUM, "Invalid blend function"));
4060 return false;
4061 }
4062
Frank Henigman146e8a12017-03-02 23:22:37 -05004063 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4064 context->getExtensions().webglCompatibility)
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004065 {
4066 bool constantColorUsed =
4067 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
4068 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
4069
4070 bool constantAlphaUsed =
4071 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
4072 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
4073
4074 if (constantColorUsed && constantAlphaUsed)
4075 {
Frank Henigman146e8a12017-03-02 23:22:37 -05004076 const char *msg;
4077 if (context->getExtensions().webglCompatibility)
4078 {
4079 msg =
4080 "Invalid simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4081 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR.";
4082 }
4083 else
4084 {
4085 msg =
4086 "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
4087 "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
4088 "implementation.";
4089 ERR() << msg;
4090 }
4091 context->handleError(Error(GL_INVALID_OPERATION, msg));
Jamie Madill8a9e4bc2016-11-13 20:02:12 -05004092 return false;
4093 }
4094 }
4095
4096 return true;
4097}
4098
Geoff Langc339c4e2016-11-29 10:37:36 -05004099bool ValidateGetString(Context *context, GLenum name)
4100{
4101 switch (name)
4102 {
4103 case GL_VENDOR:
4104 case GL_RENDERER:
4105 case GL_VERSION:
4106 case GL_SHADING_LANGUAGE_VERSION:
4107 case GL_EXTENSIONS:
4108 break;
4109
4110 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
4111 if (!context->getExtensions().requestExtension)
4112 {
4113 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4114 return false;
4115 }
4116 break;
4117
4118 default:
4119 context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
4120 return false;
4121 }
4122
4123 return true;
4124}
4125
Geoff Lang47c48082016-12-07 15:38:13 -05004126bool ValidateLineWidth(ValidationContext *context, GLfloat width)
4127{
4128 if (width <= 0.0f || isNaN(width))
4129 {
4130 context->handleError(Error(GL_INVALID_VALUE, "Invalid width value."));
4131 return false;
4132 }
4133
4134 return true;
4135}
4136
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004137bool ValidateVertexAttribPointer(ValidationContext *context,
4138 GLuint index,
4139 GLint size,
4140 GLenum type,
4141 GLboolean normalized,
4142 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04004143 const void *ptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004144{
Shao80957d92017-02-20 21:25:59 +08004145 if (!ValidateVertexFormatBase(context, index, size, type, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004146 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004147 return false;
4148 }
4149
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004150 if (stride < 0)
4151 {
Shao80957d92017-02-20 21:25:59 +08004152 context->handleError(Error(GL_INVALID_VALUE, "stride cannot be negative."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004153 return false;
4154 }
4155
Shao80957d92017-02-20 21:25:59 +08004156 const Caps &caps = context->getCaps();
4157 if (context->getClientVersion() >= ES_3_1)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004158 {
Shao80957d92017-02-20 21:25:59 +08004159 if (stride > caps.maxVertexAttribStride)
4160 {
4161 context->handleError(
4162 Error(GL_INVALID_VALUE, "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE."));
4163 return false;
4164 }
4165
4166 if (index >= caps.maxVertexAttribBindings)
4167 {
4168 context->handleError(
4169 Error(GL_INVALID_VALUE, "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
4170 return false;
4171 }
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004172 }
4173
4174 // [OpenGL ES 3.0.2] Section 2.8 page 24:
4175 // An INVALID_OPERATION error is generated when a non-zero vertex array object
4176 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
4177 // and the pointer argument is not NULL.
Geoff Langfeb8c682017-02-13 16:07:35 -05004178 bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
4179 context->getGLState().getVertexArray()->id() == 0;
Shao80957d92017-02-20 21:25:59 +08004180 if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != nullptr)
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004181 {
4182 context->handleError(
4183 Error(GL_INVALID_OPERATION,
Shao80957d92017-02-20 21:25:59 +08004184 "Client data cannot be used with a non-default vertex array object."));
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004185 return false;
4186 }
4187
4188 if (context->getExtensions().webglCompatibility)
4189 {
4190 // WebGL 1.0 [Section 6.14] Fixed point support
4191 // The WebGL API does not support the GL_FIXED data type.
4192 if (type == GL_FIXED)
4193 {
4194 context->handleError(Error(GL_INVALID_ENUM, "GL_FIXED is not supported in WebGL."));
4195 return false;
4196 }
4197
Geoff Lang2d62ab72017-03-23 16:54:40 -04004198 if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004199 {
Corentin Wallez0c7baf12016-12-19 15:43:10 -05004200 return false;
4201 }
4202 }
4203
4204 return true;
4205}
4206
Jamie Madill876429b2017-04-20 15:46:24 -04004207bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
Frank Henigman6137ddc2017-02-10 18:55:07 -05004208{
4209 if (context->getExtensions().webglCompatibility && zNear > zFar)
4210 {
4211 context->handleError(Error(GL_INVALID_OPERATION, "Depth near > far."));
4212 return false;
4213 }
4214
4215 return true;
4216}
4217
Jamie Madille8fb6402017-02-14 17:56:40 -05004218bool ValidateRenderbufferStorage(ValidationContext *context,
4219 GLenum target,
4220 GLenum internalformat,
4221 GLsizei width,
4222 GLsizei height)
4223{
4224 return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
4225 height);
4226}
4227
4228bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
4229 GLenum target,
4230 GLsizei samples,
4231 GLenum internalformat,
4232 GLsizei width,
4233 GLsizei height)
4234{
4235 if (!context->getExtensions().framebufferMultisample)
4236 {
4237 context->handleError(
4238 Error(GL_INVALID_OPERATION, "GL_ANGLE_framebuffer_multisample not available"));
4239 return false;
4240 }
4241
4242 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
4243 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
4244 // generated.
4245 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
4246 {
4247 context->handleError(Error(GL_INVALID_VALUE));
4248 return false;
4249 }
4250
4251 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
4252 // the specified storage. This is different than ES 3.0 in which a sample number higher
4253 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
4254 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
4255 if (context->getClientMajorVersion() >= 3)
4256 {
4257 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
4258 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
4259 {
4260 context->handleError(Error(GL_OUT_OF_MEMORY));
4261 return false;
4262 }
4263 }
4264
4265 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
4266 width, height);
4267}
4268
Jamie Madillc1d770e2017-04-13 17:31:24 -04004269bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
4270{
4271 if (!ValidFramebufferTarget(target))
4272 {
4273 context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
4274 return false;
4275 }
4276
4277 return true;
4278}
4279
4280bool ValidateClearColor(ValidationContext *context,
Jamie Madill876429b2017-04-20 15:46:24 -04004281 GLfloat red,
4282 GLfloat green,
4283 GLfloat blue,
4284 GLfloat alpha)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004285{
4286 return true;
4287}
4288
Jamie Madill876429b2017-04-20 15:46:24 -04004289bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004290{
4291 return true;
4292}
4293
4294bool ValidateClearStencil(ValidationContext *context, GLint s)
4295{
4296 return true;
4297}
4298
4299bool ValidateColorMask(ValidationContext *context,
4300 GLboolean red,
4301 GLboolean green,
4302 GLboolean blue,
4303 GLboolean alpha)
4304{
4305 return true;
4306}
4307
4308bool ValidateCompileShader(ValidationContext *context, GLuint shader)
4309{
4310 return true;
4311}
4312
4313bool ValidateCreateProgram(ValidationContext *context)
4314{
4315 return true;
4316}
4317
4318bool ValidateCullFace(ValidationContext *context, GLenum mode)
4319{
4320 switch (mode)
4321 {
4322 case GL_FRONT:
4323 case GL_BACK:
4324 case GL_FRONT_AND_BACK:
4325 break;
4326
4327 default:
4328 context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
4329 return false;
4330 }
4331
4332 return true;
4333}
4334
4335bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
4336{
4337 if (program == 0)
4338 {
4339 return false;
4340 }
4341
4342 if (!context->getProgram(program))
4343 {
4344 if (context->getShader(program))
4345 {
4346 context->handleError(
4347 Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
4348 return false;
4349 }
4350 else
4351 {
4352 context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
4353 return false;
4354 }
4355 }
4356
4357 return true;
4358}
4359
4360bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
4361{
4362 if (shader == 0)
4363 {
4364 return false;
4365 }
4366
4367 if (!context->getShader(shader))
4368 {
4369 if (context->getProgram(shader))
4370 {
4371 context->handleError(
4372 Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
4373 return false;
4374 }
4375 else
4376 {
4377 context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
4378 return false;
4379 }
4380 }
4381
4382 return true;
4383}
4384
4385bool ValidateDepthFunc(ValidationContext *context, GLenum func)
4386{
4387 switch (func)
4388 {
4389 case GL_NEVER:
4390 case GL_ALWAYS:
4391 case GL_LESS:
4392 case GL_LEQUAL:
4393 case GL_EQUAL:
4394 case GL_GREATER:
4395 case GL_GEQUAL:
4396 case GL_NOTEQUAL:
4397 break;
4398
4399 default:
4400 context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
4401 return false;
4402 }
4403
4404 return true;
4405}
4406
4407bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
4408{
4409 return true;
4410}
4411
4412bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
4413{
4414 Program *programObject = GetValidProgram(context, program);
4415 if (!programObject)
4416 {
4417 return false;
4418 }
4419
4420 Shader *shaderObject = GetValidShader(context, shader);
4421 if (!shaderObject)
4422 {
4423 return false;
4424 }
4425
4426 const Shader *attachedShader = nullptr;
4427
4428 switch (shaderObject->getType())
4429 {
4430 case GL_VERTEX_SHADER:
4431 {
4432 attachedShader = programObject->getAttachedVertexShader();
4433 break;
4434 }
4435 case GL_FRAGMENT_SHADER:
4436 {
4437 attachedShader = programObject->getAttachedFragmentShader();
4438 break;
4439 }
4440 case GL_COMPUTE_SHADER:
4441 {
4442 attachedShader = programObject->getAttachedComputeShader();
4443 break;
4444 }
4445 default:
4446 UNREACHABLE();
4447 return false;
4448 }
4449
4450 if (attachedShader != shaderObject)
4451 {
4452 context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
4459bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
4460{
4461 if (index >= MAX_VERTEX_ATTRIBS)
4462 {
4463 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4464 return false;
4465 }
4466
4467 return true;
4468}
4469
4470bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
4471{
4472 if (index >= MAX_VERTEX_ATTRIBS)
4473 {
4474 context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
4475 return false;
4476 }
4477
4478 return true;
4479}
4480
4481bool ValidateFinish(ValidationContext *context)
4482{
4483 return true;
4484}
4485
4486bool ValidateFlush(ValidationContext *context)
4487{
4488 return true;
4489}
4490
4491bool ValidateFrontFace(ValidationContext *context, GLenum mode)
4492{
4493 switch (mode)
4494 {
4495 case GL_CW:
4496 case GL_CCW:
4497 break;
4498 default:
4499 context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
4500 return false;
4501 }
4502
4503 return true;
4504}
4505
4506bool ValidateGetActiveAttrib(ValidationContext *context,
4507 GLuint program,
4508 GLuint index,
4509 GLsizei bufsize,
4510 GLsizei *length,
4511 GLint *size,
4512 GLenum *type,
4513 GLchar *name)
4514{
4515 if (bufsize < 0)
4516 {
4517 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4518 return false;
4519 }
4520
4521 Program *programObject = GetValidProgram(context, program);
4522
4523 if (!programObject)
4524 {
4525 return false;
4526 }
4527
4528 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4529 {
4530 context->handleError(
4531 Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
4532 return false;
4533 }
4534
4535 return true;
4536}
4537
4538bool ValidateGetActiveUniform(ValidationContext *context,
4539 GLuint program,
4540 GLuint index,
4541 GLsizei bufsize,
4542 GLsizei *length,
4543 GLint *size,
4544 GLenum *type,
4545 GLchar *name)
4546{
4547 if (bufsize < 0)
4548 {
4549 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4550 return false;
4551 }
4552
4553 Program *programObject = GetValidProgram(context, program);
4554
4555 if (!programObject)
4556 {
4557 return false;
4558 }
4559
4560 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4561 {
4562 context->handleError(
4563 Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
4564 return false;
4565 }
4566
4567 return true;
4568}
4569
4570bool ValidateGetAttachedShaders(ValidationContext *context,
4571 GLuint program,
4572 GLsizei maxcount,
4573 GLsizei *count,
4574 GLuint *shaders)
4575{
4576 if (maxcount < 0)
4577 {
4578 context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
4579 return false;
4580 }
4581
4582 Program *programObject = GetValidProgram(context, program);
4583
4584 if (!programObject)
4585 {
4586 return false;
4587 }
4588
4589 return true;
4590}
4591
4592bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
4593{
4594 Program *programObject = GetValidProgram(context, program);
4595
4596 if (!programObject)
4597 {
4598 return false;
4599 }
4600
4601 if (!programObject->isLinked())
4602 {
4603 context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
4604 return false;
4605 }
4606
4607 return true;
4608}
4609
4610bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
4611{
4612 GLenum nativeType;
4613 unsigned int numParams = 0;
4614 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4615}
4616
4617bool ValidateGetError(ValidationContext *context)
4618{
4619 return true;
4620}
4621
4622bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
4623{
4624 GLenum nativeType;
4625 unsigned int numParams = 0;
4626 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4627}
4628
4629bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
4630{
4631 GLenum nativeType;
4632 unsigned int numParams = 0;
4633 return ValidateStateQuery(context, pname, &nativeType, &numParams);
4634}
4635
4636bool ValidateGetProgramInfoLog(ValidationContext *context,
4637 GLuint program,
4638 GLsizei bufsize,
4639 GLsizei *length,
4640 GLchar *infolog)
4641{
4642 if (bufsize < 0)
4643 {
4644 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4645 return false;
4646 }
4647
4648 Program *programObject = GetValidProgram(context, program);
4649 if (!programObject)
4650 {
4651 return false;
4652 }
4653
4654 return true;
4655}
4656
4657bool ValidateGetShaderInfoLog(ValidationContext *context,
4658 GLuint shader,
4659 GLsizei bufsize,
4660 GLsizei *length,
4661 GLchar *infolog)
4662{
4663 if (bufsize < 0)
4664 {
4665 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4666 return false;
4667 }
4668
4669 Shader *shaderObject = GetValidShader(context, shader);
4670 if (!shaderObject)
4671 {
4672 return false;
4673 }
4674
4675 return true;
4676}
4677
4678bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
4679 GLenum shadertype,
4680 GLenum precisiontype,
4681 GLint *range,
4682 GLint *precision)
4683{
4684 switch (shadertype)
4685 {
4686 case GL_VERTEX_SHADER:
4687 case GL_FRAGMENT_SHADER:
4688 break;
4689 case GL_COMPUTE_SHADER:
4690 context->handleError(
4691 Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
4692 return false;
4693 default:
4694 context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
4695 return false;
4696 }
4697
4698 switch (precisiontype)
4699 {
4700 case GL_LOW_FLOAT:
4701 case GL_MEDIUM_FLOAT:
4702 case GL_HIGH_FLOAT:
4703 case GL_LOW_INT:
4704 case GL_MEDIUM_INT:
4705 case GL_HIGH_INT:
4706 break;
4707
4708 default:
4709 context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
4710 return false;
4711 }
4712
4713 return true;
4714}
4715
4716bool ValidateGetShaderSource(ValidationContext *context,
4717 GLuint shader,
4718 GLsizei bufsize,
4719 GLsizei *length,
4720 GLchar *source)
4721{
4722 if (bufsize < 0)
4723 {
4724 context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
4725 return false;
4726 }
4727
4728 Shader *shaderObject = GetValidShader(context, shader);
4729 if (!shaderObject)
4730 {
4731 return false;
4732 }
4733
4734 return true;
4735}
4736
4737bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
4738{
4739 if (strstr(name, "gl_") == name)
4740 {
4741 return false;
4742 }
4743
4744 Program *programObject = GetValidProgram(context, program);
4745
4746 if (!programObject)
4747 {
4748 return false;
4749 }
4750
4751 if (!programObject->isLinked())
4752 {
4753 context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
4754 return false;
4755 }
4756
4757 return true;
4758}
4759
4760bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
4761{
4762 switch (mode)
4763 {
4764 case GL_FASTEST:
4765 case GL_NICEST:
4766 case GL_DONT_CARE:
4767 break;
4768
4769 default:
4770 context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
4771 return false;
4772 }
4773
4774 switch (target)
4775 {
4776 case GL_GENERATE_MIPMAP_HINT:
4777 break;
4778
4779 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4780 if (!context->getExtensions().standardDerivatives)
4781 {
4782 context->handleError(
4783 Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
4784 return false;
4785 }
4786 break;
4787
4788 default:
4789 context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
4790 return false;
4791 }
4792
4793 return true;
4794}
4795
4796bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
4797{
4798 return true;
4799}
4800
4801bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
4802{
4803 return true;
4804}
4805
4806bool ValidateIsProgram(ValidationContext *context, GLuint program)
4807{
4808 return true;
4809}
4810
4811bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
4812{
4813 return true;
4814}
4815
4816bool ValidateIsShader(ValidationContext *context, GLuint shader)
4817{
4818 return true;
4819}
4820
4821bool ValidateIsTexture(ValidationContext *context, GLuint texture)
4822{
4823 return true;
4824}
4825
4826bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
4827{
4828 if (context->getClientMajorVersion() < 3)
4829 {
4830 switch (pname)
4831 {
4832 case GL_UNPACK_IMAGE_HEIGHT:
4833 case GL_UNPACK_SKIP_IMAGES:
4834 context->handleError(Error(GL_INVALID_ENUM));
4835 return false;
4836
4837 case GL_UNPACK_ROW_LENGTH:
4838 case GL_UNPACK_SKIP_ROWS:
4839 case GL_UNPACK_SKIP_PIXELS:
4840 if (!context->getExtensions().unpackSubimage)
4841 {
4842 context->handleError(Error(GL_INVALID_ENUM));
4843 return false;
4844 }
4845 break;
4846
4847 case GL_PACK_ROW_LENGTH:
4848 case GL_PACK_SKIP_ROWS:
4849 case GL_PACK_SKIP_PIXELS:
4850 if (!context->getExtensions().packSubimage)
4851 {
4852 context->handleError(Error(GL_INVALID_ENUM));
4853 return false;
4854 }
4855 break;
4856 }
4857 }
4858
4859 if (param < 0)
4860 {
4861 context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
4862 return false;
4863 }
4864
4865 switch (pname)
4866 {
4867 case GL_UNPACK_ALIGNMENT:
4868 if (param != 1 && param != 2 && param != 4 && param != 8)
4869 {
4870 context->handleError(Error(GL_INVALID_VALUE));
4871 return false;
4872 }
4873 break;
4874
4875 case GL_PACK_ALIGNMENT:
4876 if (param != 1 && param != 2 && param != 4 && param != 8)
4877 {
4878 context->handleError(Error(GL_INVALID_VALUE));
4879 return false;
4880 }
4881 break;
4882
4883 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4884 case GL_UNPACK_ROW_LENGTH:
4885 case GL_UNPACK_IMAGE_HEIGHT:
4886 case GL_UNPACK_SKIP_IMAGES:
4887 case GL_UNPACK_SKIP_ROWS:
4888 case GL_UNPACK_SKIP_PIXELS:
4889 case GL_PACK_ROW_LENGTH:
4890 case GL_PACK_SKIP_ROWS:
4891 case GL_PACK_SKIP_PIXELS:
4892 break;
4893
4894 default:
4895 context->handleError(Error(GL_INVALID_ENUM));
4896 return false;
4897 }
4898
4899 return true;
4900}
4901
4902bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
4903{
4904 return true;
4905}
4906
4907bool ValidateReleaseShaderCompiler(ValidationContext *context)
4908{
4909 return true;
4910}
4911
Jamie Madill876429b2017-04-20 15:46:24 -04004912bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
Jamie Madillc1d770e2017-04-13 17:31:24 -04004913{
4914 return true;
4915}
4916
4917bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
4918{
4919 if (width < 0 || height < 0)
4920 {
4921 context->handleError(
4922 Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
4923 return false;
4924 }
4925
4926 return true;
4927}
4928
4929bool ValidateShaderBinary(ValidationContext *context,
4930 GLsizei n,
4931 const GLuint *shaders,
4932 GLenum binaryformat,
Jamie Madill876429b2017-04-20 15:46:24 -04004933 const void *binary,
Jamie Madillc1d770e2017-04-13 17:31:24 -04004934 GLsizei length)
4935{
4936 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4937 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4938 shaderBinaryFormats.end())
4939 {
4940 context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
4941 return false;
4942 }
4943
4944 return true;
4945}
4946
4947bool ValidateShaderSource(ValidationContext *context,
4948 GLuint shader,
4949 GLsizei count,
4950 const GLchar *const *string,
4951 const GLint *length)
4952{
4953 if (count < 0)
4954 {
4955 context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
4956 return false;
4957 }
4958
4959 Shader *shaderObject = GetValidShader(context, shader);
4960 if (!shaderObject)
4961 {
4962 return false;
4963 }
4964
4965 return true;
4966}
4967
4968bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
4969{
4970 if (!IsValidStencilFunc(func))
4971 {
4972 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4973 return false;
4974 }
4975
4976 return true;
4977}
4978
4979bool ValidateStencilFuncSeparate(ValidationContext *context,
4980 GLenum face,
4981 GLenum func,
4982 GLint ref,
4983 GLuint mask)
4984{
4985 if (!IsValidStencilFace(face))
4986 {
4987 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
4988 return false;
4989 }
4990
4991 if (!IsValidStencilFunc(func))
4992 {
4993 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
4994 return false;
4995 }
4996
4997 return true;
4998}
4999
5000bool ValidateStencilMask(ValidationContext *context, GLuint mask)
5001{
5002 return true;
5003}
5004
5005bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
5006{
5007 if (!IsValidStencilFace(face))
5008 {
5009 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5010 return false;
5011 }
5012
5013 return true;
5014}
5015
5016bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
5017{
5018 if (!IsValidStencilOp(fail))
5019 {
5020 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
5021 return false;
5022 }
5023
5024 if (!IsValidStencilOp(zfail))
5025 {
5026 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
5027 return false;
5028 }
5029
5030 if (!IsValidStencilOp(zpass))
5031 {
5032 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
5033 return false;
5034 }
5035
5036 return true;
5037}
5038
5039bool ValidateStencilOpSeparate(ValidationContext *context,
5040 GLenum face,
5041 GLenum fail,
5042 GLenum zfail,
5043 GLenum zpass)
5044{
5045 if (!IsValidStencilFace(face))
5046 {
5047 context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
5048 return false;
5049 }
5050
5051 return ValidateStencilOp(context, fail, zfail, zpass);
5052}
5053
5054bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
5055{
5056 return ValidateUniform(context, GL_FLOAT, location, 1);
5057}
5058
5059bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5060{
5061 return ValidateUniform(context, GL_FLOAT, location, count);
5062}
5063
Jamie Madillbe849e42017-05-02 15:49:00 -04005064bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
5065{
5066 return ValidateUniform1iv(context, location, 1, &x);
5067}
5068
Jamie Madillc1d770e2017-04-13 17:31:24 -04005069bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
5070{
5071 return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
5072}
5073
5074bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5075{
5076 return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
5077}
5078
5079bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
5080{
5081 return ValidateUniform(context, GL_INT_VEC2, location, 1);
5082}
5083
5084bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5085{
5086 return ValidateUniform(context, GL_INT_VEC2, location, count);
5087}
5088
5089bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
5090{
5091 return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
5092}
5093
5094bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5095{
5096 return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
5097}
5098
5099bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
5100{
5101 return ValidateUniform(context, GL_INT_VEC3, location, 1);
5102}
5103
5104bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5105{
5106 return ValidateUniform(context, GL_INT_VEC3, location, count);
5107}
5108
5109bool ValidateUniform4f(ValidationContext *context,
5110 GLint location,
5111 GLfloat x,
5112 GLfloat y,
5113 GLfloat z,
5114 GLfloat w)
5115{
5116 return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
5117}
5118
5119bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
5120{
5121 return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
5122}
5123
5124bool ValidateUniform4i(ValidationContext *context,
5125 GLint location,
5126 GLint x,
5127 GLint y,
5128 GLint z,
5129 GLint w)
5130{
5131 return ValidateUniform(context, GL_INT_VEC4, location, 1);
5132}
5133
5134bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
5135{
5136 return ValidateUniform(context, GL_INT_VEC4, location, count);
5137}
5138
5139bool ValidateUniformMatrix2fv(ValidationContext *context,
5140 GLint location,
5141 GLsizei count,
5142 GLboolean transpose,
5143 const GLfloat *value)
5144{
5145 return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
5146}
5147
5148bool ValidateUniformMatrix3fv(ValidationContext *context,
5149 GLint location,
5150 GLsizei count,
5151 GLboolean transpose,
5152 const GLfloat *value)
5153{
5154 return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
5155}
5156
5157bool ValidateUniformMatrix4fv(ValidationContext *context,
5158 GLint location,
5159 GLsizei count,
5160 GLboolean transpose,
5161 const GLfloat *value)
5162{
5163 return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
5164}
5165
5166bool ValidateValidateProgram(ValidationContext *context, GLuint program)
5167{
5168 Program *programObject = GetValidProgram(context, program);
5169
5170 if (!programObject)
5171 {
5172 return false;
5173 }
5174
5175 return true;
5176}
5177
5178bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5179{
5180 if (index >= MAX_VERTEX_ATTRIBS)
5181 {
5182 context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
5183 return false;
5184 }
5185
5186 return true;
5187}
5188
5189bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
5190{
5191 return ValidateVertexAttribIndex(context, index);
5192}
5193
5194bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
5195{
5196 return ValidateVertexAttribIndex(context, index);
5197}
5198
5199bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
5200{
5201 return ValidateVertexAttribIndex(context, index);
5202}
5203
5204bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
5205{
5206 return ValidateVertexAttribIndex(context, index);
5207}
5208
5209bool ValidateVertexAttrib3f(ValidationContext *context,
5210 GLuint index,
5211 GLfloat x,
5212 GLfloat y,
5213 GLfloat z)
5214{
5215 return ValidateVertexAttribIndex(context, index);
5216}
5217
5218bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
5219{
5220 return ValidateVertexAttribIndex(context, index);
5221}
5222
5223bool ValidateVertexAttrib4f(ValidationContext *context,
5224 GLuint index,
5225 GLfloat x,
5226 GLfloat y,
5227 GLfloat z,
5228 GLfloat w)
5229{
5230 return ValidateVertexAttribIndex(context, index);
5231}
5232
5233bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
5234{
5235 return ValidateVertexAttribIndex(context, index);
5236}
5237
5238bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
5239{
5240 if (width < 0 || height < 0)
5241 {
5242 context->handleError(
5243 Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
5244 return false;
5245 }
5246
5247 return true;
5248}
5249
5250bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
5251{
5252 return ValidateDrawArraysCommon(context, mode, first, count, 1);
5253}
5254
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005255bool ValidateDrawElements(ValidationContext *context,
5256 GLenum mode,
5257 GLsizei count,
5258 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04005259 const void *indices)
Jamie Madill9c9b40a2017-04-26 16:31:57 -04005260{
5261 return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
5262}
5263
Jamie Madillbe849e42017-05-02 15:49:00 -04005264bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5265 GLenum target,
5266 GLenum attachment,
5267 GLenum pname,
5268 GLint *params)
5269{
5270 return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
5271 nullptr);
5272}
5273
5274bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
5275{
5276 return ValidateGetProgramivBase(context, program, pname, nullptr);
5277}
5278
5279bool ValidateCopyTexImage2D(ValidationContext *context,
5280 GLenum target,
5281 GLint level,
5282 GLenum internalformat,
5283 GLint x,
5284 GLint y,
5285 GLsizei width,
5286 GLsizei height,
5287 GLint border)
5288{
5289 if (context->getClientMajorVersion() < 3)
5290 {
5291 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5292 0, x, y, width, height, border);
5293 }
5294
5295 ASSERT(context->getClientMajorVersion() == 3);
5296 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5297 0, x, y, width, height, border);
5298}
5299
5300bool ValidateCopyTexSubImage2D(Context *context,
5301 GLenum target,
5302 GLint level,
5303 GLint xoffset,
5304 GLint yoffset,
5305 GLint x,
5306 GLint y,
5307 GLsizei width,
5308 GLsizei height)
5309{
5310 if (context->getClientMajorVersion() < 3)
5311 {
5312 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5313 yoffset, x, y, width, height, 0);
5314 }
5315
5316 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5317 yoffset, 0, x, y, width, height, 0);
5318}
5319
5320bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5321{
5322 return ValidateGenOrDelete(context, n);
5323}
5324
5325bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5326{
5327 return ValidateGenOrDelete(context, n);
5328}
5329
5330bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5331{
5332 return ValidateGenOrDelete(context, n);
5333}
5334
5335bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5336{
5337 return ValidateGenOrDelete(context, n);
5338}
5339
5340bool ValidateDisable(Context *context, GLenum cap)
5341{
5342 if (!ValidCap(context, cap, false))
5343 {
5344 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5345 return false;
5346 }
5347
5348 return true;
5349}
5350
5351bool ValidateEnable(Context *context, GLenum cap)
5352{
5353 if (!ValidCap(context, cap, false))
5354 {
5355 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5356 return false;
5357 }
5358
5359 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5360 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5361 {
5362 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5363 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5364
5365 // We also output an error message to the debugger window if tracing is active, so that
5366 // developers can see the error message.
5367 ERR() << errorMessage;
5368 return false;
5369 }
5370
5371 return true;
5372}
5373
5374bool ValidateFramebufferRenderbuffer(Context *context,
5375 GLenum target,
5376 GLenum attachment,
5377 GLenum renderbuffertarget,
5378 GLuint renderbuffer)
5379{
5380 if (!ValidFramebufferTarget(target) ||
5381 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
5382 {
5383 context->handleError(Error(GL_INVALID_ENUM));
5384 return false;
5385 }
5386
5387 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
5388 renderbuffertarget, renderbuffer);
5389}
5390
5391bool ValidateFramebufferTexture2D(Context *context,
5392 GLenum target,
5393 GLenum attachment,
5394 GLenum textarget,
5395 GLuint texture,
5396 GLint level)
5397{
5398 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5399 // extension
5400 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
5401 level != 0)
5402 {
5403 context->handleError(Error(GL_INVALID_VALUE));
5404 return false;
5405 }
5406
5407 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5408 {
5409 return false;
5410 }
5411
5412 if (texture != 0)
5413 {
5414 gl::Texture *tex = context->getTexture(texture);
5415 ASSERT(tex);
5416
5417 const gl::Caps &caps = context->getCaps();
5418
5419 switch (textarget)
5420 {
5421 case GL_TEXTURE_2D:
5422 {
5423 if (level > gl::log2(caps.max2DTextureSize))
5424 {
5425 context->handleError(Error(GL_INVALID_VALUE));
5426 return false;
5427 }
5428 if (tex->getTarget() != GL_TEXTURE_2D)
5429 {
5430 context->handleError(Error(GL_INVALID_OPERATION,
5431 "Textarget must match the texture target type."));
5432 return false;
5433 }
5434 }
5435 break;
5436
5437 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5438 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5439 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5440 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5441 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5442 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5443 {
5444 if (level > gl::log2(caps.maxCubeMapTextureSize))
5445 {
5446 context->handleError(Error(GL_INVALID_VALUE));
5447 return false;
5448 }
5449 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
5450 {
5451 context->handleError(Error(GL_INVALID_OPERATION,
5452 "Textarget must match the texture target type."));
5453 return false;
5454 }
5455 }
5456 break;
5457
5458 case GL_TEXTURE_2D_MULTISAMPLE:
5459 {
5460 if (context->getClientVersion() < ES_3_1)
5461 {
5462 context->handleError(Error(GL_INVALID_OPERATION,
5463 "Texture target requires at least OpenGL ES 3.1."));
5464 return false;
5465 }
5466
5467 if (level != 0)
5468 {
5469 context->handleError(
5470 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
5471 return false;
5472 }
5473 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
5474 {
5475 context->handleError(Error(GL_INVALID_OPERATION,
5476 "Textarget must match the texture target type."));
5477 return false;
5478 }
5479 }
5480 break;
5481
5482 default:
5483 context->handleError(Error(GL_INVALID_ENUM));
5484 return false;
5485 }
5486
5487 const Format &format = tex->getFormat(textarget, level);
5488 if (format.info->compressed)
5489 {
5490 context->handleError(Error(GL_INVALID_OPERATION));
5491 return false;
5492 }
5493 }
5494
5495 return true;
5496}
5497
5498bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5499{
5500 return ValidateGenOrDelete(context, n);
5501}
5502
5503bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5504{
5505 return ValidateGenOrDelete(context, n);
5506}
5507
5508bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5509{
5510 return ValidateGenOrDelete(context, n);
5511}
5512
5513bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5514{
5515 return ValidateGenOrDelete(context, n);
5516}
5517
5518bool ValidateGenerateMipmap(Context *context, GLenum target)
5519{
5520 if (!ValidTextureTarget(context, target))
5521 {
5522 context->handleError(Error(GL_INVALID_ENUM));
5523 return false;
5524 }
5525
5526 Texture *texture = context->getTargetTexture(target);
5527
5528 if (texture == nullptr)
5529 {
5530 context->handleError(Error(GL_INVALID_OPERATION));
5531 return false;
5532 }
5533
5534 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5535
5536 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5537 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5538 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5539 {
5540 context->handleError(Error(GL_INVALID_OPERATION));
5541 return false;
5542 }
5543
5544 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5545 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
5546 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
5547
5548 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5549 // unsized formats or that are color renderable and filterable. Since we do not track if
5550 // the texture was created with sized or unsized format (only sized formats are stored),
5551 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5552 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5553 // textures since they're the only texture format that can be created with unsized formats
5554 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5555 // was the last version to use add them.
5556 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5557 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
5558 {
5559 context->handleError(Error(GL_INVALID_OPERATION));
5560 return false;
5561 }
5562
Geoff Lang65ac5b92017-05-01 13:16:30 -04005563 // ES3 and WebGL grant mipmap generation for sRGB textures but GL_EXT_sRGB does not.
5564 bool supportsSRGBMipmapGeneration =
5565 context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
5566 if (!supportsSRGBMipmapGeneration && format.info->colorEncoding == GL_SRGB)
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 {
Geoff Lang65ac5b92017-05-01 13:16:30 -04005568 context->handleError(
5569 Error(GL_INVALID_OPERATION, "Mipmap generation of sRGB textures is not allowed."));
Jamie Madillbe849e42017-05-02 15:49:00 -04005570 return false;
5571 }
5572
5573 // Non-power of 2 ES2 check
5574 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
5575 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5576 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5577 {
5578 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
5579 context->handleError(Error(GL_INVALID_OPERATION));
5580 return false;
5581 }
5582
5583 // Cube completeness check
5584 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5585 {
5586 context->handleError(Error(GL_INVALID_OPERATION));
5587 return false;
5588 }
5589
5590 return true;
5591}
5592
5593bool ValidateGetBufferParameteriv(ValidationContext *context,
5594 GLenum target,
5595 GLenum pname,
5596 GLint *params)
5597{
5598 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5599}
5600
5601bool ValidateGetRenderbufferParameteriv(Context *context,
5602 GLenum target,
5603 GLenum pname,
5604 GLint *params)
5605{
5606 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5607}
5608
5609bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5610{
5611 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5612}
5613
5614bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5615{
5616 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5617}
5618
5619bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5620{
5621 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5622}
5623
5624bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
5625{
5626 return ValidateGetUniformBase(context, program, location);
5627}
5628
5629bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
5630{
5631 return ValidateGetUniformBase(context, program, location);
5632}
5633
5634bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5635{
5636 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5637}
5638
5639bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5640{
5641 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5642}
5643
5644bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5645{
5646 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5647}
5648
5649bool ValidateIsEnabled(Context *context, GLenum cap)
5650{
5651 if (!ValidCap(context, cap, true))
5652 {
5653 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5654 return false;
5655 }
5656
5657 return true;
5658}
5659
5660bool ValidateLinkProgram(Context *context, GLuint program)
5661{
5662 if (context->hasActiveTransformFeedback(program))
5663 {
5664 // ES 3.0.4 section 2.15 page 91
5665 context->handleError(Error(GL_INVALID_OPERATION,
5666 "Cannot link program while program is associated with an active "
5667 "transform feedback object."));
5668 return false;
5669 }
5670
5671 Program *programObject = GetValidProgram(context, program);
5672 if (!programObject)
5673 {
5674 return false;
5675 }
5676
5677 return true;
5678}
5679
5680bool ValidateReadPixels(ValidationContext *context,
5681 GLint x,
5682 GLint y,
5683 GLsizei width,
5684 GLsizei height,
5685 GLenum format,
5686 GLenum type,
5687 void *pixels)
5688{
5689 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5690 nullptr, pixels);
5691}
5692
5693bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5694{
5695 return ValidateTexParameterBase(context, target, pname, -1, &param);
5696}
5697
5698bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5699{
5700 return ValidateTexParameterBase(context, target, pname, -1, params);
5701}
5702
5703bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5704{
5705 return ValidateTexParameterBase(context, target, pname, -1, &param);
5706}
5707
5708bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5709{
5710 return ValidateTexParameterBase(context, target, pname, -1, params);
5711}
5712
5713bool ValidateUseProgram(Context *context, GLuint program)
5714{
5715 if (program != 0)
5716 {
5717 Program *programObject = context->getProgram(program);
5718 if (!programObject)
5719 {
5720 // ES 3.1.0 section 7.3 page 72
5721 if (context->getShader(program))
5722 {
5723 context->handleError(
5724 Error(GL_INVALID_OPERATION,
5725 "Attempted to use a single shader instead of a shader program."));
5726 return false;
5727 }
5728 else
5729 {
5730 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
5731 return false;
5732 }
5733 }
5734 if (!programObject->isLinked())
5735 {
5736 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
5737 return false;
5738 }
5739 }
5740 if (context->getGLState().isTransformFeedbackActiveUnpaused())
5741 {
5742 // ES 3.0.4 section 2.15 page 91
5743 context->handleError(
5744 Error(GL_INVALID_OPERATION,
5745 "Cannot change active program while transform feedback is unpaused."));
5746 return false;
5747 }
5748
5749 return true;
5750}
5751
Jamie Madillc29968b2016-01-20 11:17:23 -05005752} // namespace gl