blob: c00c0aa47005ac236daba57d0b86354cd5c71323 [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// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
He Yunchaoced53ae2016-11-29 15:00:51 +080042 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
44 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040045 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
He Yunchaoced53ae2016-11-29 15:00:51 +080054 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
Jamie Madill1ca74672015-07-21 15:14:11 -040055 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700165 case GL_FRAMEBUFFER_SRGB_EXT:
166 return context->getExtensions().sRGBWriteControl;
167
Geoff Lang3b573612016-10-31 14:08:10 -0400168 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400169 return context->getClientVersion() >= Version(3, 1);
170
Geoff Langf41a7152016-09-19 15:11:17 -0400171 default:
172 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500173 }
174}
175
Geoff Lang62fce5b2016-09-30 10:46:35 -0400176bool ValidateReadPixelsBase(ValidationContext *context,
177 GLint x,
178 GLint y,
179 GLsizei width,
180 GLsizei height,
181 GLenum format,
182 GLenum type,
183 GLsizei bufSize,
184 GLsizei *length,
185 GLvoid *pixels)
186{
187 if (length != nullptr)
188 {
189 *length = 0;
190 }
191
192 if (width < 0 || height < 0)
193 {
194 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
195 return false;
196 }
197
198 auto readFramebuffer = context->getGLState().getReadFramebuffer();
199
200 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
201 {
202 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
203 return false;
204 }
205
206 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
207 {
208 context->handleError(Error(GL_INVALID_OPERATION));
209 return false;
210 }
211
212 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
213 ASSERT(framebuffer);
214
215 if (framebuffer->getReadBufferState() == GL_NONE)
216 {
217 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
218 return false;
219 }
220
221 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
222 if (!readBuffer)
223 {
224 context->handleError(Error(GL_INVALID_OPERATION));
225 return false;
226 }
227
228 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
229 GLenum currentType = framebuffer->getImplementationColorReadType();
230 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
231
232 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
233 bool validFormatTypeCombination =
234 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
235
236 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
237 {
238 context->handleError(Error(GL_INVALID_OPERATION));
239 return false;
240 }
241
242 // Check for pixel pack buffer related API errors
243 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
244 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
245 {
246 // ...the buffer object's data store is currently mapped.
247 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
248 return false;
249 }
250
251 // .. the data would be packed to the buffer object such that the memory writes required
252 // would exceed the data store size.
253 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
254 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
255 const gl::Extents size(width, height, 1);
256 const auto &pack = context->getGLState().getPackState();
257
258 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
259 if (endByteOrErr.isError())
260 {
261 context->handleError(endByteOrErr.getError());
262 return false;
263 }
264
265 size_t endByte = endByteOrErr.getResult();
266 if (bufSize >= 0)
267 {
268
269 if (static_cast<size_t>(bufSize) < endByte)
270 {
271 context->handleError(
272 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
273 return false;
274 }
275 }
276
277 if (pixelPackBuffer != nullptr)
278 {
279 CheckedNumeric<size_t> checkedEndByte(endByte);
280 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
281 checkedEndByte += checkedOffset;
282
283 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
284 {
285 // Overflow past the end of the buffer
286 context->handleError(
287 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
288 return false;
289 }
290 }
291
292 if (length != nullptr)
293 {
294 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
295 {
296 context->handleError(
297 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
298 return false;
299 }
300
301 *length = static_cast<GLsizei>(endByte);
302 }
303
304 return true;
305}
306
Geoff Lang740d9022016-10-07 11:20:52 -0400307bool ValidateGetRenderbufferParameterivBase(Context *context,
308 GLenum target,
309 GLenum pname,
310 GLsizei *length)
311{
312 if (length)
313 {
314 *length = 0;
315 }
316
317 if (target != GL_RENDERBUFFER)
318 {
319 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
320 return false;
321 }
322
323 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
324 if (renderbuffer == nullptr)
325 {
326 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
327 return false;
328 }
329
330 switch (pname)
331 {
332 case GL_RENDERBUFFER_WIDTH:
333 case GL_RENDERBUFFER_HEIGHT:
334 case GL_RENDERBUFFER_INTERNAL_FORMAT:
335 case GL_RENDERBUFFER_RED_SIZE:
336 case GL_RENDERBUFFER_GREEN_SIZE:
337 case GL_RENDERBUFFER_BLUE_SIZE:
338 case GL_RENDERBUFFER_ALPHA_SIZE:
339 case GL_RENDERBUFFER_DEPTH_SIZE:
340 case GL_RENDERBUFFER_STENCIL_SIZE:
341 break;
342
343 case GL_RENDERBUFFER_SAMPLES_ANGLE:
344 if (!context->getExtensions().framebufferMultisample)
345 {
346 context->handleError(
347 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
348 return false;
349 }
350 break;
351
352 default:
353 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
354 return false;
355 }
356
357 if (length)
358 {
359 *length = 1;
360 }
361 return true;
362}
363
Geoff Langd7d0ed32016-10-07 11:33:51 -0400364bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
365{
366 if (length)
367 {
368 *length = 0;
369 }
370
371 if (GetValidShader(context, shader) == nullptr)
372 {
373 return false;
374 }
375
376 switch (pname)
377 {
378 case GL_SHADER_TYPE:
379 case GL_DELETE_STATUS:
380 case GL_COMPILE_STATUS:
381 case GL_INFO_LOG_LENGTH:
382 case GL_SHADER_SOURCE_LENGTH:
383 break;
384
385 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
386 if (!context->getExtensions().translatedShaderSource)
387 {
388 context->handleError(
389 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
390 return false;
391 }
392 break;
393
394 default:
395 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
396 return false;
397 }
398
399 if (length)
400 {
401 *length = 1;
402 }
403 return true;
404}
405
Geoff Langc1984ed2016-10-07 12:41:00 -0400406bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
407{
408 if (length)
409 {
410 *length = 0;
411 }
412
413 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
414 {
415 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
416 return false;
417 }
418
419 if (context->getTargetTexture(target) == nullptr)
420 {
421 // Should only be possible for external textures
422 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
423 return false;
424 }
425
426 switch (pname)
427 {
428 case GL_TEXTURE_MAG_FILTER:
429 case GL_TEXTURE_MIN_FILTER:
430 case GL_TEXTURE_WRAP_S:
431 case GL_TEXTURE_WRAP_T:
432 break;
433
434 case GL_TEXTURE_USAGE_ANGLE:
435 if (!context->getExtensions().textureUsage)
436 {
437 context->handleError(
438 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
439 return false;
440 }
441 break;
442
443 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
444 if (!context->getExtensions().textureFilterAnisotropic)
445 {
446 context->handleError(
447 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
448 return false;
449 }
450 break;
451
452 case GL_TEXTURE_IMMUTABLE_FORMAT:
453 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
454 {
455 context->handleError(
456 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
457 return false;
458 }
459 break;
460
461 case GL_TEXTURE_WRAP_R:
462 case GL_TEXTURE_IMMUTABLE_LEVELS:
463 case GL_TEXTURE_SWIZZLE_R:
464 case GL_TEXTURE_SWIZZLE_G:
465 case GL_TEXTURE_SWIZZLE_B:
466 case GL_TEXTURE_SWIZZLE_A:
467 case GL_TEXTURE_BASE_LEVEL:
468 case GL_TEXTURE_MAX_LEVEL:
469 case GL_TEXTURE_MIN_LOD:
470 case GL_TEXTURE_MAX_LOD:
471 case GL_TEXTURE_COMPARE_MODE:
472 case GL_TEXTURE_COMPARE_FUNC:
473 if (context->getClientMajorVersion() < 3)
474 {
475 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
476 return false;
477 }
478 break;
479
Geoff Lang81c6b572016-10-19 14:07:52 -0700480 case GL_TEXTURE_SRGB_DECODE_EXT:
481 if (!context->getExtensions().textureSRGBDecode)
482 {
483 context->handleError(
484 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
485 return false;
486 }
487 break;
488
Geoff Langc1984ed2016-10-07 12:41:00 -0400489 default:
490 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
491 return false;
492 }
493
494 if (length)
495 {
496 *length = 1;
497 }
498 return true;
499}
500
501template <typename ParamType>
502bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
503{
504 switch (ConvertToGLenum(params[0]))
505 {
506 case GL_CLAMP_TO_EDGE:
507 break;
508
509 case GL_REPEAT:
510 case GL_MIRRORED_REPEAT:
511 if (isExternalTextureTarget)
512 {
513 // OES_EGL_image_external specifies this error.
514 context->handleError(Error(
515 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
516 return false;
517 }
518 break;
519
520 default:
521 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
522 return false;
523 }
524
525 return true;
526}
527
528template <typename ParamType>
529bool ValidateTextureMinFilterValue(Context *context,
530 ParamType *params,
531 bool isExternalTextureTarget)
532{
533 switch (ConvertToGLenum(params[0]))
534 {
535 case GL_NEAREST:
536 case GL_LINEAR:
537 break;
538
539 case GL_NEAREST_MIPMAP_NEAREST:
540 case GL_LINEAR_MIPMAP_NEAREST:
541 case GL_NEAREST_MIPMAP_LINEAR:
542 case GL_LINEAR_MIPMAP_LINEAR:
543 if (isExternalTextureTarget)
544 {
545 // OES_EGL_image_external specifies this error.
546 context->handleError(
547 Error(GL_INVALID_ENUM,
548 "external textures only support NEAREST and LINEAR filtering"));
549 return false;
550 }
551 break;
552
553 default:
554 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
555 return false;
556 }
557
558 return true;
559}
560
561template <typename ParamType>
562bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
563{
564 switch (ConvertToGLenum(params[0]))
565 {
566 case GL_NEAREST:
567 case GL_LINEAR:
568 break;
569
570 default:
571 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
572 return false;
573 }
574
575 return true;
576}
577
578template <typename ParamType>
579bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
580{
581 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
582 switch (ConvertToGLenum(params[0]))
583 {
584 case GL_NONE:
585 case GL_COMPARE_REF_TO_TEXTURE:
586 break;
587
588 default:
589 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
590 return false;
591 }
592
593 return true;
594}
595
596template <typename ParamType>
597bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
598{
599 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
600 switch (ConvertToGLenum(params[0]))
601 {
602 case GL_LEQUAL:
603 case GL_GEQUAL:
604 case GL_LESS:
605 case GL_GREATER:
606 case GL_EQUAL:
607 case GL_NOTEQUAL:
608 case GL_ALWAYS:
609 case GL_NEVER:
610 break;
611
612 default:
613 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
614 return false;
615 }
616
617 return true;
618}
619
620template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700621bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
622{
623 if (!context->getExtensions().textureSRGBDecode)
624 {
625 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
626 return false;
627 }
628
629 switch (ConvertToGLenum(params[0]))
630 {
631 case GL_DECODE_EXT:
632 case GL_SKIP_DECODE_EXT:
633 break;
634
635 default:
636 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
637 return false;
638 }
639
640 return true;
641}
642
643template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400644bool ValidateTexParameterBase(Context *context,
645 GLenum target,
646 GLenum pname,
647 GLsizei bufSize,
648 ParamType *params)
649{
650 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
651 {
652 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
653 return false;
654 }
655
656 if (context->getTargetTexture(target) == nullptr)
657 {
658 // Should only be possible for external textures
659 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
660 return false;
661 }
662
663 const GLsizei minBufSize = 1;
664 if (bufSize >= 0 && bufSize < minBufSize)
665 {
666 context->handleError(
667 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
668 return false;
669 }
670
671 switch (pname)
672 {
673 case GL_TEXTURE_WRAP_R:
674 case GL_TEXTURE_SWIZZLE_R:
675 case GL_TEXTURE_SWIZZLE_G:
676 case GL_TEXTURE_SWIZZLE_B:
677 case GL_TEXTURE_SWIZZLE_A:
678 case GL_TEXTURE_BASE_LEVEL:
679 case GL_TEXTURE_MAX_LEVEL:
680 case GL_TEXTURE_COMPARE_MODE:
681 case GL_TEXTURE_COMPARE_FUNC:
682 case GL_TEXTURE_MIN_LOD:
683 case GL_TEXTURE_MAX_LOD:
684 if (context->getClientMajorVersion() < 3)
685 {
686 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
687 return false;
688 }
689 if (target == GL_TEXTURE_EXTERNAL_OES &&
690 !context->getExtensions().eglImageExternalEssl3)
691 {
692 context->handleError(Error(GL_INVALID_ENUM,
693 "ES3 texture parameters are not available without "
694 "GL_OES_EGL_image_external_essl3."));
695 return false;
696 }
697 break;
698
699 default:
700 break;
701 }
702
703 switch (pname)
704 {
705 case GL_TEXTURE_WRAP_S:
706 case GL_TEXTURE_WRAP_T:
707 case GL_TEXTURE_WRAP_R:
708 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
709 {
710 return false;
711 }
712 break;
713
714 case GL_TEXTURE_MIN_FILTER:
715 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
716 {
717 return false;
718 }
719 break;
720
721 case GL_TEXTURE_MAG_FILTER:
722 if (!ValidateTextureMagFilterValue(context, params))
723 {
724 return false;
725 }
726 break;
727
728 case GL_TEXTURE_USAGE_ANGLE:
729 switch (ConvertToGLenum(params[0]))
730 {
731 case GL_NONE:
732 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
733 break;
734
735 default:
736 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
737 return false;
738 }
739 break;
740
741 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
742 if (!context->getExtensions().textureFilterAnisotropic)
743 {
744 context->handleError(
745 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
746 return false;
747 }
748
749 // we assume the parameter passed to this validation method is truncated, not rounded
750 if (params[0] < 1)
751 {
752 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
753 return false;
754 }
755 break;
756
757 case GL_TEXTURE_MIN_LOD:
758 case GL_TEXTURE_MAX_LOD:
759 // any value is permissible
760 break;
761
762 case GL_TEXTURE_COMPARE_MODE:
763 if (!ValidateTextureCompareModeValue(context, params))
764 {
765 return false;
766 }
767 break;
768
769 case GL_TEXTURE_COMPARE_FUNC:
770 if (!ValidateTextureCompareFuncValue(context, params))
771 {
772 return false;
773 }
774 break;
775
776 case GL_TEXTURE_SWIZZLE_R:
777 case GL_TEXTURE_SWIZZLE_G:
778 case GL_TEXTURE_SWIZZLE_B:
779 case GL_TEXTURE_SWIZZLE_A:
780 switch (ConvertToGLenum(params[0]))
781 {
782 case GL_RED:
783 case GL_GREEN:
784 case GL_BLUE:
785 case GL_ALPHA:
786 case GL_ZERO:
787 case GL_ONE:
788 break;
789
790 default:
791 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
792 return false;
793 }
794 break;
795
796 case GL_TEXTURE_BASE_LEVEL:
797 if (params[0] < 0)
798 {
799 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
800 return false;
801 }
802 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
803 {
804 context->handleError(
805 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
806 return false;
807 }
808 break;
809
810 case GL_TEXTURE_MAX_LEVEL:
811 if (params[0] < 0)
812 {
813 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
814 return false;
815 }
816 break;
817
Geoff Lang3b573612016-10-31 14:08:10 -0400818 case GL_DEPTH_STENCIL_TEXTURE_MODE:
819 if (context->getClientVersion() < Version(3, 1))
820 {
821 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
822 return false;
823 }
Geoff Lang9f090372016-12-02 10:20:43 -0500824 switch (ConvertToGLenum(params[0]))
825 {
826 case GL_DEPTH_COMPONENT:
827 case GL_STENCIL_INDEX:
828 break;
829
830 default:
831 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
832 return false;
833 }
Geoff Lang3b573612016-10-31 14:08:10 -0400834 break;
835
Geoff Lang81c6b572016-10-19 14:07:52 -0700836 case GL_TEXTURE_SRGB_DECODE_EXT:
837 if (!ValidateTextureSRGBDecodeValue(context, params))
838 {
839 return false;
840 }
841 break;
842
Geoff Langc1984ed2016-10-07 12:41:00 -0400843 default:
844 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
845 return false;
846 }
847
848 return true;
849}
850
851template <typename ParamType>
852bool ValidateSamplerParameterBase(Context *context,
853 GLuint sampler,
854 GLenum pname,
855 GLsizei bufSize,
856 ParamType *params)
857{
858 if (context->getClientMajorVersion() < 3)
859 {
860 context->handleError(
861 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
862 return false;
863 }
864
865 if (!context->isSampler(sampler))
866 {
867 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
868 return false;
869 }
870
871 const GLsizei minBufSize = 1;
872 if (bufSize >= 0 && bufSize < minBufSize)
873 {
874 context->handleError(
875 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
876 return false;
877 }
878
879 switch (pname)
880 {
881 case GL_TEXTURE_WRAP_S:
882 case GL_TEXTURE_WRAP_T:
883 case GL_TEXTURE_WRAP_R:
884 if (!ValidateTextureWrapModeValue(context, params, false))
885 {
886 return false;
887 }
888 break;
889
890 case GL_TEXTURE_MIN_FILTER:
891 if (!ValidateTextureMinFilterValue(context, params, false))
892 {
893 return false;
894 }
895 break;
896
897 case GL_TEXTURE_MAG_FILTER:
898 if (!ValidateTextureMagFilterValue(context, params))
899 {
900 return false;
901 }
902 break;
903
904 case GL_TEXTURE_MIN_LOD:
905 case GL_TEXTURE_MAX_LOD:
906 // any value is permissible
907 break;
908
909 case GL_TEXTURE_COMPARE_MODE:
910 if (!ValidateTextureCompareModeValue(context, params))
911 {
912 return false;
913 }
914 break;
915
916 case GL_TEXTURE_COMPARE_FUNC:
917 if (!ValidateTextureCompareFuncValue(context, params))
918 {
919 return false;
920 }
921 break;
922
Geoff Lang81c6b572016-10-19 14:07:52 -0700923 case GL_TEXTURE_SRGB_DECODE_EXT:
924 if (!ValidateTextureSRGBDecodeValue(context, params))
925 {
926 return false;
927 }
928 break;
929
Geoff Langc1984ed2016-10-07 12:41:00 -0400930 default:
931 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
932 return false;
933 }
934
935 return true;
936}
937
938bool ValidateGetSamplerParameterBase(Context *context,
939 GLuint sampler,
940 GLenum pname,
941 GLsizei *length)
942{
943 if (length)
944 {
945 *length = 0;
946 }
947
948 if (context->getClientMajorVersion() < 3)
949 {
950 context->handleError(
951 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
952 return false;
953 }
954
955 if (!context->isSampler(sampler))
956 {
957 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
958 return false;
959 }
960
961 switch (pname)
962 {
963 case GL_TEXTURE_WRAP_S:
964 case GL_TEXTURE_WRAP_T:
965 case GL_TEXTURE_WRAP_R:
966 case GL_TEXTURE_MIN_FILTER:
967 case GL_TEXTURE_MAG_FILTER:
968 case GL_TEXTURE_MIN_LOD:
969 case GL_TEXTURE_MAX_LOD:
970 case GL_TEXTURE_COMPARE_MODE:
971 case GL_TEXTURE_COMPARE_FUNC:
972 break;
973
Geoff Lang81c6b572016-10-19 14:07:52 -0700974 case GL_TEXTURE_SRGB_DECODE_EXT:
975 if (!context->getExtensions().textureSRGBDecode)
976 {
977 context->handleError(
978 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
979 return false;
980 }
981 break;
982
Geoff Langc1984ed2016-10-07 12:41:00 -0400983 default:
984 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
985 return false;
986 }
987
988 if (length)
989 {
990 *length = 1;
991 }
992 return true;
993}
994
Geoff Lang0b031062016-10-13 14:30:04 -0400995bool ValidateGetVertexAttribBase(Context *context,
996 GLuint index,
997 GLenum pname,
998 GLsizei *length,
999 bool pointer,
1000 bool pureIntegerEntryPoint)
1001{
1002 if (length)
1003 {
1004 *length = 0;
1005 }
1006
1007 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1008 {
1009 context->handleError(
1010 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1011 return false;
1012 }
1013
1014 if (index >= context->getCaps().maxVertexAttributes)
1015 {
1016 context->handleError(Error(
1017 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1018 return false;
1019 }
1020
1021 if (pointer)
1022 {
1023 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1024 {
1025 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1026 return false;
1027 }
1028 }
1029 else
1030 {
1031 switch (pname)
1032 {
1033 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1034 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1035 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1036 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1037 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1038 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1039 case GL_CURRENT_VERTEX_ATTRIB:
1040 break;
1041
1042 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1043 static_assert(
1044 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1045 "ANGLE extension enums not equal to GL enums.");
1046 if (context->getClientMajorVersion() < 3 &&
1047 !context->getExtensions().instancedArrays)
1048 {
1049 context->handleError(Error(GL_INVALID_ENUM,
1050 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1051 "3.0 or GL_ANGLE_instanced_arrays."));
1052 return false;
1053 }
1054 break;
1055
1056 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1057 if (context->getClientMajorVersion() < 3)
1058 {
1059 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1060 return false;
1061 }
1062 break;
1063
1064 default:
1065 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1066 return false;
1067 }
1068 }
1069
1070 if (length)
1071 {
1072 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1073 {
1074 *length = 4;
1075 }
1076 else
1077 {
1078 *length = 1;
1079 }
1080 }
1081
1082 return true;
1083}
1084
Geoff Lang6899b872016-10-14 11:30:13 -04001085bool ValidateGetActiveUniformBlockivBase(Context *context,
1086 GLuint program,
1087 GLuint uniformBlockIndex,
1088 GLenum pname,
1089 GLsizei *length)
1090{
1091 if (length)
1092 {
1093 *length = 0;
1094 }
1095
1096 if (context->getClientMajorVersion() < 3)
1097 {
1098 context->handleError(
1099 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1100 return false;
1101 }
1102
1103 Program *programObject = GetValidProgram(context, program);
1104 if (!programObject)
1105 {
1106 return false;
1107 }
1108
1109 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1110 {
1111 context->handleError(
1112 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1113 return false;
1114 }
1115
1116 switch (pname)
1117 {
1118 case GL_UNIFORM_BLOCK_BINDING:
1119 case GL_UNIFORM_BLOCK_DATA_SIZE:
1120 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1121 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1122 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1123 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1124 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1125 break;
1126
1127 default:
1128 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1129 return false;
1130 }
1131
1132 if (length)
1133 {
1134 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1135 {
1136 const UniformBlock &uniformBlock =
1137 programObject->getUniformBlockByIndex(uniformBlockIndex);
1138 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1139 }
1140 else
1141 {
1142 *length = 1;
1143 }
1144 }
1145
1146 return true;
1147}
1148
Geoff Langebebe1c2016-10-14 12:01:31 -04001149bool ValidateGetBufferParameterBase(ValidationContext *context,
1150 GLenum target,
1151 GLenum pname,
1152 bool pointerVersion,
1153 GLsizei *numParams)
1154{
1155 if (numParams)
1156 {
1157 *numParams = 0;
1158 }
1159
1160 if (!ValidBufferTarget(context, target))
1161 {
1162 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1163 return false;
1164 }
1165
1166 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1167 if (!buffer)
1168 {
1169 // A null buffer means that "0" is bound to the requested buffer target
1170 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1171 return false;
1172 }
1173
1174 const Extensions &extensions = context->getExtensions();
1175
1176 switch (pname)
1177 {
1178 case GL_BUFFER_USAGE:
1179 case GL_BUFFER_SIZE:
1180 break;
1181
1182 case GL_BUFFER_ACCESS_OES:
1183 if (!extensions.mapBuffer)
1184 {
1185 context->handleError(
1186 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1187 return false;
1188 }
1189 break;
1190
1191 case GL_BUFFER_MAPPED:
1192 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1193 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1194 !extensions.mapBufferRange)
1195 {
1196 context->handleError(Error(
1197 GL_INVALID_ENUM,
1198 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1199 return false;
1200 }
1201 break;
1202
1203 case GL_BUFFER_MAP_POINTER:
1204 if (!pointerVersion)
1205 {
1206 context->handleError(
1207 Error(GL_INVALID_ENUM,
1208 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1209 return false;
1210 }
1211 break;
1212
1213 case GL_BUFFER_ACCESS_FLAGS:
1214 case GL_BUFFER_MAP_OFFSET:
1215 case GL_BUFFER_MAP_LENGTH:
1216 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1217 {
1218 context->handleError(Error(
1219 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1220 return false;
1221 }
1222 break;
1223
1224 default:
1225 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1226 return false;
1227 }
1228
1229 // All buffer parameter queries return one value.
1230 if (numParams)
1231 {
1232 *numParams = 1;
1233 }
1234
1235 return true;
1236}
1237
Geoff Lang0a9661f2016-10-20 10:59:20 -07001238bool ValidateGetInternalFormativBase(Context *context,
1239 GLenum target,
1240 GLenum internalformat,
1241 GLenum pname,
1242 GLsizei bufSize,
1243 GLsizei *numParams)
1244{
1245 if (numParams)
1246 {
1247 *numParams = 0;
1248 }
1249
1250 if (context->getClientMajorVersion() < 3)
1251 {
1252 context->handleError(
1253 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1254 return false;
1255 }
1256
1257 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1258 if (!formatCaps.renderable)
1259 {
1260 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1261 return false;
1262 }
1263
1264 switch (target)
1265 {
1266 case GL_RENDERBUFFER:
1267 break;
1268
1269 default:
1270 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1271 return false;
1272 }
1273
1274 if (bufSize < 0)
1275 {
1276 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1277 return false;
1278 }
1279
1280 GLsizei maxWriteParams = 0;
1281 switch (pname)
1282 {
1283 case GL_NUM_SAMPLE_COUNTS:
1284 maxWriteParams = 1;
1285 break;
1286
1287 case GL_SAMPLES:
1288 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1289 break;
1290
1291 default:
1292 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1293 return false;
1294 }
1295
1296 if (numParams)
1297 {
1298 // glGetInternalFormativ will not overflow bufSize
1299 *numParams = std::min(bufSize, maxWriteParams);
1300 }
1301
1302 return true;
1303}
1304
Geoff Langf41a7152016-09-19 15:11:17 -04001305} // anonymous namespace
1306
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001307bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001308{
Jamie Madilld7460c72014-01-21 16:38:14 -05001309 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001310 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001311 case GL_TEXTURE_2D:
1312 case GL_TEXTURE_CUBE_MAP:
1313 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001314
He Yunchaoced53ae2016-11-29 15:00:51 +08001315 case GL_TEXTURE_3D:
1316 case GL_TEXTURE_2D_ARRAY:
1317 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001318
He Yunchaoced53ae2016-11-29 15:00:51 +08001319 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001320 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001321
He Yunchaoced53ae2016-11-29 15:00:51 +08001322 default:
1323 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001324 }
Jamie Madill35d15012013-10-07 10:46:37 -04001325}
1326
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001327bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1328{
1329 switch (target)
1330 {
1331 case GL_TEXTURE_2D:
1332 case GL_TEXTURE_CUBE_MAP:
1333 return true;
1334
1335 default:
1336 return false;
1337 }
1338}
1339
1340bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1341{
1342 switch (target)
1343 {
1344 case GL_TEXTURE_3D:
1345 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001346 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001347
1348 default:
1349 return false;
1350 }
1351}
1352
Ian Ewellbda75592016-04-18 17:25:54 -04001353// Most texture GL calls are not compatible with external textures, so we have a separate validation
1354// function for use in the GL calls that do
1355bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1356{
1357 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1358 (context->getExtensions().eglImageExternal ||
1359 context->getExtensions().eglStreamConsumerExternal);
1360}
1361
Shannon Woods4dfed832014-03-17 20:03:39 -04001362// This function differs from ValidTextureTarget in that the target must be
1363// usable as the destination of a 2D operation-- so a cube face is valid, but
1364// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001365// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001366bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001367{
1368 switch (target)
1369 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001370 case GL_TEXTURE_2D:
1371 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1372 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1373 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1374 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1375 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1376 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1377 return true;
1378 default:
1379 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001380 }
1381}
1382
1383bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1384{
1385 switch (target)
1386 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001387 case GL_TEXTURE_3D:
1388 case GL_TEXTURE_2D_ARRAY:
1389 return true;
1390 default:
1391 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001392 }
1393}
1394
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001395bool ValidFramebufferTarget(GLenum target)
1396{
He Yunchaoced53ae2016-11-29 15:00:51 +08001397 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1398 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001399 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001400
1401 switch (target)
1402 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001403 case GL_FRAMEBUFFER:
1404 return true;
1405 case GL_READ_FRAMEBUFFER:
1406 return true;
1407 case GL_DRAW_FRAMEBUFFER:
1408 return true;
1409 default:
1410 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001411 }
1412}
1413
Jamie Madill29639852016-09-02 15:00:09 -04001414bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001415{
1416 switch (target)
1417 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001418 case GL_ARRAY_BUFFER:
1419 case GL_ELEMENT_ARRAY_BUFFER:
1420 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001421
He Yunchaoced53ae2016-11-29 15:00:51 +08001422 case GL_PIXEL_PACK_BUFFER:
1423 case GL_PIXEL_UNPACK_BUFFER:
1424 return (context->getExtensions().pixelBufferObject ||
1425 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001426
He Yunchaoced53ae2016-11-29 15:00:51 +08001427 case GL_COPY_READ_BUFFER:
1428 case GL_COPY_WRITE_BUFFER:
1429 case GL_TRANSFORM_FEEDBACK_BUFFER:
1430 case GL_UNIFORM_BUFFER:
1431 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001432
He Yunchaoced53ae2016-11-29 15:00:51 +08001433 case GL_ATOMIC_COUNTER_BUFFER:
1434 case GL_SHADER_STORAGE_BUFFER:
1435 case GL_DRAW_INDIRECT_BUFFER:
1436 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001437 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001438
He Yunchaoced53ae2016-11-29 15:00:51 +08001439 default:
1440 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001441 }
1442}
1443
Jamie Madillc29968b2016-01-20 11:17:23 -05001444bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001445{
Jamie Madillc29968b2016-01-20 11:17:23 -05001446 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001447 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001448 switch (target)
1449 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001450 case GL_TEXTURE_2D:
1451 maxDimension = caps.max2DTextureSize;
1452 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001453 case GL_TEXTURE_CUBE_MAP:
1454 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1455 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1456 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1457 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1458 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1459 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1460 maxDimension = caps.maxCubeMapTextureSize;
1461 break;
1462 case GL_TEXTURE_3D:
1463 maxDimension = caps.max3DTextureSize;
1464 break;
1465 case GL_TEXTURE_2D_ARRAY:
1466 maxDimension = caps.max2DTextureSize;
1467 break;
1468 default:
1469 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001470 }
1471
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001472 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001473}
1474
Austin Kinross08528e12015-10-07 16:24:40 -07001475bool ValidImageSizeParameters(const Context *context,
1476 GLenum target,
1477 GLint level,
1478 GLsizei width,
1479 GLsizei height,
1480 GLsizei depth,
1481 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001482{
1483 if (level < 0 || width < 0 || height < 0 || depth < 0)
1484 {
1485 return false;
1486 }
1487
Austin Kinross08528e12015-10-07 16:24:40 -07001488 // TexSubImage parameters can be NPOT without textureNPOT extension,
1489 // as long as the destination texture is POT.
1490 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001491 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001492 {
1493 return false;
1494 }
1495
1496 if (!ValidMipLevel(context, target, level))
1497 {
1498 return false;
1499 }
1500
1501 return true;
1502}
1503
Geoff Lang0d8b7242015-09-09 14:56:53 -04001504bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1505{
1506 // List of compressed format that require that the texture size is smaller than or a multiple of
1507 // the compressed block size.
1508 switch (internalFormat)
1509 {
1510 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1511 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1512 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1513 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001514 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001515 return true;
1516
1517 default:
1518 return false;
1519 }
1520}
1521
Jamie Madillc29968b2016-01-20 11:17:23 -05001522bool ValidCompressedImageSize(const ValidationContext *context,
1523 GLenum internalFormat,
1524 GLsizei width,
1525 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001526{
Geoff Lang5d601382014-07-22 15:14:06 -04001527 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1528 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001529 {
1530 return false;
1531 }
1532
Geoff Lang0d8b7242015-09-09 14:56:53 -04001533 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001534 {
1535 return false;
1536 }
1537
Geoff Lang0d8b7242015-09-09 14:56:53 -04001538 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1539 {
1540 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1541 width % formatInfo.compressedBlockWidth != 0) ||
1542 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1543 height % formatInfo.compressedBlockHeight != 0))
1544 {
1545 return false;
1546 }
1547 }
1548
Geoff Langd4f180b2013-09-24 13:57:44 -04001549 return true;
1550}
1551
Geoff Langff5b2d52016-09-07 11:32:23 -04001552bool ValidImageDataSize(ValidationContext *context,
1553 GLenum textureTarget,
1554 GLsizei width,
1555 GLsizei height,
1556 GLsizei depth,
1557 GLenum internalFormat,
1558 GLenum type,
1559 const GLvoid *pixels,
1560 GLsizei imageSize)
1561{
1562 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1563 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1564 {
1565 // Checks are not required
1566 return true;
1567 }
1568
1569 // ...the data would be unpacked from the buffer object such that the memory reads required
1570 // would exceed the data store size.
1571 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1572 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1573 const gl::Extents size(width, height, depth);
1574 const auto &unpack = context->getGLState().getUnpackState();
1575
1576 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1577 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1578 if (endByteOrErr.isError())
1579 {
1580 context->handleError(endByteOrErr.getError());
1581 return false;
1582 }
1583
1584 GLuint endByte = endByteOrErr.getResult();
1585
1586 if (pixelUnpackBuffer)
1587 {
1588 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1589 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1590 checkedEndByte += checkedOffset;
1591
1592 if (!checkedEndByte.IsValid() ||
1593 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1594 {
1595 // Overflow past the end of the buffer
1596 context->handleError(Error(GL_INVALID_OPERATION));
1597 return false;
1598 }
1599 }
1600 else
1601 {
1602 ASSERT(imageSize >= 0);
1603 if (pixels == nullptr && imageSize != 0)
1604 {
1605 context->handleError(
1606 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001607 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001608 }
1609
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001610 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001611 {
1612 context->handleError(
1613 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1614 return false;
1615 }
1616 }
1617
1618 return true;
1619}
1620
Geoff Lang37dde692014-01-31 16:34:54 -05001621bool ValidQueryType(const Context *context, GLenum queryType)
1622{
He Yunchaoced53ae2016-11-29 15:00:51 +08001623 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1624 "GL extension enums not equal.");
1625 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1626 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001627
1628 switch (queryType)
1629 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001630 case GL_ANY_SAMPLES_PASSED:
1631 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1632 return true;
1633 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1634 return (context->getClientMajorVersion() >= 3);
1635 case GL_TIME_ELAPSED_EXT:
1636 return context->getExtensions().disjointTimerQuery;
1637 case GL_COMMANDS_COMPLETED_CHROMIUM:
1638 return context->getExtensions().syncQuery;
1639 default:
1640 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001641 }
1642}
1643
Jamie Madillef300b12016-10-07 15:12:09 -04001644Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001645{
He Yunchaoced53ae2016-11-29 15:00:51 +08001646 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1647 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1648 // or program object and INVALID_OPERATION if the provided name identifies an object
1649 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001650
Dian Xiang769769a2015-09-09 15:20:08 -07001651 Program *validProgram = context->getProgram(id);
1652
1653 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001654 {
Dian Xiang769769a2015-09-09 15:20:08 -07001655 if (context->getShader(id))
1656 {
Jamie Madill437fa652016-05-03 15:13:24 -04001657 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001658 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1659 }
1660 else
1661 {
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001663 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001664 }
Dian Xiang769769a2015-09-09 15:20:08 -07001665
1666 return validProgram;
1667}
1668
Jamie Madillef300b12016-10-07 15:12:09 -04001669Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001670{
1671 // See ValidProgram for spec details.
1672
1673 Shader *validShader = context->getShader(id);
1674
1675 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001676 {
Dian Xiang769769a2015-09-09 15:20:08 -07001677 if (context->getProgram(id))
1678 {
Jamie Madill437fa652016-05-03 15:13:24 -04001679 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001680 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1681 }
1682 else
1683 {
Jamie Madill437fa652016-05-03 15:13:24 -04001684 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001685 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001686 }
Dian Xiang769769a2015-09-09 15:20:08 -07001687
1688 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001689}
1690
Geoff Langb1196682014-07-23 13:47:29 -04001691bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001692{
1693 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1694 {
1695 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1696
Geoff Langaae65a42014-05-26 12:43:44 -04001697 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001698 {
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001700 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001701 }
1702 }
1703 else
1704 {
1705 switch (attachment)
1706 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001707 case GL_DEPTH_ATTACHMENT:
1708 case GL_STENCIL_ATTACHMENT:
1709 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001710
He Yunchaoced53ae2016-11-29 15:00:51 +08001711 case GL_DEPTH_STENCIL_ATTACHMENT:
1712 if (!context->getExtensions().webglCompatibility &&
1713 context->getClientMajorVersion() < 3)
1714 {
1715 context->handleError(Error(GL_INVALID_ENUM));
1716 return false;
1717 }
1718 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001719
He Yunchaoced53ae2016-11-29 15:00:51 +08001720 default:
1721 context->handleError(Error(GL_INVALID_ENUM));
1722 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001723 }
1724 }
1725
1726 return true;
1727}
1728
He Yunchaoced53ae2016-11-29 15:00:51 +08001729bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1730 GLenum target,
1731 GLsizei samples,
1732 GLenum internalformat,
1733 GLsizei width,
1734 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735{
1736 switch (target)
1737 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001738 case GL_RENDERBUFFER:
1739 break;
1740 default:
1741 context->handleError(Error(GL_INVALID_ENUM));
1742 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001743 }
1744
1745 if (width < 0 || height < 0 || samples < 0)
1746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001748 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001749 }
1750
Geoff Langd87878e2014-09-19 15:42:59 -04001751 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1752 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 {
Jamie Madill437fa652016-05-03 15:13:24 -04001754 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001755 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001756 }
1757
1758 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1759 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001760 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001761 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001762 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001766 }
1767
Geoff Langaae65a42014-05-26 12:43:44 -04001768 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001769 {
Jamie Madill437fa652016-05-03 15:13:24 -04001770 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001771 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001772 }
1773
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001774 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 if (handle == 0)
1776 {
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001778 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001779 }
1780
1781 return true;
1782}
1783
He Yunchaoced53ae2016-11-29 15:00:51 +08001784bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1785 GLenum target,
1786 GLsizei samples,
1787 GLenum internalformat,
1788 GLsizei width,
1789 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001790{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001791 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001792
1793 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001794 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001795 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001796 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001799 return false;
1800 }
1801
1802 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1803 // the specified storage. This is different than ES 3.0 in which a sample number higher
1804 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001805 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001806 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001807 {
Geoff Langa4903b72015-03-02 16:02:48 -08001808 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1809 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1810 {
Jamie Madill437fa652016-05-03 15:13:24 -04001811 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001812 return false;
1813 }
Corentin Walleze0902642014-11-04 12:32:15 -08001814 }
1815
He Yunchaoced53ae2016-11-29 15:00:51 +08001816 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1817 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001818}
1819
He Yunchaoced53ae2016-11-29 15:00:51 +08001820bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1821 GLenum target,
1822 GLenum attachment,
1823 GLenum renderbuffertarget,
1824 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001825{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001826 if (!ValidFramebufferTarget(target))
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001830 }
1831
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001832 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001833
Jamie Madill84115c92015-04-23 15:00:07 -04001834 ASSERT(framebuffer);
1835 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(
1838 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001839 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001840 }
1841
Jamie Madillb4472272014-07-03 10:38:55 -04001842 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001843 {
Jamie Madillb4472272014-07-03 10:38:55 -04001844 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001845 }
1846
Jamie Madillab9d82c2014-01-21 16:38:14 -05001847 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1848 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1849 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1850 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1851 if (renderbuffer != 0)
1852 {
1853 if (!context->getRenderbuffer(renderbuffer))
1854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001857 }
1858 }
1859
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001860 return true;
1861}
1862
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001863bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 GLint srcX0,
1865 GLint srcY0,
1866 GLint srcX1,
1867 GLint srcY1,
1868 GLint dstX0,
1869 GLint dstY0,
1870 GLint dstX1,
1871 GLint dstY1,
1872 GLbitfield mask,
1873 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001874{
1875 switch (filter)
1876 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001877 case GL_NEAREST:
1878 break;
1879 case GL_LINEAR:
1880 break;
1881 default:
1882 context->handleError(Error(GL_INVALID_ENUM));
1883 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001884 }
1885
1886 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1887 {
Jamie Madill437fa652016-05-03 15:13:24 -04001888 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001889 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001890 }
1891
1892 if (mask == 0)
1893 {
1894 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1895 // buffers are copied.
1896 return false;
1897 }
1898
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001899 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1900 // color buffer, leaving only nearest being unfiltered from above
1901 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001904 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001905 }
1906
Jamie Madill51f40ec2016-06-15 14:06:00 -04001907 const auto &glState = context->getGLState();
1908 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1909 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001910
1911 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001912 {
Jamie Madill437fa652016-05-03 15:13:24 -04001913 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001914 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001915 }
1916
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001917 if (readFramebuffer->id() == drawFramebuffer->id())
1918 {
1919 context->handleError(Error(GL_INVALID_OPERATION));
1920 return false;
1921 }
1922
Jamie Madill51f40ec2016-06-15 14:06:00 -04001923 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001926 return false;
1927 }
1928
Jamie Madill51f40ec2016-06-15 14:06:00 -04001929 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001930 {
Jamie Madill437fa652016-05-03 15:13:24 -04001931 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001932 return false;
1933 }
1934
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001935 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001939 }
1940
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001941 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1942
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001943 if (mask & GL_COLOR_BUFFER_BIT)
1944 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001945 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1946 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001947 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001948
1949 if (readColorBuffer && drawColorBuffer)
1950 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001951 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001952
Geoff Langa15472a2015-08-11 11:48:03 -04001953 for (size_t drawbufferIdx = 0;
1954 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955 {
Geoff Langa15472a2015-08-11 11:48:03 -04001956 const FramebufferAttachment *attachment =
1957 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1958 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001959 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001960 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961
Geoff Langb2f3d052013-08-13 12:49:27 -04001962 // The GL ES 3.0.2 spec (pg 193) states that:
1963 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001964 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1965 // as well
1966 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1967 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001968 // Changes with EXT_color_buffer_float:
1969 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001970 GLenum readComponentType = readFormat.info->componentType;
1971 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001972 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001973 readComponentType == GL_SIGNED_NORMALIZED);
1974 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1975 drawComponentType == GL_SIGNED_NORMALIZED);
1976
1977 if (extensions.colorBufferFloat)
1978 {
1979 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1980 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1981
1982 if (readFixedOrFloat != drawFixedOrFloat)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001985 "If the read buffer contains fixed-point or "
1986 "floating-point values, the draw buffer "
1987 "must as well."));
1988 return false;
1989 }
1990 }
1991 else if (readFixedPoint != drawFixedPoint)
1992 {
Jamie Madill437fa652016-05-03 15:13:24 -04001993 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001994 "If the read buffer contains fixed-point "
1995 "values, the draw buffer must as well."));
1996 return false;
1997 }
1998
1999 if (readComponentType == GL_UNSIGNED_INT &&
2000 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002001 {
Jamie Madill437fa652016-05-03 15:13:24 -04002002 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002003 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002004 }
2005
Jamie Madill6163c752015-12-07 16:32:59 -05002006 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002009 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002010 }
2011
Jamie Madilla3944d42016-07-22 22:13:26 -04002012 if (readColorBuffer->getSamples() > 0 &&
2013 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002016 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002017 }
2018 }
2019 }
2020
Jamie Madilla3944d42016-07-22 22:13:26 -04002021 if ((readFormat.info->componentType == GL_INT ||
2022 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2023 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002024 {
Jamie Madill437fa652016-05-03 15:13:24 -04002025 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002026 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002027 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002028 }
2029 }
2030
He Yunchaoced53ae2016-11-29 15:00:51 +08002031 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002032 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2033 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002034 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002035 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002036 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002037 const gl::FramebufferAttachment *readBuffer =
2038 readFramebuffer->getAttachment(attachments[i]);
2039 const gl::FramebufferAttachment *drawBuffer =
2040 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002041
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002042 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002043 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002044 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002047 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002048 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002049
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002050 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002054 }
2055 }
2056 }
2057 }
2058
2059 return true;
2060}
2061
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002062bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002063 GLint x,
2064 GLint y,
2065 GLsizei width,
2066 GLsizei height,
2067 GLenum format,
2068 GLenum type,
2069 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002070{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002071 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2072}
2073
2074bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2075 GLint x,
2076 GLint y,
2077 GLsizei width,
2078 GLsizei height,
2079 GLenum format,
2080 GLenum type,
2081 GLsizei bufSize,
2082 GLsizei *length,
2083 GLvoid *pixels)
2084{
2085 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002086 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002087 return false;
2088 }
2089
Geoff Lang62fce5b2016-09-30 10:46:35 -04002090 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2091 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002092 {
Geoff Langb1196682014-07-23 13:47:29 -04002093 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002094 }
2095
Geoff Lang62fce5b2016-09-30 10:46:35 -04002096 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002097 {
Geoff Langb1196682014-07-23 13:47:29 -04002098 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002099 }
2100
Jamie Madillc29968b2016-01-20 11:17:23 -05002101 return true;
2102}
2103
2104bool ValidateReadnPixelsEXT(Context *context,
2105 GLint x,
2106 GLint y,
2107 GLsizei width,
2108 GLsizei height,
2109 GLenum format,
2110 GLenum type,
2111 GLsizei bufSize,
2112 GLvoid *pixels)
2113{
2114 if (bufSize < 0)
2115 {
Jamie Madill437fa652016-05-03 15:13:24 -04002116 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002117 return false;
2118 }
2119
Geoff Lang62fce5b2016-09-30 10:46:35 -04002120 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2121 pixels);
2122}
Jamie Madill26e91952014-03-05 15:01:27 -05002123
Geoff Lang62fce5b2016-09-30 10:46:35 -04002124bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2125 GLint x,
2126 GLint y,
2127 GLsizei width,
2128 GLsizei height,
2129 GLenum format,
2130 GLenum type,
2131 GLsizei bufSize,
2132 GLsizei *length,
2133 GLvoid *data)
2134{
2135 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002136 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002137 return false;
2138 }
2139
Geoff Lang62fce5b2016-09-30 10:46:35 -04002140 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002141 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002142 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002143 }
2144
Geoff Lang62fce5b2016-09-30 10:46:35 -04002145 if (!ValidateRobustBufferSize(context, bufSize, *length))
2146 {
2147 return false;
2148 }
2149
2150 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002151}
2152
Olli Etuaho41997e72016-03-10 13:38:39 +02002153bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002154{
2155 if (!context->getExtensions().occlusionQueryBoolean &&
2156 !context->getExtensions().disjointTimerQuery)
2157 {
Jamie Madill437fa652016-05-03 15:13:24 -04002158 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002159 return false;
2160 }
2161
Olli Etuaho41997e72016-03-10 13:38:39 +02002162 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002163}
2164
Olli Etuaho41997e72016-03-10 13:38:39 +02002165bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002166{
2167 if (!context->getExtensions().occlusionQueryBoolean &&
2168 !context->getExtensions().disjointTimerQuery)
2169 {
Jamie Madill437fa652016-05-03 15:13:24 -04002170 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002171 return false;
2172 }
2173
Olli Etuaho41997e72016-03-10 13:38:39 +02002174 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002175}
2176
2177bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002178{
2179 if (!ValidQueryType(context, target))
2180 {
Jamie Madill437fa652016-05-03 15:13:24 -04002181 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002182 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002183 }
2184
2185 if (id == 0)
2186 {
Jamie Madill437fa652016-05-03 15:13:24 -04002187 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002189 }
2190
2191 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2192 // of zero, if the active query object name for <target> is non-zero (for the
2193 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2194 // the active query for either target is non-zero), if <id> is the name of an
2195 // existing query object whose type does not match <target>, or if <id> is the
2196 // active query object name for any query type, the error INVALID_OPERATION is
2197 // generated.
2198
2199 // Ensure no other queries are active
2200 // NOTE: If other queries than occlusion are supported, we will need to check
2201 // separately that:
2202 // a) The query ID passed is not the current active query for any target/type
2203 // b) There are no active queries for the requested target (and in the case
2204 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2205 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002206
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002207 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002211 }
2212
2213 Query *queryObject = context->getQuery(id, true, target);
2214
2215 // check that name was obtained with glGenQueries
2216 if (!queryObject)
2217 {
Jamie Madill437fa652016-05-03 15:13:24 -04002218 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002219 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002220 }
2221
2222 // check for type mismatch
2223 if (queryObject->getType() != target)
2224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002226 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002227 }
2228
2229 return true;
2230}
2231
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002232bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2233{
2234 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002235 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002236 {
Jamie Madill437fa652016-05-03 15:13:24 -04002237 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002238 return false;
2239 }
2240
2241 return ValidateBeginQueryBase(context, target, id);
2242}
2243
2244bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002245{
2246 if (!ValidQueryType(context, target))
2247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002249 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002250 }
2251
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002252 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002253
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002254 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002255 {
Jamie Madill437fa652016-05-03 15:13:24 -04002256 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002257 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002258 }
2259
Jamie Madill45c785d2014-05-13 14:09:34 -04002260 return true;
2261}
2262
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002263bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2264{
2265 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002266 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002267 {
Jamie Madill437fa652016-05-03 15:13:24 -04002268 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002269 return false;
2270 }
2271
2272 return ValidateEndQueryBase(context, target);
2273}
2274
2275bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2276{
2277 if (!context->getExtensions().disjointTimerQuery)
2278 {
Jamie Madill437fa652016-05-03 15:13:24 -04002279 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280 return false;
2281 }
2282
2283 if (target != GL_TIMESTAMP_EXT)
2284 {
Jamie Madill437fa652016-05-03 15:13:24 -04002285 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002286 return false;
2287 }
2288
2289 Query *queryObject = context->getQuery(id, true, target);
2290 if (queryObject == nullptr)
2291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
2295
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002296 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002297 {
Jamie Madill437fa652016-05-03 15:13:24 -04002298 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002299 return false;
2300 }
2301
2302 return true;
2303}
2304
Geoff Lang2186c382016-10-14 10:54:54 -04002305bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002306{
Geoff Lang2186c382016-10-14 10:54:54 -04002307 if (numParams)
2308 {
2309 *numParams = 0;
2310 }
2311
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002312 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2313 {
Jamie Madill437fa652016-05-03 15:13:24 -04002314 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002315 return false;
2316 }
2317
2318 switch (pname)
2319 {
2320 case GL_CURRENT_QUERY_EXT:
2321 if (target == GL_TIMESTAMP_EXT)
2322 {
Jamie Madill437fa652016-05-03 15:13:24 -04002323 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002324 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2325 return false;
2326 }
2327 break;
2328 case GL_QUERY_COUNTER_BITS_EXT:
2329 if (!context->getExtensions().disjointTimerQuery ||
2330 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2331 {
Jamie Madill437fa652016-05-03 15:13:24 -04002332 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002333 return false;
2334 }
2335 break;
2336 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002337 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002338 return false;
2339 }
2340
Geoff Lang2186c382016-10-14 10:54:54 -04002341 if (numParams)
2342 {
2343 // All queries return only one value
2344 *numParams = 1;
2345 }
2346
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002347 return true;
2348}
2349
2350bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2351{
2352 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002353 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002354 {
Jamie Madill437fa652016-05-03 15:13:24 -04002355 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002356 return false;
2357 }
2358
Geoff Lang2186c382016-10-14 10:54:54 -04002359 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002360}
2361
Geoff Lang2186c382016-10-14 10:54:54 -04002362bool ValidateGetQueryivRobustANGLE(Context *context,
2363 GLenum target,
2364 GLenum pname,
2365 GLsizei bufSize,
2366 GLsizei *length,
2367 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368{
Geoff Lang2186c382016-10-14 10:54:54 -04002369 if (!ValidateRobustEntryPoint(context, bufSize))
2370 {
2371 return false;
2372 }
2373
2374 if (!ValidateGetQueryivBase(context, target, pname, length))
2375 {
2376 return false;
2377 }
2378
2379 if (!ValidateRobustBufferSize(context, bufSize, *length))
2380 {
2381 return false;
2382 }
2383
2384 return true;
2385}
2386
2387bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2388{
2389 if (numParams)
2390 {
2391 *numParams = 0;
2392 }
2393
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002394 Query *queryObject = context->getQuery(id, false, GL_NONE);
2395
2396 if (!queryObject)
2397 {
Jamie Madill437fa652016-05-03 15:13:24 -04002398 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002399 return false;
2400 }
2401
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002402 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002403 {
Jamie Madill437fa652016-05-03 15:13:24 -04002404 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002405 return false;
2406 }
2407
2408 switch (pname)
2409 {
2410 case GL_QUERY_RESULT_EXT:
2411 case GL_QUERY_RESULT_AVAILABLE_EXT:
2412 break;
2413
2414 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002415 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002416 return false;
2417 }
2418
Geoff Lang2186c382016-10-14 10:54:54 -04002419 if (numParams)
2420 {
2421 *numParams = 1;
2422 }
2423
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002424 return true;
2425}
2426
2427bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2428{
2429 if (!context->getExtensions().disjointTimerQuery)
2430 {
Jamie Madill437fa652016-05-03 15:13:24 -04002431 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002432 return false;
2433 }
Geoff Lang2186c382016-10-14 10:54:54 -04002434 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2435}
2436
2437bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2438 GLuint id,
2439 GLenum pname,
2440 GLsizei bufSize,
2441 GLsizei *length,
2442 GLint *params)
2443{
2444 if (!context->getExtensions().disjointTimerQuery)
2445 {
2446 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2447 return false;
2448 }
2449
2450 if (!ValidateRobustEntryPoint(context, bufSize))
2451 {
2452 return false;
2453 }
2454
2455 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2456 {
2457 return false;
2458 }
2459
2460 if (!ValidateRobustBufferSize(context, bufSize, *length))
2461 {
2462 return false;
2463 }
2464
2465 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002466}
2467
2468bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2469{
2470 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002471 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002472 {
Jamie Madill437fa652016-05-03 15:13:24 -04002473 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002474 return false;
2475 }
Geoff Lang2186c382016-10-14 10:54:54 -04002476 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2477}
2478
2479bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2480 GLuint id,
2481 GLenum pname,
2482 GLsizei bufSize,
2483 GLsizei *length,
2484 GLuint *params)
2485{
2486 if (!context->getExtensions().disjointTimerQuery &&
2487 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2488 {
2489 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2490 return false;
2491 }
2492
2493 if (!ValidateRobustEntryPoint(context, bufSize))
2494 {
2495 return false;
2496 }
2497
2498 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2499 {
2500 return false;
2501 }
2502
2503 if (!ValidateRobustBufferSize(context, bufSize, *length))
2504 {
2505 return false;
2506 }
2507
2508 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002509}
2510
2511bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2512{
2513 if (!context->getExtensions().disjointTimerQuery)
2514 {
Jamie Madill437fa652016-05-03 15:13:24 -04002515 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002516 return false;
2517 }
Geoff Lang2186c382016-10-14 10:54:54 -04002518 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2519}
2520
2521bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2522 GLuint id,
2523 GLenum pname,
2524 GLsizei bufSize,
2525 GLsizei *length,
2526 GLint64 *params)
2527{
2528 if (!context->getExtensions().disjointTimerQuery)
2529 {
2530 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2531 return false;
2532 }
2533
2534 if (!ValidateRobustEntryPoint(context, bufSize))
2535 {
2536 return false;
2537 }
2538
2539 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2540 {
2541 return false;
2542 }
2543
2544 if (!ValidateRobustBufferSize(context, bufSize, *length))
2545 {
2546 return false;
2547 }
2548
2549 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002550}
2551
2552bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2553{
2554 if (!context->getExtensions().disjointTimerQuery)
2555 {
Jamie Madill437fa652016-05-03 15:13:24 -04002556 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002557 return false;
2558 }
Geoff Lang2186c382016-10-14 10:54:54 -04002559 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2560}
2561
2562bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2563 GLuint id,
2564 GLenum pname,
2565 GLsizei bufSize,
2566 GLsizei *length,
2567 GLuint64 *params)
2568{
2569 if (!context->getExtensions().disjointTimerQuery)
2570 {
2571 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2572 return false;
2573 }
2574
2575 if (!ValidateRobustEntryPoint(context, bufSize))
2576 {
2577 return false;
2578 }
2579
2580 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2581 {
2582 return false;
2583 }
2584
2585 if (!ValidateRobustBufferSize(context, bufSize, *length))
2586 {
2587 return false;
2588 }
2589
2590 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002591}
2592
Jamie Madill62d31cb2015-09-11 13:25:51 -04002593static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002594 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002595 GLenum targetUniformType,
2596 GLint location,
2597 GLsizei count,
2598 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002599{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002600 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002601 if (count < 0)
2602 {
Jamie Madill437fa652016-05-03 15:13:24 -04002603 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002604 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002605 }
2606
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002607 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002608 {
Jamie Madill437fa652016-05-03 15:13:24 -04002609 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002610 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002611 }
2612
Geoff Langd8605522016-04-13 10:19:12 -04002613 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002614 {
2615 // Silently ignore the uniform command
2616 return false;
2617 }
2618
Geoff Lang7dd2e102014-11-10 15:19:26 -05002619 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002620 {
Jamie Madill437fa652016-05-03 15:13:24 -04002621 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002623 }
2624
Jamie Madill62d31cb2015-09-11 13:25:51 -04002625 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002626
2627 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002628 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002629 {
Jamie Madill437fa652016-05-03 15:13:24 -04002630 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002631 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002632 }
2633
Jamie Madill62d31cb2015-09-11 13:25:51 -04002634 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002635 return true;
2636}
2637
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002638bool ValidateProgramUniform(gl::Context *context,
2639 GLenum uniformType,
2640 GLuint program,
2641 GLint location,
2642 GLsizei count)
2643{
2644 // Check for ES31 program uniform entry points
2645 if (context->getClientVersion() < Version(3, 1))
2646 {
2647 context->handleError(Error(GL_INVALID_OPERATION));
2648 return false;
2649 }
2650
2651 const LinkedUniform *uniform = nullptr;
2652 gl::Program *programObject = GetValidProgram(context, program);
2653 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2654 {
2655 return false;
2656 }
2657
2658 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2659 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2660 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2661 {
2662 context->handleError(Error(GL_INVALID_OPERATION));
2663 return false;
2664 }
2665
2666 return true;
2667}
2668
2669bool ValidateProgramUniformMatrix(gl::Context *context,
2670 GLenum matrixType,
2671 GLuint program,
2672 GLint location,
2673 GLsizei count,
2674 GLboolean transpose)
2675{
2676 // Check for ES31 program uniform entry points
2677 if (context->getClientVersion() < Version(3, 1))
2678 {
2679 context->handleError(Error(GL_INVALID_OPERATION));
2680 return false;
2681 }
2682
2683 const LinkedUniform *uniform = nullptr;
2684 gl::Program *programObject = GetValidProgram(context, program);
2685 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2686 {
2687 return false;
2688 }
2689
2690 if (uniform->type != matrixType)
2691 {
2692 context->handleError(Error(GL_INVALID_OPERATION));
2693 return false;
2694 }
2695
2696 return true;
2697}
2698
Jamie Madillaa981bd2014-05-20 10:55:55 -04002699bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2700{
2701 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002702 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2703 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002704 {
Jamie Madill437fa652016-05-03 15:13:24 -04002705 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002707 }
2708
Jamie Madill62d31cb2015-09-11 13:25:51 -04002709 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002710 gl::Program *program = context->getGLState().getProgram();
2711 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002712 {
2713 return false;
2714 }
2715
He Yunchaoced53ae2016-11-29 15:00:51 +08002716 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002717 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002718 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2719 {
Jamie Madill437fa652016-05-03 15:13:24 -04002720 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002721 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002722 }
2723
2724 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002725}
2726
He Yunchaoced53ae2016-11-29 15:00:51 +08002727bool ValidateUniformMatrix(gl::Context *context,
2728 GLenum matrixType,
2729 GLint location,
2730 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002731 GLboolean transpose)
2732{
2733 // Check for ES3 uniform entry points
2734 int rows = VariableRowCount(matrixType);
2735 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002736 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002737 {
Jamie Madill437fa652016-05-03 15:13:24 -04002738 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002739 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002740 }
2741
Martin Radev1be913c2016-07-11 17:59:16 +03002742 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002746 }
2747
Jamie Madill62d31cb2015-09-11 13:25:51 -04002748 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002749 gl::Program *program = context->getGLState().getProgram();
2750 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002751 {
2752 return false;
2753 }
2754
2755 if (uniform->type != matrixType)
2756 {
Jamie Madill437fa652016-05-03 15:13:24 -04002757 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002758 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002759 }
2760
2761 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002762}
2763
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002764bool ValidateStateQuery(ValidationContext *context,
2765 GLenum pname,
2766 GLenum *nativeType,
2767 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002768{
2769 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2770 {
Jamie Madill437fa652016-05-03 15:13:24 -04002771 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002772 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002773 }
2774
Jamie Madill0af26e12015-03-05 19:54:33 -05002775 const Caps &caps = context->getCaps();
2776
Jamie Madill893ab082014-05-16 16:56:10 -04002777 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2778 {
2779 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2780
Jamie Madill0af26e12015-03-05 19:54:33 -05002781 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002782 {
Jamie Madill437fa652016-05-03 15:13:24 -04002783 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002784 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002785 }
2786 }
2787
2788 switch (pname)
2789 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002790 case GL_TEXTURE_BINDING_2D:
2791 case GL_TEXTURE_BINDING_CUBE_MAP:
2792 case GL_TEXTURE_BINDING_3D:
2793 case GL_TEXTURE_BINDING_2D_ARRAY:
2794 break;
2795 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2796 if (!context->getExtensions().eglStreamConsumerExternal &&
2797 !context->getExtensions().eglImageExternal)
2798 {
2799 context->handleError(Error(GL_INVALID_ENUM,
2800 "Neither NV_EGL_stream_consumer_external nor "
2801 "GL_OES_EGL_image_external extensions enabled"));
2802 return false;
2803 }
2804 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002805
He Yunchaoced53ae2016-11-29 15:00:51 +08002806 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2807 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002808 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002809 if (context->getGLState().getReadFramebuffer()->checkStatus(
2810 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002811 {
Jamie Madill437fa652016-05-03 15:13:24 -04002812 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002813 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002814 }
2815
Jamie Madill51f40ec2016-06-15 14:06:00 -04002816 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2817 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002818
2819 if (framebuffer->getReadBufferState() == GL_NONE)
2820 {
2821 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2822 return false;
2823 }
2824
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002825 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002826 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002827 {
Jamie Madill437fa652016-05-03 15:13:24 -04002828 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002829 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002830 }
2831 }
2832 break;
2833
He Yunchaoced53ae2016-11-29 15:00:51 +08002834 default:
2835 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002836 }
2837
2838 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002839 if (*numParams == 0)
2840 {
2841 return false;
2842 }
2843
2844 return true;
2845}
2846
2847bool ValidateRobustStateQuery(ValidationContext *context,
2848 GLenum pname,
2849 GLsizei bufSize,
2850 GLenum *nativeType,
2851 unsigned int *numParams)
2852{
2853 if (!ValidateRobustEntryPoint(context, bufSize))
2854 {
2855 return false;
2856 }
2857
2858 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2859 {
2860 return false;
2861 }
2862
2863 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002864 {
2865 return false;
2866 }
2867
2868 return true;
2869}
2870
Jamie Madillc29968b2016-01-20 11:17:23 -05002871bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2872 GLenum target,
2873 GLint level,
2874 GLenum internalformat,
2875 bool isSubImage,
2876 GLint xoffset,
2877 GLint yoffset,
2878 GLint zoffset,
2879 GLint x,
2880 GLint y,
2881 GLsizei width,
2882 GLsizei height,
2883 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002884 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002885{
Jamie Madill560a8d82014-05-21 13:06:20 -04002886 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2887 {
Jamie Madill437fa652016-05-03 15:13:24 -04002888 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002889 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002890 }
2891
He Yunchaoced53ae2016-11-29 15:00:51 +08002892 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2893 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002894 {
Jamie Madill437fa652016-05-03 15:13:24 -04002895 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002896 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002897 }
2898
2899 if (border != 0)
2900 {
Jamie Madill437fa652016-05-03 15:13:24 -04002901 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002902 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002903 }
2904
2905 if (!ValidMipLevel(context, target, level))
2906 {
Jamie Madill437fa652016-05-03 15:13:24 -04002907 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002908 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002909 }
2910
Jamie Madill51f40ec2016-06-15 14:06:00 -04002911 const auto &state = context->getGLState();
2912 auto readFramebuffer = state.getReadFramebuffer();
2913 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002914 {
Jamie Madill437fa652016-05-03 15:13:24 -04002915 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002916 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002917 }
2918
Jamie Madill51f40ec2016-06-15 14:06:00 -04002919 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002920 {
Jamie Madill437fa652016-05-03 15:13:24 -04002921 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002922 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002923 }
2924
Martin Radev138064f2016-07-15 12:03:41 +03002925 if (readFramebuffer->getReadBufferState() == GL_NONE)
2926 {
2927 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2928 return false;
2929 }
2930
Geoff Langaae65a42014-05-26 12:43:44 -04002931 const gl::Caps &caps = context->getCaps();
2932
Geoff Langaae65a42014-05-26 12:43:44 -04002933 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002934 switch (target)
2935 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002936 case GL_TEXTURE_2D:
2937 maxDimension = caps.max2DTextureSize;
2938 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002939
He Yunchaoced53ae2016-11-29 15:00:51 +08002940 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2941 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2942 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2943 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2944 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2945 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2946 maxDimension = caps.maxCubeMapTextureSize;
2947 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002948
He Yunchaoced53ae2016-11-29 15:00:51 +08002949 case GL_TEXTURE_2D_ARRAY:
2950 maxDimension = caps.max2DTextureSize;
2951 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002952
He Yunchaoced53ae2016-11-29 15:00:51 +08002953 case GL_TEXTURE_3D:
2954 maxDimension = caps.max3DTextureSize;
2955 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002956
He Yunchaoced53ae2016-11-29 15:00:51 +08002957 default:
2958 context->handleError(Error(GL_INVALID_ENUM));
2959 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002960 }
2961
Jamie Madillc29968b2016-01-20 11:17:23 -05002962 gl::Texture *texture =
2963 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002964 if (!texture)
2965 {
Jamie Madill437fa652016-05-03 15:13:24 -04002966 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002968 }
2969
Geoff Lang69cce582015-09-17 13:20:36 -04002970 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002971 {
Jamie Madill437fa652016-05-03 15:13:24 -04002972 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002973 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002974 }
2975
Geoff Lang5d601382014-07-22 15:14:06 -04002976 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2977
2978 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002979 {
Jamie Madill437fa652016-05-03 15:13:24 -04002980 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002981 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002982 }
2983
Geoff Langa9be0dc2014-12-17 12:34:40 -05002984 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002985 {
Jamie Madill437fa652016-05-03 15:13:24 -04002986 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002987 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002988 }
2989
2990 if (isSubImage)
2991 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002992 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2993 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2994 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002995 {
Jamie Madill437fa652016-05-03 15:13:24 -04002996 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002997 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002998 }
2999 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003000 else
3001 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003002 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003003 {
Jamie Madill437fa652016-05-03 15:13:24 -04003004 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003005 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003006 }
3007
Geoff Langeb66a6e2016-10-31 13:06:12 -04003008 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003009 {
Jamie Madill437fa652016-05-03 15:13:24 -04003010 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003011 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003012 }
3013
3014 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003015 if (static_cast<int>(width) > maxLevelDimension ||
3016 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003017 {
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003019 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003020 }
3021 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003022
Jamie Madill0c8abca2016-07-22 20:21:26 -04003023 if (textureFormatOut)
3024 {
3025 *textureFormatOut = texture->getFormat(target, level);
3026 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003027 return true;
3028}
3029
Jamie Madillf25855c2015-11-03 11:06:18 -05003030static bool ValidateDrawBase(ValidationContext *context,
3031 GLenum mode,
3032 GLsizei count,
3033 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003034{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003035 switch (mode)
3036 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003037 case GL_POINTS:
3038 case GL_LINES:
3039 case GL_LINE_LOOP:
3040 case GL_LINE_STRIP:
3041 case GL_TRIANGLES:
3042 case GL_TRIANGLE_STRIP:
3043 case GL_TRIANGLE_FAN:
3044 break;
3045 default:
3046 context->handleError(Error(GL_INVALID_ENUM));
3047 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003048 }
3049
Jamie Madill250d33f2014-06-06 17:09:03 -04003050 if (count < 0)
3051 {
Jamie Madill437fa652016-05-03 15:13:24 -04003052 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003053 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003054 }
3055
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003056 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003057
Jamie Madill250d33f2014-06-06 17:09:03 -04003058 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003059 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003060 {
Jamie Madill437fa652016-05-03 15:13:24 -04003061 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003062 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003063 }
3064
Jamie Madill51f40ec2016-06-15 14:06:00 -04003065 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003066 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003067 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003068 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003069 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3070 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003071 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3072 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3073 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003074 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003075 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3076 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003077 {
3078 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3079 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003080 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003081 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003083 return false;
3084 }
Jamie Madillac528012014-06-20 13:21:23 -04003085 }
3086
Jamie Madill51f40ec2016-06-15 14:06:00 -04003087 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003088 {
Jamie Madill437fa652016-05-03 15:13:24 -04003089 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003090 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003091 }
3092
Geoff Lang7dd2e102014-11-10 15:19:26 -05003093 gl::Program *program = state.getProgram();
3094 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003098 }
3099
Geoff Lang7dd2e102014-11-10 15:19:26 -05003100 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003101 {
Jamie Madill437fa652016-05-03 15:13:24 -04003102 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003103 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003104 }
3105
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003106 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003107 for (unsigned int uniformBlockIndex = 0;
3108 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003109 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003110 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003111 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003112 const OffsetBindingPointer<Buffer> &uniformBuffer =
3113 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003114
Geoff Lang5d124a62015-09-15 13:03:27 -04003115 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003116 {
3117 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003118 context->handleError(
3119 Error(GL_INVALID_OPERATION,
3120 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003121 return false;
3122 }
3123
Geoff Lang5d124a62015-09-15 13:03:27 -04003124 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003125 if (uniformBufferSize == 0)
3126 {
3127 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003128 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003129 }
3130
Jamie Madill62d31cb2015-09-11 13:25:51 -04003131 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003132 {
3133 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003134 context->handleError(
3135 Error(GL_INVALID_OPERATION,
3136 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003137 return false;
3138 }
3139 }
3140
Jamie Madill250d33f2014-06-06 17:09:03 -04003141 // No-op if zero count
3142 return (count > 0);
3143}
3144
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003145bool ValidateDrawArrays(ValidationContext *context,
3146 GLenum mode,
3147 GLint first,
3148 GLsizei count,
3149 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003150{
Jamie Madillfd716582014-06-06 17:09:04 -04003151 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003152 {
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003154 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003155 }
3156
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003157 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003158 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003159 if (curTransformFeedback && curTransformFeedback->isActive() &&
3160 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003161 {
3162 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003163 // that does not match the current transform feedback object's draw mode (if transform
3164 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003165 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003168 }
3169
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003170 if (!ValidateDrawBase(context, mode, count, primcount))
3171 {
3172 return false;
3173 }
3174
3175 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003176 {
3177 return false;
3178 }
3179
3180 return true;
3181}
3182
He Yunchaoced53ae2016-11-29 15:00:51 +08003183bool ValidateDrawArraysInstanced(Context *context,
3184 GLenum mode,
3185 GLint first,
3186 GLsizei count,
3187 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003188{
3189 if (primcount < 0)
3190 {
Jamie Madill437fa652016-05-03 15:13:24 -04003191 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003192 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003193 }
3194
Jamie Madill2b976812014-08-25 15:47:49 -04003195 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003196 {
3197 return false;
3198 }
3199
3200 // No-op if zero primitive count
3201 return (primcount > 0);
3202}
3203
Geoff Lang87a93302014-09-16 13:29:43 -04003204static bool ValidateDrawInstancedANGLE(Context *context)
3205{
3206 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003207 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003208
Geoff Lang7dd2e102014-11-10 15:19:26 -05003209 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003210
3211 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003212 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003213 {
3214 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003215 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003216 {
3217 return true;
3218 }
3219 }
3220
Jamie Madill437fa652016-05-03 15:13:24 -04003221 context->handleError(Error(GL_INVALID_OPERATION,
3222 "ANGLE_instanced_arrays requires that at least one active attribute"
3223 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003224 return false;
3225}
3226
He Yunchaoced53ae2016-11-29 15:00:51 +08003227bool ValidateDrawArraysInstancedANGLE(Context *context,
3228 GLenum mode,
3229 GLint first,
3230 GLsizei count,
3231 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003232{
3233 if (!ValidateDrawInstancedANGLE(context))
3234 {
3235 return false;
3236 }
3237
3238 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3239}
3240
Jamie Madillf25855c2015-11-03 11:06:18 -05003241bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003242 GLenum mode,
3243 GLsizei count,
3244 GLenum type,
3245 const GLvoid *indices,
3246 GLsizei primcount,
3247 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003248{
Jamie Madill250d33f2014-06-06 17:09:03 -04003249 switch (type)
3250 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003251 case GL_UNSIGNED_BYTE:
3252 case GL_UNSIGNED_SHORT:
3253 break;
3254 case GL_UNSIGNED_INT:
3255 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3256 {
3257 context->handleError(Error(GL_INVALID_ENUM));
3258 return false;
3259 }
3260 break;
3261 default:
3262 context->handleError(Error(GL_INVALID_ENUM));
3263 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003264 }
3265
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003266 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003267
3268 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003269 if (curTransformFeedback && curTransformFeedback->isActive() &&
3270 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003271 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003272 // It is an invalid operation to call DrawElements, DrawRangeElements or
3273 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003274 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003275 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003276 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003277 }
3278
3279 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003280 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003281 {
Jamie Madill437fa652016-05-03 15:13:24 -04003282 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003283 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003284 }
3285
He Yunchaoced53ae2016-11-29 15:00:51 +08003286 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003287 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003288 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003289 {
Jamie Madill437fa652016-05-03 15:13:24 -04003290 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003291 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003292 }
3293
Jamie Madillae3000b2014-08-25 15:47:51 -04003294 if (elementArrayBuffer)
3295 {
3296 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3297
3298 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003299 GLint64 byteCount =
3300 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003301
3302 // check for integer overflows
3303 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3304 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3305 {
Jamie Madill437fa652016-05-03 15:13:24 -04003306 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003307 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003308 }
3309
3310 // Check for reading past the end of the bound buffer object
3311 if (byteCount > elementArrayBuffer->getSize())
3312 {
Jamie Madill437fa652016-05-03 15:13:24 -04003313 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003314 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003315 }
3316 }
3317 else if (!indices)
3318 {
3319 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003320 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003321 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003322 }
3323
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003324 if (!ValidateDrawBase(context, mode, count, primcount))
3325 {
3326 return false;
3327 }
3328
Jamie Madill2b976812014-08-25 15:47:49 -04003329 // Use max index to validate if our vertex buffers are large enough for the pull.
3330 // TODO: offer fast path, with disabled index validation.
3331 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3332 if (elementArrayBuffer)
3333 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003334 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003335 Error error =
3336 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3337 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003338 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003339 {
Jamie Madill437fa652016-05-03 15:13:24 -04003340 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003341 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003342 }
3343 }
3344 else
3345 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003346 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003347 }
3348
Jamie Madille79b1e12015-11-04 16:36:37 -05003349 // If we use an index greater than our maximum supported index range, return an error.
3350 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3351 // return an error if possible here.
3352 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3353 {
Jamie Madill437fa652016-05-03 15:13:24 -04003354 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003355 return false;
3356 }
3357
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003358 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003359 {
3360 return false;
3361 }
3362
Geoff Lang3edfe032015-09-04 16:38:24 -04003363 // No op if there are no real indices in the index data (all are primitive restart).
3364 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003365}
3366
Geoff Langb1196682014-07-23 13:47:29 -04003367bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003368 GLenum mode,
3369 GLsizei count,
3370 GLenum type,
3371 const GLvoid *indices,
3372 GLsizei primcount,
3373 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003374{
3375 if (primcount < 0)
3376 {
Jamie Madill437fa652016-05-03 15:13:24 -04003377 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003378 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003379 }
3380
Jamie Madill2b976812014-08-25 15:47:49 -04003381 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003382 {
3383 return false;
3384 }
3385
3386 // No-op zero primitive count
3387 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003388}
3389
Geoff Lang3edfe032015-09-04 16:38:24 -04003390bool ValidateDrawElementsInstancedANGLE(Context *context,
3391 GLenum mode,
3392 GLsizei count,
3393 GLenum type,
3394 const GLvoid *indices,
3395 GLsizei primcount,
3396 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003397{
3398 if (!ValidateDrawInstancedANGLE(context))
3399 {
3400 return false;
3401 }
3402
He Yunchaoced53ae2016-11-29 15:00:51 +08003403 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3404 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003405}
3406
He Yunchaoced53ae2016-11-29 15:00:51 +08003407bool ValidateFramebufferTextureBase(Context *context,
3408 GLenum target,
3409 GLenum attachment,
3410 GLuint texture,
3411 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003412{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003413 if (!ValidFramebufferTarget(target))
3414 {
Jamie Madill437fa652016-05-03 15:13:24 -04003415 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003416 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003417 }
3418
3419 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003420 {
3421 return false;
3422 }
3423
Jamie Madill55ec3b12014-07-03 10:38:57 -04003424 if (texture != 0)
3425 {
3426 gl::Texture *tex = context->getTexture(texture);
3427
3428 if (tex == NULL)
3429 {
Jamie Madill437fa652016-05-03 15:13:24 -04003430 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003431 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003432 }
3433
3434 if (level < 0)
3435 {
Jamie Madill437fa652016-05-03 15:13:24 -04003436 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003437 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003438 }
3439 }
3440
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003441 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003442 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003443
Jamie Madill84115c92015-04-23 15:00:07 -04003444 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003445 {
Jamie Madill437fa652016-05-03 15:13:24 -04003446 context->handleError(
3447 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003448 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003449 }
3450
3451 return true;
3452}
3453
He Yunchaoced53ae2016-11-29 15:00:51 +08003454bool ValidateFramebufferTexture2D(Context *context,
3455 GLenum target,
3456 GLenum attachment,
3457 GLenum textarget,
3458 GLuint texture,
3459 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003460{
He Yunchaoced53ae2016-11-29 15:00:51 +08003461 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3462 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003463 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3464 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003465 {
Jamie Madill437fa652016-05-03 15:13:24 -04003466 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003467 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003468 }
3469
3470 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003471 {
3472 return false;
3473 }
3474
Jamie Madill55ec3b12014-07-03 10:38:57 -04003475 if (texture != 0)
3476 {
3477 gl::Texture *tex = context->getTexture(texture);
3478 ASSERT(tex);
3479
Jamie Madill2a6564e2014-07-11 09:53:19 -04003480 const gl::Caps &caps = context->getCaps();
3481
Jamie Madill55ec3b12014-07-03 10:38:57 -04003482 switch (textarget)
3483 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003484 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003485 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003486 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003487 {
Jamie Madill437fa652016-05-03 15:13:24 -04003488 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003489 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003490 }
3491 if (tex->getTarget() != GL_TEXTURE_2D)
3492 {
Jamie Madill437fa652016-05-03 15:13:24 -04003493 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003494 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003495 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003496 }
3497 break;
3498
He Yunchaoced53ae2016-11-29 15:00:51 +08003499 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3500 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3501 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3502 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3503 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3504 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003505 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003506 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003507 {
Jamie Madill437fa652016-05-03 15:13:24 -04003508 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003509 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003510 }
3511 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3512 {
Jamie Madill437fa652016-05-03 15:13:24 -04003513 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003514 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003515 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003516 }
3517 break;
3518
He Yunchaoced53ae2016-11-29 15:00:51 +08003519 default:
3520 context->handleError(Error(GL_INVALID_ENUM));
3521 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003522 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003523
Jamie Madilla3944d42016-07-22 22:13:26 -04003524 const Format &format = tex->getFormat(textarget, level);
3525 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003526 {
Jamie Madill437fa652016-05-03 15:13:24 -04003527 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003528 return false;
3529 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003530 }
3531
Jamie Madill570f7c82014-07-03 10:38:54 -04003532 return true;
3533}
3534
Geoff Langb1196682014-07-23 13:47:29 -04003535bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003536{
3537 if (program == 0)
3538 {
Jamie Madill437fa652016-05-03 15:13:24 -04003539 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003540 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003541 }
3542
Dian Xiang769769a2015-09-09 15:20:08 -07003543 gl::Program *programObject = GetValidProgram(context, program);
3544 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003545 {
3546 return false;
3547 }
3548
Jamie Madill0063c512014-08-25 15:47:53 -04003549 if (!programObject || !programObject->isLinked())
3550 {
Jamie Madill437fa652016-05-03 15:13:24 -04003551 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003552 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003553 }
3554
Geoff Lang7dd2e102014-11-10 15:19:26 -05003555 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003556 {
Jamie Madill437fa652016-05-03 15:13:24 -04003557 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003558 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003559 }
3560
Jamie Madill0063c512014-08-25 15:47:53 -04003561 return true;
3562}
3563
He Yunchaoced53ae2016-11-29 15:00:51 +08003564bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003565{
3566 return ValidateGetUniformBase(context, program, location);
3567}
3568
He Yunchaoced53ae2016-11-29 15:00:51 +08003569bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003570{
Jamie Madill78f41802014-08-25 15:47:55 -04003571 return ValidateGetUniformBase(context, program, location);
3572}
3573
Geoff Langf41d0ee2016-10-07 13:04:23 -04003574static bool ValidateSizedGetUniform(Context *context,
3575 GLuint program,
3576 GLint location,
3577 GLsizei bufSize,
3578 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003579{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003580 if (length)
3581 {
3582 *length = 0;
3583 }
3584
Jamie Madill78f41802014-08-25 15:47:55 -04003585 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003586 {
Jamie Madill78f41802014-08-25 15:47:55 -04003587 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003588 }
3589
Geoff Langf41d0ee2016-10-07 13:04:23 -04003590 if (bufSize < 0)
3591 {
3592 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3593 return false;
3594 }
3595
Jamie Madilla502c742014-08-28 17:19:13 -04003596 gl::Program *programObject = context->getProgram(program);
3597 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003598
Jamie Madill78f41802014-08-25 15:47:55 -04003599 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003600 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003601 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003602 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003603 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003604 context->handleError(
3605 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003606 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003607 }
3608
Geoff Langf41d0ee2016-10-07 13:04:23 -04003609 if (length)
3610 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003611 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003612 }
3613
Jamie Madill0063c512014-08-25 15:47:53 -04003614 return true;
3615}
3616
He Yunchaoced53ae2016-11-29 15:00:51 +08003617bool ValidateGetnUniformfvEXT(Context *context,
3618 GLuint program,
3619 GLint location,
3620 GLsizei bufSize,
3621 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003622{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003623 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003624}
3625
He Yunchaoced53ae2016-11-29 15:00:51 +08003626bool ValidateGetnUniformivEXT(Context *context,
3627 GLuint program,
3628 GLint location,
3629 GLsizei bufSize,
3630 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003631{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003632 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3633}
3634
3635bool ValidateGetUniformfvRobustANGLE(Context *context,
3636 GLuint program,
3637 GLint location,
3638 GLsizei bufSize,
3639 GLsizei *length,
3640 GLfloat *params)
3641{
3642 if (!ValidateRobustEntryPoint(context, bufSize))
3643 {
3644 return false;
3645 }
3646
3647 // bufSize is validated in ValidateSizedGetUniform
3648 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3649}
3650
3651bool ValidateGetUniformivRobustANGLE(Context *context,
3652 GLuint program,
3653 GLint location,
3654 GLsizei bufSize,
3655 GLsizei *length,
3656 GLint *params)
3657{
3658 if (!ValidateRobustEntryPoint(context, bufSize))
3659 {
3660 return false;
3661 }
3662
3663 // bufSize is validated in ValidateSizedGetUniform
3664 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3665}
3666
3667bool ValidateGetUniformuivRobustANGLE(Context *context,
3668 GLuint program,
3669 GLint location,
3670 GLsizei bufSize,
3671 GLsizei *length,
3672 GLuint *params)
3673{
3674 if (!ValidateRobustEntryPoint(context, bufSize))
3675 {
3676 return false;
3677 }
3678
3679 if (context->getClientMajorVersion() < 3)
3680 {
3681 context->handleError(
3682 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3683 return false;
3684 }
3685
3686 // bufSize is validated in ValidateSizedGetUniform
3687 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003688}
3689
He Yunchaoced53ae2016-11-29 15:00:51 +08003690bool ValidateDiscardFramebufferBase(Context *context,
3691 GLenum target,
3692 GLsizei numAttachments,
3693 const GLenum *attachments,
3694 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003695{
3696 if (numAttachments < 0)
3697 {
Jamie Madill437fa652016-05-03 15:13:24 -04003698 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003699 return false;
3700 }
3701
3702 for (GLsizei i = 0; i < numAttachments; ++i)
3703 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003704 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003705 {
3706 if (defaultFramebuffer)
3707 {
Jamie Madill437fa652016-05-03 15:13:24 -04003708 context->handleError(Error(
3709 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003710 return false;
3711 }
3712
3713 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3714 {
Jamie Madill437fa652016-05-03 15:13:24 -04003715 context->handleError(Error(GL_INVALID_OPERATION,
3716 "Requested color attachment is greater than the maximum "
3717 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003718 return false;
3719 }
3720 }
3721 else
3722 {
3723 switch (attachments[i])
3724 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003725 case GL_DEPTH_ATTACHMENT:
3726 case GL_STENCIL_ATTACHMENT:
3727 case GL_DEPTH_STENCIL_ATTACHMENT:
3728 if (defaultFramebuffer)
3729 {
3730 context->handleError(
3731 Error(GL_INVALID_ENUM,
3732 "Invalid attachment when the default framebuffer is bound"));
3733 return false;
3734 }
3735 break;
3736 case GL_COLOR:
3737 case GL_DEPTH:
3738 case GL_STENCIL:
3739 if (!defaultFramebuffer)
3740 {
3741 context->handleError(
3742 Error(GL_INVALID_ENUM,
3743 "Invalid attachment when the default framebuffer is not bound"));
3744 return false;
3745 }
3746 break;
3747 default:
3748 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003749 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003750 }
3751 }
3752 }
3753
3754 return true;
3755}
3756
Austin Kinross6ee1e782015-05-29 17:05:37 -07003757bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3758{
3759 // Note that debug marker calls must not set error state
3760
3761 if (length < 0)
3762 {
3763 return false;
3764 }
3765
3766 if (marker == nullptr)
3767 {
3768 return false;
3769 }
3770
3771 return true;
3772}
3773
3774bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3775{
3776 // Note that debug marker calls must not set error state
3777
3778 if (length < 0)
3779 {
3780 return false;
3781 }
3782
3783 if (length > 0 && marker == nullptr)
3784 {
3785 return false;
3786 }
3787
3788 return true;
3789}
3790
Geoff Langdcab33b2015-07-21 13:03:16 -04003791bool ValidateEGLImageTargetTexture2DOES(Context *context,
3792 egl::Display *display,
3793 GLenum target,
3794 egl::Image *image)
3795{
Geoff Langa8406172015-07-21 16:53:39 -04003796 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3797 {
Jamie Madill437fa652016-05-03 15:13:24 -04003798 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003799 return false;
3800 }
3801
3802 switch (target)
3803 {
3804 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003805 if (!context->getExtensions().eglImage)
3806 {
3807 context->handleError(Error(
3808 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3809 }
3810 break;
3811
3812 case GL_TEXTURE_EXTERNAL_OES:
3813 if (!context->getExtensions().eglImageExternal)
3814 {
3815 context->handleError(Error(
3816 GL_INVALID_ENUM,
3817 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3818 }
Geoff Langa8406172015-07-21 16:53:39 -04003819 break;
3820
3821 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003823 return false;
3824 }
3825
3826 if (!display->isValidImage(image))
3827 {
Jamie Madill437fa652016-05-03 15:13:24 -04003828 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003829 return false;
3830 }
3831
3832 if (image->getSamples() > 0)
3833 {
Jamie Madill437fa652016-05-03 15:13:24 -04003834 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003835 "cannot create a 2D texture from a multisampled EGL image."));
3836 return false;
3837 }
3838
Jamie Madilla3944d42016-07-22 22:13:26 -04003839 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003840 if (!textureCaps.texturable)
3841 {
Jamie Madill437fa652016-05-03 15:13:24 -04003842 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003843 "EGL image internal format is not supported as a texture."));
3844 return false;
3845 }
3846
Geoff Langdcab33b2015-07-21 13:03:16 -04003847 return true;
3848}
3849
3850bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3851 egl::Display *display,
3852 GLenum target,
3853 egl::Image *image)
3854{
Geoff Langa8406172015-07-21 16:53:39 -04003855 if (!context->getExtensions().eglImage)
3856 {
Jamie Madill437fa652016-05-03 15:13:24 -04003857 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003858 return false;
3859 }
3860
3861 switch (target)
3862 {
3863 case GL_RENDERBUFFER:
3864 break;
3865
3866 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003867 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003868 return false;
3869 }
3870
3871 if (!display->isValidImage(image))
3872 {
Jamie Madill437fa652016-05-03 15:13:24 -04003873 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003874 return false;
3875 }
3876
Jamie Madilla3944d42016-07-22 22:13:26 -04003877 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003878 if (!textureCaps.renderable)
3879 {
Jamie Madill437fa652016-05-03 15:13:24 -04003880 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003881 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3882 return false;
3883 }
3884
Geoff Langdcab33b2015-07-21 13:03:16 -04003885 return true;
3886}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003887
3888bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3889{
Geoff Lang36167ab2015-12-07 10:27:14 -05003890 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003891 {
3892 // The default VAO should always exist
3893 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003894 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003895 return false;
3896 }
3897
3898 return true;
3899}
3900
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003901bool ValidateLinkProgram(Context *context, GLuint program)
3902{
3903 if (context->hasActiveTransformFeedback(program))
3904 {
3905 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003906 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003907 "Cannot link program while program is associated with an active "
3908 "transform feedback object."));
3909 return false;
3910 }
3911 return true;
3912}
3913
Geoff Langc5629752015-12-07 16:29:04 -05003914bool ValidateProgramBinaryBase(Context *context,
3915 GLuint program,
3916 GLenum binaryFormat,
3917 const void *binary,
3918 GLint length)
3919{
3920 Program *programObject = GetValidProgram(context, program);
3921 if (programObject == nullptr)
3922 {
3923 return false;
3924 }
3925
3926 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3927 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3928 programBinaryFormats.end())
3929 {
Jamie Madill437fa652016-05-03 15:13:24 -04003930 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003931 return false;
3932 }
3933
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003934 if (context->hasActiveTransformFeedback(program))
3935 {
3936 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003937 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003938 "Cannot change program binary while program is associated with "
3939 "an active transform feedback object."));
3940 return false;
3941 }
3942
Geoff Langc5629752015-12-07 16:29:04 -05003943 return true;
3944}
3945
3946bool ValidateGetProgramBinaryBase(Context *context,
3947 GLuint program,
3948 GLsizei bufSize,
3949 GLsizei *length,
3950 GLenum *binaryFormat,
3951 void *binary)
3952{
3953 Program *programObject = GetValidProgram(context, program);
3954 if (programObject == nullptr)
3955 {
3956 return false;
3957 }
3958
3959 if (!programObject->isLinked())
3960 {
Jamie Madill437fa652016-05-03 15:13:24 -04003961 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003962 return false;
3963 }
3964
3965 return true;
3966}
Jamie Madillc29968b2016-01-20 11:17:23 -05003967
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003968bool ValidateUseProgram(Context *context, GLuint program)
3969{
3970 if (program != 0)
3971 {
3972 Program *programObject = context->getProgram(program);
3973 if (!programObject)
3974 {
3975 // ES 3.1.0 section 7.3 page 72
3976 if (context->getShader(program))
3977 {
Jamie Madill437fa652016-05-03 15:13:24 -04003978 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003979 Error(GL_INVALID_OPERATION,
3980 "Attempted to use a single shader instead of a shader program."));
3981 return false;
3982 }
3983 else
3984 {
Jamie Madill437fa652016-05-03 15:13:24 -04003985 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003986 return false;
3987 }
3988 }
3989 if (!programObject->isLinked())
3990 {
Jamie Madill437fa652016-05-03 15:13:24 -04003991 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003992 return false;
3993 }
3994 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003995 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003996 {
3997 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003998 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003999 Error(GL_INVALID_OPERATION,
4000 "Cannot change active program while transform feedback is unpaused."));
4001 return false;
4002 }
4003
4004 return true;
4005}
4006
Jamie Madillc29968b2016-01-20 11:17:23 -05004007bool ValidateCopyTexImage2D(ValidationContext *context,
4008 GLenum target,
4009 GLint level,
4010 GLenum internalformat,
4011 GLint x,
4012 GLint y,
4013 GLsizei width,
4014 GLsizei height,
4015 GLint border)
4016{
Martin Radev1be913c2016-07-11 17:59:16 +03004017 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004018 {
4019 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4020 0, x, y, width, height, border);
4021 }
4022
Martin Radev1be913c2016-07-11 17:59:16 +03004023 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004024 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4025 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004026}
Jamie Madillc29968b2016-01-20 11:17:23 -05004027
4028bool ValidateFramebufferRenderbuffer(Context *context,
4029 GLenum target,
4030 GLenum attachment,
4031 GLenum renderbuffertarget,
4032 GLuint renderbuffer)
4033{
4034 if (!ValidFramebufferTarget(target) ||
4035 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4036 {
Jamie Madill437fa652016-05-03 15:13:24 -04004037 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004038 return false;
4039 }
4040
4041 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4042 renderbuffertarget, renderbuffer);
4043}
4044
4045bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4046{
4047 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4048 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4049 {
Jamie Madill437fa652016-05-03 15:13:24 -04004050 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004051 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4052 return false;
4053 }
4054
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004055 ASSERT(context->getGLState().getDrawFramebuffer());
4056 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004057 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4058
4059 // This should come first before the check for the default frame buffer
4060 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4061 // rather than INVALID_OPERATION
4062 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4063 {
4064 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4065
4066 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004067 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4068 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004069 {
4070 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004071 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4072 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4073 // 3.1 is still a bit ambiguous about the error, but future specs are
4074 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004075 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004076 return false;
4077 }
4078 else if (bufs[colorAttachment] >= maxColorAttachment)
4079 {
Jamie Madill437fa652016-05-03 15:13:24 -04004080 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004081 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004082 return false;
4083 }
4084 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4085 frameBufferId != 0)
4086 {
4087 // INVALID_OPERATION-GL is bound to buffer and ith argument
4088 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004089 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004090 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4091 return false;
4092 }
4093 }
4094
4095 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4096 // and n is not 1 or bufs is bound to value other than BACK and NONE
4097 if (frameBufferId == 0)
4098 {
4099 if (n != 1)
4100 {
Jamie Madill437fa652016-05-03 15:13:24 -04004101 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004102 "n must be 1 when GL is bound to the default framebuffer"));
4103 return false;
4104 }
4105
4106 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4107 {
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004109 GL_INVALID_OPERATION,
4110 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4111 return false;
4112 }
4113 }
4114
4115 return true;
4116}
4117
4118bool ValidateCopyTexSubImage2D(Context *context,
4119 GLenum target,
4120 GLint level,
4121 GLint xoffset,
4122 GLint yoffset,
4123 GLint x,
4124 GLint y,
4125 GLsizei width,
4126 GLsizei height)
4127{
Martin Radev1be913c2016-07-11 17:59:16 +03004128 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004129 {
4130 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4131 yoffset, x, y, width, height, 0);
4132 }
4133
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004134 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4135 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004136}
4137
Geoff Lang496c02d2016-10-20 11:38:11 -07004138bool ValidateGetBufferPointervBase(Context *context,
4139 GLenum target,
4140 GLenum pname,
4141 GLsizei *length,
4142 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004143{
Geoff Lang496c02d2016-10-20 11:38:11 -07004144 if (length)
4145 {
4146 *length = 0;
4147 }
4148
4149 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4150 {
4151 context->handleError(
4152 Error(GL_INVALID_OPERATION,
4153 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4154 return false;
4155 }
4156
Olli Etuaho4f667482016-03-30 15:56:35 +03004157 if (!ValidBufferTarget(context, target))
4158 {
Jamie Madill437fa652016-05-03 15:13:24 -04004159 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004160 return false;
4161 }
4162
Geoff Lang496c02d2016-10-20 11:38:11 -07004163 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004164 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004165 case GL_BUFFER_MAP_POINTER:
4166 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004167
Geoff Lang496c02d2016-10-20 11:38:11 -07004168 default:
4169 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4170 return false;
4171 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004172
4173 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4174 // target bound to zero generate an INVALID_OPERATION error."
4175 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004176 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004177 {
Jamie Madill437fa652016-05-03 15:13:24 -04004178 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004179 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4180 return false;
4181 }
4182
Geoff Lang496c02d2016-10-20 11:38:11 -07004183 if (length)
4184 {
4185 *length = 1;
4186 }
4187
Olli Etuaho4f667482016-03-30 15:56:35 +03004188 return true;
4189}
4190
4191bool ValidateUnmapBufferBase(Context *context, GLenum target)
4192{
4193 if (!ValidBufferTarget(context, target))
4194 {
Jamie Madill437fa652016-05-03 15:13:24 -04004195 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004196 return false;
4197 }
4198
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004199 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004200
4201 if (buffer == nullptr || !buffer->isMapped())
4202 {
Jamie Madill437fa652016-05-03 15:13:24 -04004203 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004204 return false;
4205 }
4206
4207 return true;
4208}
4209
4210bool ValidateMapBufferRangeBase(Context *context,
4211 GLenum target,
4212 GLintptr offset,
4213 GLsizeiptr length,
4214 GLbitfield access)
4215{
4216 if (!ValidBufferTarget(context, target))
4217 {
Jamie Madill437fa652016-05-03 15:13:24 -04004218 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004219 return false;
4220 }
4221
4222 if (offset < 0 || length < 0)
4223 {
Jamie Madill437fa652016-05-03 15:13:24 -04004224 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004225 return false;
4226 }
4227
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004228 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004229
4230 if (!buffer)
4231 {
Jamie Madill437fa652016-05-03 15:13:24 -04004232 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004233 return false;
4234 }
4235
4236 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004237 CheckedNumeric<size_t> checkedOffset(offset);
4238 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004239
Jamie Madille2e406c2016-06-02 13:04:10 -04004240 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004241 {
Jamie Madill437fa652016-05-03 15:13:24 -04004242 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004243 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4244 return false;
4245 }
4246
4247 // Check for invalid bits in the mask
4248 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4249 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4250 GL_MAP_UNSYNCHRONIZED_BIT;
4251
4252 if (access & ~(allAccessBits))
4253 {
Jamie Madill437fa652016-05-03 15:13:24 -04004254 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004255 return false;
4256 }
4257
4258 if (length == 0)
4259 {
Jamie Madill437fa652016-05-03 15:13:24 -04004260 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004261 return false;
4262 }
4263
4264 if (buffer->isMapped())
4265 {
Jamie Madill437fa652016-05-03 15:13:24 -04004266 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004267 return false;
4268 }
4269
4270 // Check for invalid bit combinations
4271 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4272 {
Jamie Madill437fa652016-05-03 15:13:24 -04004273 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004274 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4275 return false;
4276 }
4277
4278 GLbitfield writeOnlyBits =
4279 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4280
4281 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4282 {
Jamie Madill437fa652016-05-03 15:13:24 -04004283 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004284 "Invalid access bits when mapping buffer for reading: 0x%X.",
4285 access));
4286 return false;
4287 }
4288
4289 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4290 {
Jamie Madill437fa652016-05-03 15:13:24 -04004291 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004292 GL_INVALID_OPERATION,
4293 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4294 return false;
4295 }
4296 return true;
4297}
4298
4299bool ValidateFlushMappedBufferRangeBase(Context *context,
4300 GLenum target,
4301 GLintptr offset,
4302 GLsizeiptr length)
4303{
4304 if (offset < 0 || length < 0)
4305 {
Jamie Madill437fa652016-05-03 15:13:24 -04004306 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004307 return false;
4308 }
4309
4310 if (!ValidBufferTarget(context, target))
4311 {
Jamie Madill437fa652016-05-03 15:13:24 -04004312 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004313 return false;
4314 }
4315
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004316 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004317
4318 if (buffer == nullptr)
4319 {
Jamie Madill437fa652016-05-03 15:13:24 -04004320 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004321 return false;
4322 }
4323
4324 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4325 {
Jamie Madill437fa652016-05-03 15:13:24 -04004326 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004327 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4328 return false;
4329 }
4330
4331 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004332 CheckedNumeric<size_t> checkedOffset(offset);
4333 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004334
Jamie Madille2e406c2016-06-02 13:04:10 -04004335 if (!checkedSize.IsValid() ||
4336 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004337 {
Jamie Madill437fa652016-05-03 15:13:24 -04004338 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004339 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4340 return false;
4341 }
4342
4343 return true;
4344}
4345
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004346bool ValidateGenerateMipmap(Context *context, GLenum target)
4347{
4348 if (!ValidTextureTarget(context, target))
4349 {
4350 context->handleError(Error(GL_INVALID_ENUM));
4351 return false;
4352 }
4353
4354 Texture *texture = context->getTargetTexture(target);
4355
4356 if (texture == nullptr)
4357 {
4358 context->handleError(Error(GL_INVALID_OPERATION));
4359 return false;
4360 }
4361
4362 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4363
4364 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4365 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4366 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4367 {
4368 context->handleError(Error(GL_INVALID_OPERATION));
4369 return false;
4370 }
4371
Jamie Madilla3944d42016-07-22 22:13:26 -04004372 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4373 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4374 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004375
4376 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4377 // unsized formats or that are color renderable and filterable. Since we do not track if
4378 // the texture was created with sized or unsized format (only sized formats are stored),
4379 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4380 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4381 // textures since they're the only texture format that can be created with unsized formats
4382 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4383 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004384 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4385 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004386 {
4387 context->handleError(Error(GL_INVALID_OPERATION));
4388 return false;
4389 }
4390
4391 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004392 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004393 {
4394 context->handleError(Error(GL_INVALID_OPERATION));
4395 return false;
4396 }
4397
4398 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004399 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004400 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4401 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4402 {
Geoff Lang55482a12016-11-21 16:54:01 -05004403 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004404 context->handleError(Error(GL_INVALID_OPERATION));
4405 return false;
4406 }
4407
4408 // Cube completeness check
4409 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4410 {
4411 context->handleError(Error(GL_INVALID_OPERATION));
4412 return false;
4413 }
4414
4415 return true;
4416}
4417
Olli Etuaho41997e72016-03-10 13:38:39 +02004418bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4419{
4420 return ValidateGenOrDelete(context, n);
4421}
4422
4423bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4424{
4425 return ValidateGenOrDelete(context, n);
4426}
4427
4428bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4429{
4430 return ValidateGenOrDelete(context, n);
4431}
4432
4433bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4434{
4435 return ValidateGenOrDelete(context, n);
4436}
4437
4438bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4439{
4440 return ValidateGenOrDelete(context, n);
4441}
4442
4443bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4444{
4445 return ValidateGenOrDelete(context, n);
4446}
4447
4448bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4449{
4450 return ValidateGenOrDelete(context, n);
4451}
4452
4453bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4454{
4455 return ValidateGenOrDelete(context, n);
4456}
4457
4458bool ValidateGenOrDelete(Context *context, GLint n)
4459{
4460 if (n < 0)
4461 {
Jamie Madill437fa652016-05-03 15:13:24 -04004462 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004463 return false;
4464 }
4465 return true;
4466}
4467
Geoff Langf41a7152016-09-19 15:11:17 -04004468bool ValidateEnable(Context *context, GLenum cap)
4469{
4470 if (!ValidCap(context, cap, false))
4471 {
4472 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4473 return false;
4474 }
4475
4476 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4477 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4478 {
4479 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4480 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4481
4482 // We also output an error message to the debugger window if tracing is active, so that
4483 // developers can see the error message.
4484 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004485 return false;
4486 }
4487
4488 return true;
4489}
4490
4491bool ValidateDisable(Context *context, GLenum cap)
4492{
4493 if (!ValidCap(context, cap, false))
4494 {
4495 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4496 return false;
4497 }
4498
4499 return true;
4500}
4501
4502bool ValidateIsEnabled(Context *context, GLenum cap)
4503{
4504 if (!ValidCap(context, cap, true))
4505 {
4506 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4507 return false;
4508 }
4509
4510 return true;
4511}
4512
Geoff Langff5b2d52016-09-07 11:32:23 -04004513bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4514{
4515 if (!context->getExtensions().robustClientMemory)
4516 {
4517 context->handleError(
4518 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4519 return false;
4520 }
4521
4522 if (bufSize < 0)
4523 {
4524 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4525 return false;
4526 }
4527
4528 return true;
4529}
4530
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004531bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4532{
4533 if (bufSize < numParams)
4534 {
4535 context->handleError(Error(GL_INVALID_OPERATION,
4536 "%u parameters are required but %i were provided.", numParams,
4537 bufSize));
4538 return false;
4539 }
4540
4541 return true;
4542}
4543
Geoff Langff5b2d52016-09-07 11:32:23 -04004544bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4545 GLenum target,
4546 GLenum attachment,
4547 GLenum pname,
4548 GLsizei *numParams)
4549{
4550 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4551 *numParams = 1;
4552
4553 if (!ValidFramebufferTarget(target))
4554 {
4555 context->handleError(Error(GL_INVALID_ENUM));
4556 return false;
4557 }
4558
4559 int clientVersion = context->getClientMajorVersion();
4560
4561 switch (pname)
4562 {
4563 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4564 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4565 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4566 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4567 break;
4568
4569 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4570 if (clientVersion < 3 && !context->getExtensions().sRGB)
4571 {
4572 context->handleError(Error(GL_INVALID_ENUM));
4573 return false;
4574 }
4575 break;
4576
4577 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4578 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4579 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4580 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4581 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4582 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4583 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4584 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4585 if (clientVersion < 3)
4586 {
4587 context->handleError(Error(GL_INVALID_ENUM));
4588 return false;
4589 }
4590 break;
4591
4592 default:
4593 context->handleError(Error(GL_INVALID_ENUM));
4594 return false;
4595 }
4596
4597 // Determine if the attachment is a valid enum
4598 switch (attachment)
4599 {
4600 case GL_BACK:
4601 case GL_FRONT:
4602 case GL_DEPTH:
4603 case GL_STENCIL:
4604 case GL_DEPTH_STENCIL_ATTACHMENT:
4605 if (clientVersion < 3)
4606 {
4607 context->handleError(Error(GL_INVALID_ENUM));
4608 return false;
4609 }
4610 break;
4611
4612 case GL_DEPTH_ATTACHMENT:
4613 case GL_STENCIL_ATTACHMENT:
4614 break;
4615
4616 default:
4617 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4618 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4619 {
4620 context->handleError(Error(GL_INVALID_ENUM));
4621 return false;
4622 }
4623 break;
4624 }
4625
4626 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4627 ASSERT(framebuffer);
4628
4629 if (framebuffer->id() == 0)
4630 {
4631 if (clientVersion < 3)
4632 {
4633 context->handleError(Error(GL_INVALID_OPERATION));
4634 return false;
4635 }
4636
4637 switch (attachment)
4638 {
4639 case GL_BACK:
4640 case GL_DEPTH:
4641 case GL_STENCIL:
4642 break;
4643
4644 default:
4645 context->handleError(Error(GL_INVALID_OPERATION));
4646 return false;
4647 }
4648 }
4649 else
4650 {
4651 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4652 {
4653 // Valid attachment query
4654 }
4655 else
4656 {
4657 switch (attachment)
4658 {
4659 case GL_DEPTH_ATTACHMENT:
4660 case GL_STENCIL_ATTACHMENT:
4661 break;
4662
4663 case GL_DEPTH_STENCIL_ATTACHMENT:
4664 if (!framebuffer->hasValidDepthStencil())
4665 {
4666 context->handleError(Error(GL_INVALID_OPERATION));
4667 return false;
4668 }
4669 break;
4670
4671 default:
4672 context->handleError(Error(GL_INVALID_OPERATION));
4673 return false;
4674 }
4675 }
4676 }
4677
4678 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4679 if (attachmentObject)
4680 {
4681 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4682 attachmentObject->type() == GL_TEXTURE ||
4683 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4684
4685 switch (pname)
4686 {
4687 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4688 if (attachmentObject->type() != GL_RENDERBUFFER &&
4689 attachmentObject->type() != GL_TEXTURE)
4690 {
4691 context->handleError(Error(GL_INVALID_ENUM));
4692 return false;
4693 }
4694 break;
4695
4696 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4697 if (attachmentObject->type() != GL_TEXTURE)
4698 {
4699 context->handleError(Error(GL_INVALID_ENUM));
4700 return false;
4701 }
4702 break;
4703
4704 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4705 if (attachmentObject->type() != GL_TEXTURE)
4706 {
4707 context->handleError(Error(GL_INVALID_ENUM));
4708 return false;
4709 }
4710 break;
4711
4712 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4713 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4714 {
4715 context->handleError(Error(GL_INVALID_OPERATION));
4716 return false;
4717 }
4718 break;
4719
4720 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4721 if (attachmentObject->type() != GL_TEXTURE)
4722 {
4723 context->handleError(Error(GL_INVALID_ENUM));
4724 return false;
4725 }
4726 break;
4727
4728 default:
4729 break;
4730 }
4731 }
4732 else
4733 {
4734 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4735 // is NONE, then querying any other pname will generate INVALID_ENUM.
4736
4737 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4738 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4739 // INVALID_OPERATION for all other pnames
4740
4741 switch (pname)
4742 {
4743 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4744 break;
4745
4746 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4747 if (clientVersion < 3)
4748 {
4749 context->handleError(Error(GL_INVALID_ENUM));
4750 return false;
4751 }
4752 break;
4753
4754 default:
4755 if (clientVersion < 3)
4756 {
4757 context->handleError(Error(GL_INVALID_ENUM));
4758 return false;
4759 }
4760 else
4761 {
4762 context->handleError(Error(GL_INVALID_OPERATION));
4763 return false;
4764 }
4765 }
4766 }
4767
4768 return true;
4769}
4770
4771bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4772 GLenum target,
4773 GLenum attachment,
4774 GLenum pname,
4775 GLsizei bufSize,
4776 GLsizei *numParams)
4777{
4778 if (!ValidateRobustEntryPoint(context, bufSize))
4779 {
4780 return false;
4781 }
4782
4783 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4784 {
4785 return false;
4786 }
4787
4788 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4789 {
4790 return false;
4791 }
4792
4793 return true;
4794}
4795
4796bool ValidateGetBufferParameteriv(ValidationContext *context,
4797 GLenum target,
4798 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004799 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004800{
Geoff Langebebe1c2016-10-14 12:01:31 -04004801 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004802}
4803
4804bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4805 GLenum target,
4806 GLenum pname,
4807 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004808 GLsizei *length,
4809 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004810{
4811 if (!ValidateRobustEntryPoint(context, bufSize))
4812 {
4813 return false;
4814 }
4815
Geoff Langebebe1c2016-10-14 12:01:31 -04004816 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004817 {
4818 return false;
4819 }
4820
Geoff Langebebe1c2016-10-14 12:01:31 -04004821 if (!ValidateRobustBufferSize(context, bufSize, *length))
4822 {
4823 return false;
4824 }
4825
4826 return true;
4827}
4828
4829bool ValidateGetBufferParameteri64v(ValidationContext *context,
4830 GLenum target,
4831 GLenum pname,
4832 GLint64 *params)
4833{
4834 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4835}
4836
4837bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4838 GLenum target,
4839 GLenum pname,
4840 GLsizei bufSize,
4841 GLsizei *length,
4842 GLint64 *params)
4843{
4844 if (!ValidateRobustEntryPoint(context, bufSize))
4845 {
4846 return false;
4847 }
4848
4849 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4850 {
4851 return false;
4852 }
4853
4854 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004855 {
4856 return false;
4857 }
4858
4859 return true;
4860}
4861
4862bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4863{
4864 // Currently, all GetProgramiv queries return 1 parameter
4865 *numParams = 1;
4866
4867 Program *programObject = GetValidProgram(context, program);
4868 if (!programObject)
4869 {
4870 return false;
4871 }
4872
4873 switch (pname)
4874 {
4875 case GL_DELETE_STATUS:
4876 case GL_LINK_STATUS:
4877 case GL_VALIDATE_STATUS:
4878 case GL_INFO_LOG_LENGTH:
4879 case GL_ATTACHED_SHADERS:
4880 case GL_ACTIVE_ATTRIBUTES:
4881 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4882 case GL_ACTIVE_UNIFORMS:
4883 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4884 break;
4885
4886 case GL_PROGRAM_BINARY_LENGTH:
4887 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4888 {
4889 context->handleError(Error(GL_INVALID_ENUM,
4890 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4891 "GL_OES_get_program_binary or ES 3.0."));
4892 return false;
4893 }
4894 break;
4895
4896 case GL_ACTIVE_UNIFORM_BLOCKS:
4897 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4898 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4899 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4900 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4901 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4902 if (context->getClientMajorVersion() < 3)
4903 {
4904 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4905 return false;
4906 }
4907 break;
4908
4909 default:
4910 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4911 return false;
4912 }
4913
4914 return true;
4915}
4916
4917bool ValidateGetProgramivRobustANGLE(Context *context,
4918 GLuint program,
4919 GLenum pname,
4920 GLsizei bufSize,
4921 GLsizei *numParams)
4922{
4923 if (!ValidateRobustEntryPoint(context, bufSize))
4924 {
4925 return false;
4926 }
4927
4928 if (!ValidateGetProgramiv(context, program, pname, numParams))
4929 {
4930 return false;
4931 }
4932
4933 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4934 {
4935 return false;
4936 }
4937
4938 return true;
4939}
4940
Geoff Lang740d9022016-10-07 11:20:52 -04004941bool ValidateGetRenderbufferParameteriv(Context *context,
4942 GLenum target,
4943 GLenum pname,
4944 GLint *params)
4945{
4946 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4947}
4948
4949bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4950 GLenum target,
4951 GLenum pname,
4952 GLsizei bufSize,
4953 GLsizei *length,
4954 GLint *params)
4955{
4956 if (!ValidateRobustEntryPoint(context, bufSize))
4957 {
4958 return false;
4959 }
4960
4961 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4962 {
4963 return false;
4964 }
4965
4966 if (!ValidateRobustBufferSize(context, bufSize, *length))
4967 {
4968 return false;
4969 }
4970
4971 return true;
4972}
4973
Geoff Langd7d0ed32016-10-07 11:33:51 -04004974bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4975{
4976 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4977}
4978
4979bool ValidateGetShaderivRobustANGLE(Context *context,
4980 GLuint shader,
4981 GLenum pname,
4982 GLsizei bufSize,
4983 GLsizei *length,
4984 GLint *params)
4985{
4986 if (!ValidateRobustEntryPoint(context, bufSize))
4987 {
4988 return false;
4989 }
4990
4991 if (!ValidateGetShaderivBase(context, shader, pname, length))
4992 {
4993 return false;
4994 }
4995
4996 if (!ValidateRobustBufferSize(context, bufSize, *length))
4997 {
4998 return false;
4999 }
5000
5001 return true;
5002}
5003
Geoff Langc1984ed2016-10-07 12:41:00 -04005004bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5005{
5006 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5007}
5008
5009bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5010 GLenum target,
5011 GLenum pname,
5012 GLsizei bufSize,
5013 GLsizei *length,
5014 GLfloat *params)
5015{
5016 if (!ValidateRobustEntryPoint(context, bufSize))
5017 {
5018 return false;
5019 }
5020
5021 if (!ValidateGetTexParameterBase(context, target, pname, length))
5022 {
5023 return false;
5024 }
5025
5026 if (!ValidateRobustBufferSize(context, bufSize, *length))
5027 {
5028 return false;
5029 }
5030
5031 return true;
5032}
5033
5034bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5035{
5036 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5037}
5038
5039bool ValidateGetTexParameterivRobustANGLE(Context *context,
5040 GLenum target,
5041 GLenum pname,
5042 GLsizei bufSize,
5043 GLsizei *length,
5044 GLint *params)
5045{
5046 if (!ValidateRobustEntryPoint(context, bufSize))
5047 {
5048 return false;
5049 }
5050
5051 if (!ValidateGetTexParameterBase(context, target, pname, length))
5052 {
5053 return false;
5054 }
5055
5056 if (!ValidateRobustBufferSize(context, bufSize, *length))
5057 {
5058 return false;
5059 }
5060
5061 return true;
5062}
5063
5064bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5065{
5066 return ValidateTexParameterBase(context, target, pname, -1, &param);
5067}
5068
5069bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5070{
5071 return ValidateTexParameterBase(context, target, pname, -1, params);
5072}
5073
5074bool ValidateTexParameterfvRobustANGLE(Context *context,
5075 GLenum target,
5076 GLenum pname,
5077 GLsizei bufSize,
5078 const GLfloat *params)
5079{
5080 if (!ValidateRobustEntryPoint(context, bufSize))
5081 {
5082 return false;
5083 }
5084
5085 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5086}
5087
5088bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5089{
5090 return ValidateTexParameterBase(context, target, pname, -1, &param);
5091}
5092
5093bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5094{
5095 return ValidateTexParameterBase(context, target, pname, -1, params);
5096}
5097
5098bool ValidateTexParameterivRobustANGLE(Context *context,
5099 GLenum target,
5100 GLenum pname,
5101 GLsizei bufSize,
5102 const GLint *params)
5103{
5104 if (!ValidateRobustEntryPoint(context, bufSize))
5105 {
5106 return false;
5107 }
5108
5109 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5110}
5111
5112bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5113{
5114 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5115}
5116
5117bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5118 GLuint sampler,
5119 GLenum pname,
5120 GLuint bufSize,
5121 GLsizei *length,
5122 GLfloat *params)
5123{
5124 if (!ValidateRobustEntryPoint(context, bufSize))
5125 {
5126 return false;
5127 }
5128
5129 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5130 {
5131 return false;
5132 }
5133
5134 if (!ValidateRobustBufferSize(context, bufSize, *length))
5135 {
5136 return false;
5137 }
5138
5139 return true;
5140}
5141
5142bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5143{
5144 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5145}
5146
5147bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5148 GLuint sampler,
5149 GLenum pname,
5150 GLuint bufSize,
5151 GLsizei *length,
5152 GLint *params)
5153{
5154 if (!ValidateRobustEntryPoint(context, bufSize))
5155 {
5156 return false;
5157 }
5158
5159 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5160 {
5161 return false;
5162 }
5163
5164 if (!ValidateRobustBufferSize(context, bufSize, *length))
5165 {
5166 return false;
5167 }
5168
5169 return true;
5170}
5171
5172bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5173{
5174 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5175}
5176
5177bool ValidateSamplerParameterfv(Context *context,
5178 GLuint sampler,
5179 GLenum pname,
5180 const GLfloat *params)
5181{
5182 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5183}
5184
5185bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5186 GLuint sampler,
5187 GLenum pname,
5188 GLsizei bufSize,
5189 const GLfloat *params)
5190{
5191 if (!ValidateRobustEntryPoint(context, bufSize))
5192 {
5193 return false;
5194 }
5195
5196 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5197}
5198
5199bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5200{
5201 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5202}
5203
5204bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5205{
5206 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5207}
5208
5209bool ValidateSamplerParameterivRobustANGLE(Context *context,
5210 GLuint sampler,
5211 GLenum pname,
5212 GLsizei bufSize,
5213 const GLint *params)
5214{
5215 if (!ValidateRobustEntryPoint(context, bufSize))
5216 {
5217 return false;
5218 }
5219
5220 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5221}
5222
Geoff Lang0b031062016-10-13 14:30:04 -04005223bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5224{
5225 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5226}
5227
5228bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5229 GLuint index,
5230 GLenum pname,
5231 GLsizei bufSize,
5232 GLsizei *length,
5233 GLfloat *params)
5234{
5235 if (!ValidateRobustEntryPoint(context, bufSize))
5236 {
5237 return false;
5238 }
5239
5240 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5241 {
5242 return false;
5243 }
5244
5245 if (!ValidateRobustBufferSize(context, bufSize, *length))
5246 {
5247 return false;
5248 }
5249
5250 return true;
5251}
5252
5253bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5254{
5255 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5256}
5257
5258bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5259 GLuint index,
5260 GLenum pname,
5261 GLsizei bufSize,
5262 GLsizei *length,
5263 GLint *params)
5264{
5265 if (!ValidateRobustEntryPoint(context, bufSize))
5266 {
5267 return false;
5268 }
5269
5270 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5271 {
5272 return false;
5273 }
5274
5275 if (!ValidateRobustBufferSize(context, bufSize, *length))
5276 {
5277 return false;
5278 }
5279
5280 return true;
5281}
5282
5283bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5284{
5285 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5286}
5287
5288bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5289 GLuint index,
5290 GLenum pname,
5291 GLsizei bufSize,
5292 GLsizei *length,
5293 void **pointer)
5294{
5295 if (!ValidateRobustEntryPoint(context, bufSize))
5296 {
5297 return false;
5298 }
5299
5300 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5301 {
5302 return false;
5303 }
5304
5305 if (!ValidateRobustBufferSize(context, bufSize, *length))
5306 {
5307 return false;
5308 }
5309
5310 return true;
5311}
5312
5313bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5314{
5315 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5316}
5317
5318bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5319 GLuint index,
5320 GLenum pname,
5321 GLsizei bufSize,
5322 GLsizei *length,
5323 GLint *params)
5324{
5325 if (!ValidateRobustEntryPoint(context, bufSize))
5326 {
5327 return false;
5328 }
5329
5330 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5331 {
5332 return false;
5333 }
5334
5335 if (!ValidateRobustBufferSize(context, bufSize, *length))
5336 {
5337 return false;
5338 }
5339
5340 return true;
5341}
5342
5343bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5344{
5345 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5346}
5347
5348bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5349 GLuint index,
5350 GLenum pname,
5351 GLsizei bufSize,
5352 GLsizei *length,
5353 GLuint *params)
5354{
5355 if (!ValidateRobustEntryPoint(context, bufSize))
5356 {
5357 return false;
5358 }
5359
5360 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5361 {
5362 return false;
5363 }
5364
5365 if (!ValidateRobustBufferSize(context, bufSize, *length))
5366 {
5367 return false;
5368 }
5369
5370 return true;
5371}
5372
Geoff Lang6899b872016-10-14 11:30:13 -04005373bool ValidateGetActiveUniformBlockiv(Context *context,
5374 GLuint program,
5375 GLuint uniformBlockIndex,
5376 GLenum pname,
5377 GLint *params)
5378{
5379 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5380}
5381
5382bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5383 GLuint program,
5384 GLuint uniformBlockIndex,
5385 GLenum pname,
5386 GLsizei bufSize,
5387 GLsizei *length,
5388 GLint *params)
5389{
5390 if (!ValidateRobustEntryPoint(context, bufSize))
5391 {
5392 return false;
5393 }
5394
5395 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5396 {
5397 return false;
5398 }
5399
5400 if (!ValidateRobustBufferSize(context, bufSize, *length))
5401 {
5402 return false;
5403 }
5404
5405 return true;
5406}
5407
Geoff Lang0a9661f2016-10-20 10:59:20 -07005408bool ValidateGetInternalFormativ(Context *context,
5409 GLenum target,
5410 GLenum internalformat,
5411 GLenum pname,
5412 GLsizei bufSize,
5413 GLint *params)
5414{
5415 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5416 nullptr);
5417}
5418
5419bool ValidateGetInternalFormativRobustANGLE(Context *context,
5420 GLenum target,
5421 GLenum internalformat,
5422 GLenum pname,
5423 GLsizei bufSize,
5424 GLsizei *length,
5425 GLint *params)
5426{
5427 if (!ValidateRobustEntryPoint(context, bufSize))
5428 {
5429 return false;
5430 }
5431
5432 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5433 {
5434 return false;
5435 }
5436
5437 if (!ValidateRobustBufferSize(context, bufSize, *length))
5438 {
5439 return false;
5440 }
5441
5442 return true;
5443}
5444
Jamie Madillc29968b2016-01-20 11:17:23 -05005445} // namespace gl