blob: 6d76d339bf3202dde4c3def8c98ac924588b42f4 [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
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 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 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 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:
169 UNIMPLEMENTED();
170 return context->getClientVersion() >= Version(3, 1);
171
Geoff Langf41a7152016-09-19 15:11:17 -0400172 default:
173 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500174 }
175}
176
Geoff Lang62fce5b2016-09-30 10:46:35 -0400177bool ValidateReadPixelsBase(ValidationContext *context,
178 GLint x,
179 GLint y,
180 GLsizei width,
181 GLsizei height,
182 GLenum format,
183 GLenum type,
184 GLsizei bufSize,
185 GLsizei *length,
186 GLvoid *pixels)
187{
188 if (length != nullptr)
189 {
190 *length = 0;
191 }
192
193 if (width < 0 || height < 0)
194 {
195 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
196 return false;
197 }
198
199 auto readFramebuffer = context->getGLState().getReadFramebuffer();
200
201 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
202 {
203 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
204 return false;
205 }
206
207 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
208 {
209 context->handleError(Error(GL_INVALID_OPERATION));
210 return false;
211 }
212
213 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
214 ASSERT(framebuffer);
215
216 if (framebuffer->getReadBufferState() == GL_NONE)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
219 return false;
220 }
221
222 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
223 if (!readBuffer)
224 {
225 context->handleError(Error(GL_INVALID_OPERATION));
226 return false;
227 }
228
229 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
230 GLenum currentType = framebuffer->getImplementationColorReadType();
231 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
232
233 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
234 bool validFormatTypeCombination =
235 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
236
237 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
238 {
239 context->handleError(Error(GL_INVALID_OPERATION));
240 return false;
241 }
242
243 // Check for pixel pack buffer related API errors
244 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
245 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
246 {
247 // ...the buffer object's data store is currently mapped.
248 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
249 return false;
250 }
251
252 // .. the data would be packed to the buffer object such that the memory writes required
253 // would exceed the data store size.
254 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
255 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
256 const gl::Extents size(width, height, 1);
257 const auto &pack = context->getGLState().getPackState();
258
259 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
260 if (endByteOrErr.isError())
261 {
262 context->handleError(endByteOrErr.getError());
263 return false;
264 }
265
266 size_t endByte = endByteOrErr.getResult();
267 if (bufSize >= 0)
268 {
269
270 if (static_cast<size_t>(bufSize) < endByte)
271 {
272 context->handleError(
273 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
274 return false;
275 }
276 }
277
278 if (pixelPackBuffer != nullptr)
279 {
280 CheckedNumeric<size_t> checkedEndByte(endByte);
281 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
282 checkedEndByte += checkedOffset;
283
284 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
285 {
286 // Overflow past the end of the buffer
287 context->handleError(
288 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
289 return false;
290 }
291 }
292
293 if (length != nullptr)
294 {
295 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
296 {
297 context->handleError(
298 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
299 return false;
300 }
301
302 *length = static_cast<GLsizei>(endByte);
303 }
304
305 return true;
306}
307
Geoff Lang740d9022016-10-07 11:20:52 -0400308bool ValidateGetRenderbufferParameterivBase(Context *context,
309 GLenum target,
310 GLenum pname,
311 GLsizei *length)
312{
313 if (length)
314 {
315 *length = 0;
316 }
317
318 if (target != GL_RENDERBUFFER)
319 {
320 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
321 return false;
322 }
323
324 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
325 if (renderbuffer == nullptr)
326 {
327 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
328 return false;
329 }
330
331 switch (pname)
332 {
333 case GL_RENDERBUFFER_WIDTH:
334 case GL_RENDERBUFFER_HEIGHT:
335 case GL_RENDERBUFFER_INTERNAL_FORMAT:
336 case GL_RENDERBUFFER_RED_SIZE:
337 case GL_RENDERBUFFER_GREEN_SIZE:
338 case GL_RENDERBUFFER_BLUE_SIZE:
339 case GL_RENDERBUFFER_ALPHA_SIZE:
340 case GL_RENDERBUFFER_DEPTH_SIZE:
341 case GL_RENDERBUFFER_STENCIL_SIZE:
342 break;
343
344 case GL_RENDERBUFFER_SAMPLES_ANGLE:
345 if (!context->getExtensions().framebufferMultisample)
346 {
347 context->handleError(
348 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
349 return false;
350 }
351 break;
352
353 default:
354 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
355 return false;
356 }
357
358 if (length)
359 {
360 *length = 1;
361 }
362 return true;
363}
364
Geoff Langd7d0ed32016-10-07 11:33:51 -0400365bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
366{
367 if (length)
368 {
369 *length = 0;
370 }
371
372 if (GetValidShader(context, shader) == nullptr)
373 {
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_SHADER_TYPE:
380 case GL_DELETE_STATUS:
381 case GL_COMPILE_STATUS:
382 case GL_INFO_LOG_LENGTH:
383 case GL_SHADER_SOURCE_LENGTH:
384 break;
385
386 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
387 if (!context->getExtensions().translatedShaderSource)
388 {
389 context->handleError(
390 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
391 return false;
392 }
393 break;
394
395 default:
396 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
397 return false;
398 }
399
400 if (length)
401 {
402 *length = 1;
403 }
404 return true;
405}
406
Geoff Langc1984ed2016-10-07 12:41:00 -0400407bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
408{
409 if (length)
410 {
411 *length = 0;
412 }
413
414 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
415 {
416 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
417 return false;
418 }
419
420 if (context->getTargetTexture(target) == nullptr)
421 {
422 // Should only be possible for external textures
423 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
424 return false;
425 }
426
427 switch (pname)
428 {
429 case GL_TEXTURE_MAG_FILTER:
430 case GL_TEXTURE_MIN_FILTER:
431 case GL_TEXTURE_WRAP_S:
432 case GL_TEXTURE_WRAP_T:
433 break;
434
435 case GL_TEXTURE_USAGE_ANGLE:
436 if (!context->getExtensions().textureUsage)
437 {
438 context->handleError(
439 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
445 if (!context->getExtensions().textureFilterAnisotropic)
446 {
447 context->handleError(
448 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
449 return false;
450 }
451 break;
452
453 case GL_TEXTURE_IMMUTABLE_FORMAT:
454 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
455 {
456 context->handleError(
457 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
458 return false;
459 }
460 break;
461
462 case GL_TEXTURE_WRAP_R:
463 case GL_TEXTURE_IMMUTABLE_LEVELS:
464 case GL_TEXTURE_SWIZZLE_R:
465 case GL_TEXTURE_SWIZZLE_G:
466 case GL_TEXTURE_SWIZZLE_B:
467 case GL_TEXTURE_SWIZZLE_A:
468 case GL_TEXTURE_BASE_LEVEL:
469 case GL_TEXTURE_MAX_LEVEL:
470 case GL_TEXTURE_MIN_LOD:
471 case GL_TEXTURE_MAX_LOD:
472 case GL_TEXTURE_COMPARE_MODE:
473 case GL_TEXTURE_COMPARE_FUNC:
474 if (context->getClientMajorVersion() < 3)
475 {
476 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
477 return false;
478 }
479 break;
480
Geoff Lang81c6b572016-10-19 14:07:52 -0700481 case GL_TEXTURE_SRGB_DECODE_EXT:
482 if (!context->getExtensions().textureSRGBDecode)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
486 return false;
487 }
488 break;
489
Geoff Langc1984ed2016-10-07 12:41:00 -0400490 default:
491 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
492 return false;
493 }
494
495 if (length)
496 {
497 *length = 1;
498 }
499 return true;
500}
501
502template <typename ParamType>
503bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
504{
505 switch (ConvertToGLenum(params[0]))
506 {
507 case GL_CLAMP_TO_EDGE:
508 break;
509
510 case GL_REPEAT:
511 case GL_MIRRORED_REPEAT:
512 if (isExternalTextureTarget)
513 {
514 // OES_EGL_image_external specifies this error.
515 context->handleError(Error(
516 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
517 return false;
518 }
519 break;
520
521 default:
522 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
523 return false;
524 }
525
526 return true;
527}
528
529template <typename ParamType>
530bool ValidateTextureMinFilterValue(Context *context,
531 ParamType *params,
532 bool isExternalTextureTarget)
533{
534 switch (ConvertToGLenum(params[0]))
535 {
536 case GL_NEAREST:
537 case GL_LINEAR:
538 break;
539
540 case GL_NEAREST_MIPMAP_NEAREST:
541 case GL_LINEAR_MIPMAP_NEAREST:
542 case GL_NEAREST_MIPMAP_LINEAR:
543 case GL_LINEAR_MIPMAP_LINEAR:
544 if (isExternalTextureTarget)
545 {
546 // OES_EGL_image_external specifies this error.
547 context->handleError(
548 Error(GL_INVALID_ENUM,
549 "external textures only support NEAREST and LINEAR filtering"));
550 return false;
551 }
552 break;
553
554 default:
555 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
556 return false;
557 }
558
559 return true;
560}
561
562template <typename ParamType>
563bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
564{
565 switch (ConvertToGLenum(params[0]))
566 {
567 case GL_NEAREST:
568 case GL_LINEAR:
569 break;
570
571 default:
572 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
573 return false;
574 }
575
576 return true;
577}
578
579template <typename ParamType>
580bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
581{
582 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
583 switch (ConvertToGLenum(params[0]))
584 {
585 case GL_NONE:
586 case GL_COMPARE_REF_TO_TEXTURE:
587 break;
588
589 default:
590 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
591 return false;
592 }
593
594 return true;
595}
596
597template <typename ParamType>
598bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
599{
600 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
601 switch (ConvertToGLenum(params[0]))
602 {
603 case GL_LEQUAL:
604 case GL_GEQUAL:
605 case GL_LESS:
606 case GL_GREATER:
607 case GL_EQUAL:
608 case GL_NOTEQUAL:
609 case GL_ALWAYS:
610 case GL_NEVER:
611 break;
612
613 default:
614 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
615 return false;
616 }
617
618 return true;
619}
620
621template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700622bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
623{
624 if (!context->getExtensions().textureSRGBDecode)
625 {
626 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
627 return false;
628 }
629
630 switch (ConvertToGLenum(params[0]))
631 {
632 case GL_DECODE_EXT:
633 case GL_SKIP_DECODE_EXT:
634 break;
635
636 default:
637 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
638 return false;
639 }
640
641 return true;
642}
643
644template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400645bool ValidateTexParameterBase(Context *context,
646 GLenum target,
647 GLenum pname,
648 GLsizei bufSize,
649 ParamType *params)
650{
651 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
652 {
653 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
654 return false;
655 }
656
657 if (context->getTargetTexture(target) == nullptr)
658 {
659 // Should only be possible for external textures
660 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
661 return false;
662 }
663
664 const GLsizei minBufSize = 1;
665 if (bufSize >= 0 && bufSize < minBufSize)
666 {
667 context->handleError(
668 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
669 return false;
670 }
671
672 switch (pname)
673 {
674 case GL_TEXTURE_WRAP_R:
675 case GL_TEXTURE_SWIZZLE_R:
676 case GL_TEXTURE_SWIZZLE_G:
677 case GL_TEXTURE_SWIZZLE_B:
678 case GL_TEXTURE_SWIZZLE_A:
679 case GL_TEXTURE_BASE_LEVEL:
680 case GL_TEXTURE_MAX_LEVEL:
681 case GL_TEXTURE_COMPARE_MODE:
682 case GL_TEXTURE_COMPARE_FUNC:
683 case GL_TEXTURE_MIN_LOD:
684 case GL_TEXTURE_MAX_LOD:
685 if (context->getClientMajorVersion() < 3)
686 {
687 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
688 return false;
689 }
690 if (target == GL_TEXTURE_EXTERNAL_OES &&
691 !context->getExtensions().eglImageExternalEssl3)
692 {
693 context->handleError(Error(GL_INVALID_ENUM,
694 "ES3 texture parameters are not available without "
695 "GL_OES_EGL_image_external_essl3."));
696 return false;
697 }
698 break;
699
700 default:
701 break;
702 }
703
704 switch (pname)
705 {
706 case GL_TEXTURE_WRAP_S:
707 case GL_TEXTURE_WRAP_T:
708 case GL_TEXTURE_WRAP_R:
709 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
710 {
711 return false;
712 }
713 break;
714
715 case GL_TEXTURE_MIN_FILTER:
716 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
717 {
718 return false;
719 }
720 break;
721
722 case GL_TEXTURE_MAG_FILTER:
723 if (!ValidateTextureMagFilterValue(context, params))
724 {
725 return false;
726 }
727 break;
728
729 case GL_TEXTURE_USAGE_ANGLE:
730 switch (ConvertToGLenum(params[0]))
731 {
732 case GL_NONE:
733 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
734 break;
735
736 default:
737 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
738 return false;
739 }
740 break;
741
742 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
743 if (!context->getExtensions().textureFilterAnisotropic)
744 {
745 context->handleError(
746 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
747 return false;
748 }
749
750 // we assume the parameter passed to this validation method is truncated, not rounded
751 if (params[0] < 1)
752 {
753 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
754 return false;
755 }
756 break;
757
758 case GL_TEXTURE_MIN_LOD:
759 case GL_TEXTURE_MAX_LOD:
760 // any value is permissible
761 break;
762
763 case GL_TEXTURE_COMPARE_MODE:
764 if (!ValidateTextureCompareModeValue(context, params))
765 {
766 return false;
767 }
768 break;
769
770 case GL_TEXTURE_COMPARE_FUNC:
771 if (!ValidateTextureCompareFuncValue(context, params))
772 {
773 return false;
774 }
775 break;
776
777 case GL_TEXTURE_SWIZZLE_R:
778 case GL_TEXTURE_SWIZZLE_G:
779 case GL_TEXTURE_SWIZZLE_B:
780 case GL_TEXTURE_SWIZZLE_A:
781 switch (ConvertToGLenum(params[0]))
782 {
783 case GL_RED:
784 case GL_GREEN:
785 case GL_BLUE:
786 case GL_ALPHA:
787 case GL_ZERO:
788 case GL_ONE:
789 break;
790
791 default:
792 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
793 return false;
794 }
795 break;
796
797 case GL_TEXTURE_BASE_LEVEL:
798 if (params[0] < 0)
799 {
800 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
801 return false;
802 }
803 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
804 {
805 context->handleError(
806 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
807 return false;
808 }
809 break;
810
811 case GL_TEXTURE_MAX_LEVEL:
812 if (params[0] < 0)
813 {
814 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
815 return false;
816 }
817 break;
818
Geoff Lang3b573612016-10-31 14:08:10 -0400819 case GL_DEPTH_STENCIL_TEXTURE_MODE:
820 if (context->getClientVersion() < Version(3, 1))
821 {
822 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
823 return false;
824 }
825 UNIMPLEMENTED();
826 break;
827
Geoff Lang81c6b572016-10-19 14:07:52 -0700828 case GL_TEXTURE_SRGB_DECODE_EXT:
829 if (!ValidateTextureSRGBDecodeValue(context, params))
830 {
831 return false;
832 }
833 break;
834
Geoff Langc1984ed2016-10-07 12:41:00 -0400835 default:
836 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
837 return false;
838 }
839
840 return true;
841}
842
843template <typename ParamType>
844bool ValidateSamplerParameterBase(Context *context,
845 GLuint sampler,
846 GLenum pname,
847 GLsizei bufSize,
848 ParamType *params)
849{
850 if (context->getClientMajorVersion() < 3)
851 {
852 context->handleError(
853 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
854 return false;
855 }
856
857 if (!context->isSampler(sampler))
858 {
859 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
860 return false;
861 }
862
863 const GLsizei minBufSize = 1;
864 if (bufSize >= 0 && bufSize < minBufSize)
865 {
866 context->handleError(
867 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
868 return false;
869 }
870
871 switch (pname)
872 {
873 case GL_TEXTURE_WRAP_S:
874 case GL_TEXTURE_WRAP_T:
875 case GL_TEXTURE_WRAP_R:
876 if (!ValidateTextureWrapModeValue(context, params, false))
877 {
878 return false;
879 }
880 break;
881
882 case GL_TEXTURE_MIN_FILTER:
883 if (!ValidateTextureMinFilterValue(context, params, false))
884 {
885 return false;
886 }
887 break;
888
889 case GL_TEXTURE_MAG_FILTER:
890 if (!ValidateTextureMagFilterValue(context, params))
891 {
892 return false;
893 }
894 break;
895
896 case GL_TEXTURE_MIN_LOD:
897 case GL_TEXTURE_MAX_LOD:
898 // any value is permissible
899 break;
900
901 case GL_TEXTURE_COMPARE_MODE:
902 if (!ValidateTextureCompareModeValue(context, params))
903 {
904 return false;
905 }
906 break;
907
908 case GL_TEXTURE_COMPARE_FUNC:
909 if (!ValidateTextureCompareFuncValue(context, params))
910 {
911 return false;
912 }
913 break;
914
Geoff Lang81c6b572016-10-19 14:07:52 -0700915 case GL_TEXTURE_SRGB_DECODE_EXT:
916 if (!ValidateTextureSRGBDecodeValue(context, params))
917 {
918 return false;
919 }
920 break;
921
Geoff Langc1984ed2016-10-07 12:41:00 -0400922 default:
923 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
924 return false;
925 }
926
927 return true;
928}
929
930bool ValidateGetSamplerParameterBase(Context *context,
931 GLuint sampler,
932 GLenum pname,
933 GLsizei *length)
934{
935 if (length)
936 {
937 *length = 0;
938 }
939
940 if (context->getClientMajorVersion() < 3)
941 {
942 context->handleError(
943 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
944 return false;
945 }
946
947 if (!context->isSampler(sampler))
948 {
949 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
950 return false;
951 }
952
953 switch (pname)
954 {
955 case GL_TEXTURE_WRAP_S:
956 case GL_TEXTURE_WRAP_T:
957 case GL_TEXTURE_WRAP_R:
958 case GL_TEXTURE_MIN_FILTER:
959 case GL_TEXTURE_MAG_FILTER:
960 case GL_TEXTURE_MIN_LOD:
961 case GL_TEXTURE_MAX_LOD:
962 case GL_TEXTURE_COMPARE_MODE:
963 case GL_TEXTURE_COMPARE_FUNC:
964 break;
965
Geoff Lang81c6b572016-10-19 14:07:52 -0700966 case GL_TEXTURE_SRGB_DECODE_EXT:
967 if (!context->getExtensions().textureSRGBDecode)
968 {
969 context->handleError(
970 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
971 return false;
972 }
973 break;
974
Geoff Langc1984ed2016-10-07 12:41:00 -0400975 default:
976 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
977 return false;
978 }
979
980 if (length)
981 {
982 *length = 1;
983 }
984 return true;
985}
986
Geoff Lang0b031062016-10-13 14:30:04 -0400987bool ValidateGetVertexAttribBase(Context *context,
988 GLuint index,
989 GLenum pname,
990 GLsizei *length,
991 bool pointer,
992 bool pureIntegerEntryPoint)
993{
994 if (length)
995 {
996 *length = 0;
997 }
998
999 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1000 {
1001 context->handleError(
1002 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1003 return false;
1004 }
1005
1006 if (index >= context->getCaps().maxVertexAttributes)
1007 {
1008 context->handleError(Error(
1009 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1010 return false;
1011 }
1012
1013 if (pointer)
1014 {
1015 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1016 {
1017 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1018 return false;
1019 }
1020 }
1021 else
1022 {
1023 switch (pname)
1024 {
1025 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1026 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1027 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1028 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1029 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1030 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1031 case GL_CURRENT_VERTEX_ATTRIB:
1032 break;
1033
1034 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1035 static_assert(
1036 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1037 "ANGLE extension enums not equal to GL enums.");
1038 if (context->getClientMajorVersion() < 3 &&
1039 !context->getExtensions().instancedArrays)
1040 {
1041 context->handleError(Error(GL_INVALID_ENUM,
1042 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1043 "3.0 or GL_ANGLE_instanced_arrays."));
1044 return false;
1045 }
1046 break;
1047
1048 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1049 if (context->getClientMajorVersion() < 3)
1050 {
1051 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1052 return false;
1053 }
1054 break;
1055
1056 default:
1057 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1058 return false;
1059 }
1060 }
1061
1062 if (length)
1063 {
1064 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1065 {
1066 *length = 4;
1067 }
1068 else
1069 {
1070 *length = 1;
1071 }
1072 }
1073
1074 return true;
1075}
1076
Geoff Lang6899b872016-10-14 11:30:13 -04001077bool ValidateGetActiveUniformBlockivBase(Context *context,
1078 GLuint program,
1079 GLuint uniformBlockIndex,
1080 GLenum pname,
1081 GLsizei *length)
1082{
1083 if (length)
1084 {
1085 *length = 0;
1086 }
1087
1088 if (context->getClientMajorVersion() < 3)
1089 {
1090 context->handleError(
1091 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1092 return false;
1093 }
1094
1095 Program *programObject = GetValidProgram(context, program);
1096 if (!programObject)
1097 {
1098 return false;
1099 }
1100
1101 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1102 {
1103 context->handleError(
1104 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1105 return false;
1106 }
1107
1108 switch (pname)
1109 {
1110 case GL_UNIFORM_BLOCK_BINDING:
1111 case GL_UNIFORM_BLOCK_DATA_SIZE:
1112 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1113 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1114 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1115 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1116 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1117 break;
1118
1119 default:
1120 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1121 return false;
1122 }
1123
1124 if (length)
1125 {
1126 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1127 {
1128 const UniformBlock &uniformBlock =
1129 programObject->getUniformBlockByIndex(uniformBlockIndex);
1130 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1131 }
1132 else
1133 {
1134 *length = 1;
1135 }
1136 }
1137
1138 return true;
1139}
1140
Geoff Langebebe1c2016-10-14 12:01:31 -04001141bool ValidateGetBufferParameterBase(ValidationContext *context,
1142 GLenum target,
1143 GLenum pname,
1144 bool pointerVersion,
1145 GLsizei *numParams)
1146{
1147 if (numParams)
1148 {
1149 *numParams = 0;
1150 }
1151
1152 if (!ValidBufferTarget(context, target))
1153 {
1154 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1155 return false;
1156 }
1157
1158 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1159 if (!buffer)
1160 {
1161 // A null buffer means that "0" is bound to the requested buffer target
1162 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1163 return false;
1164 }
1165
1166 const Extensions &extensions = context->getExtensions();
1167
1168 switch (pname)
1169 {
1170 case GL_BUFFER_USAGE:
1171 case GL_BUFFER_SIZE:
1172 break;
1173
1174 case GL_BUFFER_ACCESS_OES:
1175 if (!extensions.mapBuffer)
1176 {
1177 context->handleError(
1178 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1179 return false;
1180 }
1181 break;
1182
1183 case GL_BUFFER_MAPPED:
1184 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1185 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1186 !extensions.mapBufferRange)
1187 {
1188 context->handleError(Error(
1189 GL_INVALID_ENUM,
1190 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1191 return false;
1192 }
1193 break;
1194
1195 case GL_BUFFER_MAP_POINTER:
1196 if (!pointerVersion)
1197 {
1198 context->handleError(
1199 Error(GL_INVALID_ENUM,
1200 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1201 return false;
1202 }
1203 break;
1204
1205 case GL_BUFFER_ACCESS_FLAGS:
1206 case GL_BUFFER_MAP_OFFSET:
1207 case GL_BUFFER_MAP_LENGTH:
1208 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1209 {
1210 context->handleError(Error(
1211 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1212 return false;
1213 }
1214 break;
1215
1216 default:
1217 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1218 return false;
1219 }
1220
1221 // All buffer parameter queries return one value.
1222 if (numParams)
1223 {
1224 *numParams = 1;
1225 }
1226
1227 return true;
1228}
1229
Geoff Lang0a9661f2016-10-20 10:59:20 -07001230bool ValidateGetInternalFormativBase(Context *context,
1231 GLenum target,
1232 GLenum internalformat,
1233 GLenum pname,
1234 GLsizei bufSize,
1235 GLsizei *numParams)
1236{
1237 if (numParams)
1238 {
1239 *numParams = 0;
1240 }
1241
1242 if (context->getClientMajorVersion() < 3)
1243 {
1244 context->handleError(
1245 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1246 return false;
1247 }
1248
1249 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1250 if (!formatCaps.renderable)
1251 {
1252 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1253 return false;
1254 }
1255
1256 switch (target)
1257 {
1258 case GL_RENDERBUFFER:
1259 break;
1260
1261 default:
1262 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1263 return false;
1264 }
1265
1266 if (bufSize < 0)
1267 {
1268 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1269 return false;
1270 }
1271
1272 GLsizei maxWriteParams = 0;
1273 switch (pname)
1274 {
1275 case GL_NUM_SAMPLE_COUNTS:
1276 maxWriteParams = 1;
1277 break;
1278
1279 case GL_SAMPLES:
1280 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1281 break;
1282
1283 default:
1284 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1285 return false;
1286 }
1287
1288 if (numParams)
1289 {
1290 // glGetInternalFormativ will not overflow bufSize
1291 *numParams = std::min(bufSize, maxWriteParams);
1292 }
1293
1294 return true;
1295}
1296
Geoff Langf41a7152016-09-19 15:11:17 -04001297} // anonymous namespace
1298
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001299bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001300{
Jamie Madilld7460c72014-01-21 16:38:14 -05001301 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001302 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001303 case GL_TEXTURE_2D:
1304 case GL_TEXTURE_CUBE_MAP:
1305 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001306
Jamie Madilld7460c72014-01-21 16:38:14 -05001307 case GL_TEXTURE_3D:
1308 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001309 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001310
Geoff Lang3b573612016-10-31 14:08:10 -04001311 case GL_TEXTURE_2D_MULTISAMPLE:
1312 UNIMPLEMENTED();
1313 return (context->getClientVersion() >= Version(3, 1));
1314
Jamie Madilld7460c72014-01-21 16:38:14 -05001315 default:
1316 return false;
1317 }
Jamie Madill35d15012013-10-07 10:46:37 -04001318}
1319
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001320bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1321{
1322 switch (target)
1323 {
1324 case GL_TEXTURE_2D:
1325 case GL_TEXTURE_CUBE_MAP:
1326 return true;
1327
1328 default:
1329 return false;
1330 }
1331}
1332
1333bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1334{
1335 switch (target)
1336 {
1337 case GL_TEXTURE_3D:
1338 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001339 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001340
1341 default:
1342 return false;
1343 }
1344}
1345
Ian Ewellbda75592016-04-18 17:25:54 -04001346// Most texture GL calls are not compatible with external textures, so we have a separate validation
1347// function for use in the GL calls that do
1348bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1349{
1350 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1351 (context->getExtensions().eglImageExternal ||
1352 context->getExtensions().eglStreamConsumerExternal);
1353}
1354
Shannon Woods4dfed832014-03-17 20:03:39 -04001355// This function differs from ValidTextureTarget in that the target must be
1356// usable as the destination of a 2D operation-- so a cube face is valid, but
1357// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001358// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001359bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001360{
1361 switch (target)
1362 {
1363 case GL_TEXTURE_2D:
1364 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1365 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1366 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1367 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1368 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1369 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1370 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001371 default:
1372 return false;
1373 }
1374}
1375
1376bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1377{
1378 switch (target)
1379 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001380 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001381 case GL_TEXTURE_2D_ARRAY:
1382 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001383 default:
1384 return false;
1385 }
1386}
1387
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001388bool ValidFramebufferTarget(GLenum target)
1389{
Geoff Langd4475812015-03-18 10:53:05 -04001390 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1391 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001392
1393 switch (target)
1394 {
1395 case GL_FRAMEBUFFER: return true;
1396 case GL_READ_FRAMEBUFFER: return true;
1397 case GL_DRAW_FRAMEBUFFER: return true;
1398 default: return false;
1399 }
1400}
1401
Jamie Madill29639852016-09-02 15:00:09 -04001402bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001403{
1404 switch (target)
1405 {
1406 case GL_ARRAY_BUFFER:
1407 case GL_ELEMENT_ARRAY_BUFFER:
1408 return true;
1409
Jamie Madill8c96d582014-03-05 15:01:23 -05001410 case GL_PIXEL_PACK_BUFFER:
1411 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001412 return (context->getExtensions().pixelBufferObject ||
1413 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001414
Shannon Woodsb3801742014-03-27 14:59:19 -04001415 case GL_COPY_READ_BUFFER:
1416 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001417 case GL_TRANSFORM_FEEDBACK_BUFFER:
1418 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001419 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001420
Geoff Lang3b573612016-10-31 14:08:10 -04001421 case GL_ATOMIC_COUNTER_BUFFER:
1422 case GL_SHADER_STORAGE_BUFFER:
1423 case GL_DRAW_INDIRECT_BUFFER:
1424 case GL_DISPATCH_INDIRECT_BUFFER:
1425 UNIMPLEMENTED();
1426 return context->getClientVersion() >= Version(3, 1);
1427
Jamie Madill8c96d582014-03-05 15:01:23 -05001428 default:
1429 return false;
1430 }
1431}
1432
Jamie Madillc29968b2016-01-20 11:17:23 -05001433bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001434{
Jamie Madillc29968b2016-01-20 11:17:23 -05001435 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001436 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001437 switch (target)
1438 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001439 case GL_TEXTURE_2D:
1440 maxDimension = caps.max2DTextureSize;
1441 break;
Geoff Langce635692013-09-24 13:56:32 -04001442 case GL_TEXTURE_CUBE_MAP:
1443 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1444 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1445 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1446 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1447 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001448 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1449 maxDimension = caps.maxCubeMapTextureSize;
1450 break;
1451 case GL_TEXTURE_3D:
1452 maxDimension = caps.max3DTextureSize;
1453 break;
1454 case GL_TEXTURE_2D_ARRAY:
1455 maxDimension = caps.max2DTextureSize;
1456 break;
Geoff Langce635692013-09-24 13:56:32 -04001457 default: UNREACHABLE();
1458 }
1459
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001460 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001461}
1462
Austin Kinross08528e12015-10-07 16:24:40 -07001463bool ValidImageSizeParameters(const Context *context,
1464 GLenum target,
1465 GLint level,
1466 GLsizei width,
1467 GLsizei height,
1468 GLsizei depth,
1469 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001470{
1471 if (level < 0 || width < 0 || height < 0 || depth < 0)
1472 {
1473 return false;
1474 }
1475
Austin Kinross08528e12015-10-07 16:24:40 -07001476 // TexSubImage parameters can be NPOT without textureNPOT extension,
1477 // as long as the destination texture is POT.
1478 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001479 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001480 {
1481 return false;
1482 }
1483
1484 if (!ValidMipLevel(context, target, level))
1485 {
1486 return false;
1487 }
1488
1489 return true;
1490}
1491
Geoff Lang0d8b7242015-09-09 14:56:53 -04001492bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1493{
1494 // List of compressed format that require that the texture size is smaller than or a multiple of
1495 // the compressed block size.
1496 switch (internalFormat)
1497 {
1498 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1499 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1500 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1501 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001502 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001503 return true;
1504
1505 default:
1506 return false;
1507 }
1508}
1509
Jamie Madillc29968b2016-01-20 11:17:23 -05001510bool ValidCompressedImageSize(const ValidationContext *context,
1511 GLenum internalFormat,
1512 GLsizei width,
1513 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001514{
Geoff Lang5d601382014-07-22 15:14:06 -04001515 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1516 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001517 {
1518 return false;
1519 }
1520
Geoff Lang0d8b7242015-09-09 14:56:53 -04001521 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001522 {
1523 return false;
1524 }
1525
Geoff Lang0d8b7242015-09-09 14:56:53 -04001526 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1527 {
1528 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1529 width % formatInfo.compressedBlockWidth != 0) ||
1530 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1531 height % formatInfo.compressedBlockHeight != 0))
1532 {
1533 return false;
1534 }
1535 }
1536
Geoff Langd4f180b2013-09-24 13:57:44 -04001537 return true;
1538}
1539
Geoff Langff5b2d52016-09-07 11:32:23 -04001540bool ValidImageDataSize(ValidationContext *context,
1541 GLenum textureTarget,
1542 GLsizei width,
1543 GLsizei height,
1544 GLsizei depth,
1545 GLenum internalFormat,
1546 GLenum type,
1547 const GLvoid *pixels,
1548 GLsizei imageSize)
1549{
1550 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1551 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1552 {
1553 // Checks are not required
1554 return true;
1555 }
1556
1557 // ...the data would be unpacked from the buffer object such that the memory reads required
1558 // would exceed the data store size.
1559 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1560 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1561 const gl::Extents size(width, height, depth);
1562 const auto &unpack = context->getGLState().getUnpackState();
1563
1564 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1565 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1566 if (endByteOrErr.isError())
1567 {
1568 context->handleError(endByteOrErr.getError());
1569 return false;
1570 }
1571
1572 GLuint endByte = endByteOrErr.getResult();
1573
1574 if (pixelUnpackBuffer)
1575 {
1576 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1577 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1578 checkedEndByte += checkedOffset;
1579
1580 if (!checkedEndByte.IsValid() ||
1581 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1582 {
1583 // Overflow past the end of the buffer
1584 context->handleError(Error(GL_INVALID_OPERATION));
1585 return false;
1586 }
1587 }
1588 else
1589 {
1590 ASSERT(imageSize >= 0);
1591 if (pixels == nullptr && imageSize != 0)
1592 {
1593 context->handleError(
1594 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001595 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001596 }
1597
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001598 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001599 {
1600 context->handleError(
1601 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1602 return false;
1603 }
1604 }
1605
1606 return true;
1607}
1608
Geoff Lang37dde692014-01-31 16:34:54 -05001609bool ValidQueryType(const Context *context, GLenum queryType)
1610{
Geoff Langd4475812015-03-18 10:53:05 -04001611 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1612 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001613
1614 switch (queryType)
1615 {
1616 case GL_ANY_SAMPLES_PASSED:
1617 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1618 return true;
1619 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001620 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001621 case GL_TIME_ELAPSED_EXT:
1622 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001623 case GL_COMMANDS_COMPLETED_CHROMIUM:
1624 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001625 default:
1626 return false;
1627 }
1628}
1629
Jamie Madillef300b12016-10-07 15:12:09 -04001630Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001631{
1632 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1633 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1634 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1635
Dian Xiang769769a2015-09-09 15:20:08 -07001636 Program *validProgram = context->getProgram(id);
1637
1638 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001639 {
Dian Xiang769769a2015-09-09 15:20:08 -07001640 if (context->getShader(id))
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001643 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1644 }
1645 else
1646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001648 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001649 }
Dian Xiang769769a2015-09-09 15:20:08 -07001650
1651 return validProgram;
1652}
1653
Jamie Madillef300b12016-10-07 15:12:09 -04001654Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001655{
1656 // See ValidProgram for spec details.
1657
1658 Shader *validShader = context->getShader(id);
1659
1660 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001661 {
Dian Xiang769769a2015-09-09 15:20:08 -07001662 if (context->getProgram(id))
1663 {
Jamie Madill437fa652016-05-03 15:13:24 -04001664 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001665 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1666 }
1667 else
1668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001670 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001671 }
Dian Xiang769769a2015-09-09 15:20:08 -07001672
1673 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001674}
1675
Geoff Langb1196682014-07-23 13:47:29 -04001676bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001677{
1678 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1679 {
1680 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1681
Geoff Langaae65a42014-05-26 12:43:44 -04001682 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001683 {
Jamie Madill437fa652016-05-03 15:13:24 -04001684 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001685 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001686 }
1687 }
1688 else
1689 {
1690 switch (attachment)
1691 {
1692 case GL_DEPTH_ATTACHMENT:
1693 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001694 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001695
1696 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001697 if (!context->getExtensions().webglCompatibility &&
1698 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001699 {
1700 context->handleError(Error(GL_INVALID_ENUM));
1701 return false;
1702 }
1703 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001704
1705 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001707 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001708 }
1709 }
1710
1711 return true;
1712}
1713
Corentin Walleze0902642014-11-04 12:32:15 -08001714bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1715 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001716{
1717 switch (target)
1718 {
1719 case GL_RENDERBUFFER:
1720 break;
1721 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001723 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724 }
1725
1726 if (width < 0 || height < 0 || samples < 0)
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001729 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001730 }
1731
Geoff Langd87878e2014-09-19 15:42:59 -04001732 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1733 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001734 {
Jamie Madill437fa652016-05-03 15:13:24 -04001735 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001736 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001737 }
1738
1739 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1740 // 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 -08001741 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001742 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001743 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001747 }
1748
Geoff Langaae65a42014-05-26 12:43:44 -04001749 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 }
1754
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001755 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001756 if (handle == 0)
1757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 }
1761
1762 return true;
1763}
1764
Corentin Walleze0902642014-11-04 12:32:15 -08001765bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1766 GLenum internalformat, GLsizei width, GLsizei height)
1767{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001768 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001769
1770 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001771 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001772 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001773 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001776 return false;
1777 }
1778
1779 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1780 // the specified storage. This is different than ES 3.0 in which a sample number higher
1781 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001782 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001783 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001784 {
Geoff Langa4903b72015-03-02 16:02:48 -08001785 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1786 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001789 return false;
1790 }
Corentin Walleze0902642014-11-04 12:32:15 -08001791 }
1792
1793 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1794}
1795
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001796bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1797 GLenum renderbuffertarget, GLuint renderbuffer)
1798{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001799 if (!ValidFramebufferTarget(target))
1800 {
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001802 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001803 }
1804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001805 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001806
Jamie Madill84115c92015-04-23 15:00:07 -04001807 ASSERT(framebuffer);
1808 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001809 {
Jamie Madill437fa652016-05-03 15:13:24 -04001810 context->handleError(
1811 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001812 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001813 }
1814
Jamie Madillb4472272014-07-03 10:38:55 -04001815 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001816 {
Jamie Madillb4472272014-07-03 10:38:55 -04001817 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001818 }
1819
Jamie Madillab9d82c2014-01-21 16:38:14 -05001820 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1821 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1822 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1823 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1824 if (renderbuffer != 0)
1825 {
1826 if (!context->getRenderbuffer(renderbuffer))
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001830 }
1831 }
1832
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001833 return true;
1834}
1835
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001836bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001837 GLint srcX0,
1838 GLint srcY0,
1839 GLint srcX1,
1840 GLint srcY1,
1841 GLint dstX0,
1842 GLint dstY0,
1843 GLint dstX1,
1844 GLint dstY1,
1845 GLbitfield mask,
1846 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001847{
1848 switch (filter)
1849 {
1850 case GL_NEAREST:
1851 break;
1852 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001853 break;
1854 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001857 }
1858
1859 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001863 }
1864
1865 if (mask == 0)
1866 {
1867 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1868 // buffers are copied.
1869 return false;
1870 }
1871
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001872 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1873 // color buffer, leaving only nearest being unfiltered from above
1874 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1875 {
Jamie Madill437fa652016-05-03 15:13:24 -04001876 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001878 }
1879
Jamie Madill51f40ec2016-06-15 14:06:00 -04001880 const auto &glState = context->getGLState();
1881 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1882 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001883
1884 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001887 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001888 }
1889
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001890 if (readFramebuffer->id() == drawFramebuffer->id())
1891 {
1892 context->handleError(Error(GL_INVALID_OPERATION));
1893 return false;
1894 }
1895
Jamie Madill51f40ec2016-06-15 14:06:00 -04001896 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001897 {
Jamie Madill437fa652016-05-03 15:13:24 -04001898 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001899 return false;
1900 }
1901
Jamie Madill51f40ec2016-06-15 14:06:00 -04001902 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001905 return false;
1906 }
1907
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001908 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001912 }
1913
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001914 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1915
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001916 if (mask & GL_COLOR_BUFFER_BIT)
1917 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001918 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1919 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001920 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001921
1922 if (readColorBuffer && drawColorBuffer)
1923 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001924 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001925
Geoff Langa15472a2015-08-11 11:48:03 -04001926 for (size_t drawbufferIdx = 0;
1927 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001928 {
Geoff Langa15472a2015-08-11 11:48:03 -04001929 const FramebufferAttachment *attachment =
1930 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1931 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001932 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001933 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001934
Geoff Langb2f3d052013-08-13 12:49:27 -04001935 // The GL ES 3.0.2 spec (pg 193) states that:
1936 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1937 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1938 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001939 // Changes with EXT_color_buffer_float:
1940 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001941 GLenum readComponentType = readFormat.info->componentType;
1942 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001943 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1944 readComponentType == GL_SIGNED_NORMALIZED);
1945 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1946 drawComponentType == GL_SIGNED_NORMALIZED);
1947
1948 if (extensions.colorBufferFloat)
1949 {
1950 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1951 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1952
1953 if (readFixedOrFloat != drawFixedOrFloat)
1954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001956 "If the read buffer contains fixed-point or "
1957 "floating-point values, the draw buffer "
1958 "must as well."));
1959 return false;
1960 }
1961 }
1962 else if (readFixedPoint != drawFixedPoint)
1963 {
Jamie Madill437fa652016-05-03 15:13:24 -04001964 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001965 "If the read buffer contains fixed-point "
1966 "values, the draw buffer must as well."));
1967 return false;
1968 }
1969
1970 if (readComponentType == GL_UNSIGNED_INT &&
1971 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001975 }
1976
Jamie Madill6163c752015-12-07 16:32:59 -05001977 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001980 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 }
1982
Jamie Madilla3944d42016-07-22 22:13:26 -04001983 if (readColorBuffer->getSamples() > 0 &&
1984 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 {
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001988 }
1989 }
1990 }
1991
Jamie Madilla3944d42016-07-22 22:13:26 -04001992 if ((readFormat.info->componentType == GL_INT ||
1993 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1994 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001995 {
Jamie Madill437fa652016-05-03 15:13:24 -04001996 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001998 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001999 }
2000 }
2001
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002002 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2003 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2004 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002005 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002006 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002007 {
Jamie Madill2d06b732015-04-20 12:53:28 -04002008 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
2009 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002010
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002011 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002012 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002013 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
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 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002018
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002019 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002023 }
2024 }
2025 }
2026 }
2027
2028 return true;
2029}
2030
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002031bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 GLint x,
2033 GLint y,
2034 GLsizei width,
2035 GLsizei height,
2036 GLenum format,
2037 GLenum type,
2038 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002039{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002040 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2041}
2042
2043bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2044 GLint x,
2045 GLint y,
2046 GLsizei width,
2047 GLsizei height,
2048 GLenum format,
2049 GLenum type,
2050 GLsizei bufSize,
2051 GLsizei *length,
2052 GLvoid *pixels)
2053{
2054 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002055 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002056 return false;
2057 }
2058
Geoff Lang62fce5b2016-09-30 10:46:35 -04002059 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2060 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002061 {
Geoff Langb1196682014-07-23 13:47:29 -04002062 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002063 }
2064
Geoff Lang62fce5b2016-09-30 10:46:35 -04002065 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002066 {
Geoff Langb1196682014-07-23 13:47:29 -04002067 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002068 }
2069
Jamie Madillc29968b2016-01-20 11:17:23 -05002070 return true;
2071}
2072
2073bool ValidateReadnPixelsEXT(Context *context,
2074 GLint x,
2075 GLint y,
2076 GLsizei width,
2077 GLsizei height,
2078 GLenum format,
2079 GLenum type,
2080 GLsizei bufSize,
2081 GLvoid *pixels)
2082{
2083 if (bufSize < 0)
2084 {
Jamie Madill437fa652016-05-03 15:13:24 -04002085 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002086 return false;
2087 }
2088
Geoff Lang62fce5b2016-09-30 10:46:35 -04002089 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2090 pixels);
2091}
Jamie Madill26e91952014-03-05 15:01:27 -05002092
Geoff Lang62fce5b2016-09-30 10:46:35 -04002093bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2094 GLint x,
2095 GLint y,
2096 GLsizei width,
2097 GLsizei height,
2098 GLenum format,
2099 GLenum type,
2100 GLsizei bufSize,
2101 GLsizei *length,
2102 GLvoid *data)
2103{
2104 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002105 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002106 return false;
2107 }
2108
Geoff Lang62fce5b2016-09-30 10:46:35 -04002109 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002110 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002111 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002112 }
2113
Geoff Lang62fce5b2016-09-30 10:46:35 -04002114 if (!ValidateRobustBufferSize(context, bufSize, *length))
2115 {
2116 return false;
2117 }
2118
2119 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002120}
2121
Olli Etuaho41997e72016-03-10 13:38:39 +02002122bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002123{
2124 if (!context->getExtensions().occlusionQueryBoolean &&
2125 !context->getExtensions().disjointTimerQuery)
2126 {
Jamie Madill437fa652016-05-03 15:13:24 -04002127 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002128 return false;
2129 }
2130
Olli Etuaho41997e72016-03-10 13:38:39 +02002131 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002132}
2133
Olli Etuaho41997e72016-03-10 13:38:39 +02002134bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002135{
2136 if (!context->getExtensions().occlusionQueryBoolean &&
2137 !context->getExtensions().disjointTimerQuery)
2138 {
Jamie Madill437fa652016-05-03 15:13:24 -04002139 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002140 return false;
2141 }
2142
Olli Etuaho41997e72016-03-10 13:38:39 +02002143 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002144}
2145
2146bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002147{
2148 if (!ValidQueryType(context, target))
2149 {
Jamie Madill437fa652016-05-03 15:13:24 -04002150 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002151 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002152 }
2153
2154 if (id == 0)
2155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002157 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002158 }
2159
2160 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2161 // of zero, if the active query object name for <target> is non-zero (for the
2162 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2163 // the active query for either target is non-zero), if <id> is the name of an
2164 // existing query object whose type does not match <target>, or if <id> is the
2165 // active query object name for any query type, the error INVALID_OPERATION is
2166 // generated.
2167
2168 // Ensure no other queries are active
2169 // NOTE: If other queries than occlusion are supported, we will need to check
2170 // separately that:
2171 // a) The query ID passed is not the current active query for any target/type
2172 // b) There are no active queries for the requested target (and in the case
2173 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2174 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002175
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002176 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002180 }
2181
2182 Query *queryObject = context->getQuery(id, true, target);
2183
2184 // check that name was obtained with glGenQueries
2185 if (!queryObject)
2186 {
Jamie Madill437fa652016-05-03 15:13:24 -04002187 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002189 }
2190
2191 // check for type mismatch
2192 if (queryObject->getType() != target)
2193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002196 }
2197
2198 return true;
2199}
2200
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002201bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2202{
2203 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002204 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002207 return false;
2208 }
2209
2210 return ValidateBeginQueryBase(context, target, id);
2211}
2212
2213bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002214{
2215 if (!ValidQueryType(context, target))
2216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002218 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002219 }
2220
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002221 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002222
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002223 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002226 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002227 }
2228
Jamie Madill45c785d2014-05-13 14:09:34 -04002229 return true;
2230}
2231
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002232bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
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 ValidateEndQueryBase(context, target);
2242}
2243
2244bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2245{
2246 if (!context->getExtensions().disjointTimerQuery)
2247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249 return false;
2250 }
2251
2252 if (target != GL_TIMESTAMP_EXT)
2253 {
Jamie Madill437fa652016-05-03 15:13:24 -04002254 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002255 return false;
2256 }
2257
2258 Query *queryObject = context->getQuery(id, true, target);
2259 if (queryObject == nullptr)
2260 {
Jamie Madill437fa652016-05-03 15:13:24 -04002261 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002262 return false;
2263 }
2264
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002265 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002266 {
Jamie Madill437fa652016-05-03 15:13:24 -04002267 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002268 return false;
2269 }
2270
2271 return true;
2272}
2273
Geoff Lang2186c382016-10-14 10:54:54 -04002274bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002275{
Geoff Lang2186c382016-10-14 10:54:54 -04002276 if (numParams)
2277 {
2278 *numParams = 0;
2279 }
2280
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002281 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2282 {
Jamie Madill437fa652016-05-03 15:13:24 -04002283 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002284 return false;
2285 }
2286
2287 switch (pname)
2288 {
2289 case GL_CURRENT_QUERY_EXT:
2290 if (target == GL_TIMESTAMP_EXT)
2291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2294 return false;
2295 }
2296 break;
2297 case GL_QUERY_COUNTER_BITS_EXT:
2298 if (!context->getExtensions().disjointTimerQuery ||
2299 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2300 {
Jamie Madill437fa652016-05-03 15:13:24 -04002301 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002302 return false;
2303 }
2304 break;
2305 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002306 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002307 return false;
2308 }
2309
Geoff Lang2186c382016-10-14 10:54:54 -04002310 if (numParams)
2311 {
2312 // All queries return only one value
2313 *numParams = 1;
2314 }
2315
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002316 return true;
2317}
2318
2319bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2320{
2321 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002322 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002325 return false;
2326 }
2327
Geoff Lang2186c382016-10-14 10:54:54 -04002328 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002329}
2330
Geoff Lang2186c382016-10-14 10:54:54 -04002331bool ValidateGetQueryivRobustANGLE(Context *context,
2332 GLenum target,
2333 GLenum pname,
2334 GLsizei bufSize,
2335 GLsizei *length,
2336 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337{
Geoff Lang2186c382016-10-14 10:54:54 -04002338 if (!ValidateRobustEntryPoint(context, bufSize))
2339 {
2340 return false;
2341 }
2342
2343 if (!ValidateGetQueryivBase(context, target, pname, length))
2344 {
2345 return false;
2346 }
2347
2348 if (!ValidateRobustBufferSize(context, bufSize, *length))
2349 {
2350 return false;
2351 }
2352
2353 return true;
2354}
2355
2356bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2357{
2358 if (numParams)
2359 {
2360 *numParams = 0;
2361 }
2362
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002363 Query *queryObject = context->getQuery(id, false, GL_NONE);
2364
2365 if (!queryObject)
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368 return false;
2369 }
2370
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002371 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002372 {
Jamie Madill437fa652016-05-03 15:13:24 -04002373 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002374 return false;
2375 }
2376
2377 switch (pname)
2378 {
2379 case GL_QUERY_RESULT_EXT:
2380 case GL_QUERY_RESULT_AVAILABLE_EXT:
2381 break;
2382
2383 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002384 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002385 return false;
2386 }
2387
Geoff Lang2186c382016-10-14 10:54:54 -04002388 if (numParams)
2389 {
2390 *numParams = 1;
2391 }
2392
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002393 return true;
2394}
2395
2396bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2397{
2398 if (!context->getExtensions().disjointTimerQuery)
2399 {
Jamie Madill437fa652016-05-03 15:13:24 -04002400 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002401 return false;
2402 }
Geoff Lang2186c382016-10-14 10:54:54 -04002403 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2404}
2405
2406bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2407 GLuint id,
2408 GLenum pname,
2409 GLsizei bufSize,
2410 GLsizei *length,
2411 GLint *params)
2412{
2413 if (!context->getExtensions().disjointTimerQuery)
2414 {
2415 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2416 return false;
2417 }
2418
2419 if (!ValidateRobustEntryPoint(context, bufSize))
2420 {
2421 return false;
2422 }
2423
2424 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2425 {
2426 return false;
2427 }
2428
2429 if (!ValidateRobustBufferSize(context, bufSize, *length))
2430 {
2431 return false;
2432 }
2433
2434 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002435}
2436
2437bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2438{
2439 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002440 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002441 {
Jamie Madill437fa652016-05-03 15:13:24 -04002442 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002443 return false;
2444 }
Geoff Lang2186c382016-10-14 10:54:54 -04002445 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2446}
2447
2448bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2449 GLuint id,
2450 GLenum pname,
2451 GLsizei bufSize,
2452 GLsizei *length,
2453 GLuint *params)
2454{
2455 if (!context->getExtensions().disjointTimerQuery &&
2456 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2457 {
2458 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2459 return false;
2460 }
2461
2462 if (!ValidateRobustEntryPoint(context, bufSize))
2463 {
2464 return false;
2465 }
2466
2467 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2468 {
2469 return false;
2470 }
2471
2472 if (!ValidateRobustBufferSize(context, bufSize, *length))
2473 {
2474 return false;
2475 }
2476
2477 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002478}
2479
2480bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2481{
2482 if (!context->getExtensions().disjointTimerQuery)
2483 {
Jamie Madill437fa652016-05-03 15:13:24 -04002484 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002485 return false;
2486 }
Geoff Lang2186c382016-10-14 10:54:54 -04002487 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2488}
2489
2490bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2491 GLuint id,
2492 GLenum pname,
2493 GLsizei bufSize,
2494 GLsizei *length,
2495 GLint64 *params)
2496{
2497 if (!context->getExtensions().disjointTimerQuery)
2498 {
2499 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2500 return false;
2501 }
2502
2503 if (!ValidateRobustEntryPoint(context, bufSize))
2504 {
2505 return false;
2506 }
2507
2508 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2509 {
2510 return false;
2511 }
2512
2513 if (!ValidateRobustBufferSize(context, bufSize, *length))
2514 {
2515 return false;
2516 }
2517
2518 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002519}
2520
2521bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2522{
2523 if (!context->getExtensions().disjointTimerQuery)
2524 {
Jamie Madill437fa652016-05-03 15:13:24 -04002525 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002526 return false;
2527 }
Geoff Lang2186c382016-10-14 10:54:54 -04002528 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2529}
2530
2531bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2532 GLuint id,
2533 GLenum pname,
2534 GLsizei bufSize,
2535 GLsizei *length,
2536 GLuint64 *params)
2537{
2538 if (!context->getExtensions().disjointTimerQuery)
2539 {
2540 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2541 return false;
2542 }
2543
2544 if (!ValidateRobustEntryPoint(context, bufSize))
2545 {
2546 return false;
2547 }
2548
2549 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2550 {
2551 return false;
2552 }
2553
2554 if (!ValidateRobustBufferSize(context, bufSize, *length))
2555 {
2556 return false;
2557 }
2558
2559 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002560}
2561
Jamie Madill62d31cb2015-09-11 13:25:51 -04002562static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002563 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002564 GLenum targetUniformType,
2565 GLint location,
2566 GLsizei count,
2567 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002568{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002569 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002570 if (count < 0)
2571 {
Jamie Madill437fa652016-05-03 15:13:24 -04002572 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002573 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002574 }
2575
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002576 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002577 {
Jamie Madill437fa652016-05-03 15:13:24 -04002578 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002579 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002580 }
2581
Geoff Langd8605522016-04-13 10:19:12 -04002582 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002583 {
2584 // Silently ignore the uniform command
2585 return false;
2586 }
2587
Geoff Lang7dd2e102014-11-10 15:19:26 -05002588 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002589 {
Jamie Madill437fa652016-05-03 15:13:24 -04002590 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002591 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002592 }
2593
Jamie Madill62d31cb2015-09-11 13:25:51 -04002594 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002595
2596 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002597 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002598 {
Jamie Madill437fa652016-05-03 15:13:24 -04002599 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002600 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002601 }
2602
Jamie Madill62d31cb2015-09-11 13:25:51 -04002603 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002604 return true;
2605}
2606
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002607bool ValidateProgramUniform(gl::Context *context,
2608 GLenum uniformType,
2609 GLuint program,
2610 GLint location,
2611 GLsizei count)
2612{
2613 // Check for ES31 program uniform entry points
2614 if (context->getClientVersion() < Version(3, 1))
2615 {
2616 context->handleError(Error(GL_INVALID_OPERATION));
2617 return false;
2618 }
2619
2620 const LinkedUniform *uniform = nullptr;
2621 gl::Program *programObject = GetValidProgram(context, program);
2622 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2623 {
2624 return false;
2625 }
2626
2627 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2628 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2629 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2630 {
2631 context->handleError(Error(GL_INVALID_OPERATION));
2632 return false;
2633 }
2634
2635 return true;
2636}
2637
2638bool ValidateProgramUniformMatrix(gl::Context *context,
2639 GLenum matrixType,
2640 GLuint program,
2641 GLint location,
2642 GLsizei count,
2643 GLboolean transpose)
2644{
2645 // Check for ES31 program uniform entry points
2646 if (context->getClientVersion() < Version(3, 1))
2647 {
2648 context->handleError(Error(GL_INVALID_OPERATION));
2649 return false;
2650 }
2651
2652 const LinkedUniform *uniform = nullptr;
2653 gl::Program *programObject = GetValidProgram(context, program);
2654 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2655 {
2656 return false;
2657 }
2658
2659 if (uniform->type != matrixType)
2660 {
2661 context->handleError(Error(GL_INVALID_OPERATION));
2662 return false;
2663 }
2664
2665 return true;
2666}
2667
Jamie Madillaa981bd2014-05-20 10:55:55 -04002668bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2669{
2670 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002671 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2672 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002673 {
Jamie Madill437fa652016-05-03 15:13:24 -04002674 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002675 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002676 }
2677
Jamie Madill62d31cb2015-09-11 13:25:51 -04002678 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002679 gl::Program *program = context->getGLState().getProgram();
2680 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002681 {
2682 return false;
2683 }
2684
Jamie Madillf2575982014-06-25 16:04:54 -04002685 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002686 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002687 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2688 {
Jamie Madill437fa652016-05-03 15:13:24 -04002689 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002690 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002691 }
2692
2693 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002694}
2695
2696bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2697 GLboolean transpose)
2698{
2699 // Check for ES3 uniform entry points
2700 int rows = VariableRowCount(matrixType);
2701 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002702 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002703 {
Jamie Madill437fa652016-05-03 15:13:24 -04002704 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002705 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002706 }
2707
Martin Radev1be913c2016-07-11 17:59:16 +03002708 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002709 {
Jamie Madill437fa652016-05-03 15:13:24 -04002710 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002711 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002712 }
2713
Jamie Madill62d31cb2015-09-11 13:25:51 -04002714 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002715 gl::Program *program = context->getGLState().getProgram();
2716 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002717 {
2718 return false;
2719 }
2720
2721 if (uniform->type != matrixType)
2722 {
Jamie Madill437fa652016-05-03 15:13:24 -04002723 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002724 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002725 }
2726
2727 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002728}
2729
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002730bool ValidateStateQuery(ValidationContext *context,
2731 GLenum pname,
2732 GLenum *nativeType,
2733 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002734{
2735 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2736 {
Jamie Madill437fa652016-05-03 15:13:24 -04002737 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002738 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002739 }
2740
Jamie Madill0af26e12015-03-05 19:54:33 -05002741 const Caps &caps = context->getCaps();
2742
Jamie Madill893ab082014-05-16 16:56:10 -04002743 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2744 {
2745 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2746
Jamie Madill0af26e12015-03-05 19:54:33 -05002747 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002748 {
Jamie Madill437fa652016-05-03 15:13:24 -04002749 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002750 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002751 }
2752 }
2753
2754 switch (pname)
2755 {
2756 case GL_TEXTURE_BINDING_2D:
2757 case GL_TEXTURE_BINDING_CUBE_MAP:
2758 case GL_TEXTURE_BINDING_3D:
2759 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002760 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002761 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002762 if (!context->getExtensions().eglStreamConsumerExternal &&
2763 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002764 {
John Bauman18319182016-09-28 14:22:27 -07002765 context->handleError(Error(GL_INVALID_ENUM,
2766 "Neither NV_EGL_stream_consumer_external nor "
2767 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002768 return false;
2769 }
2770 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002771
2772 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2773 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2774 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002775 if (context->getGLState().getReadFramebuffer()->checkStatus(
2776 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002777 {
Jamie Madill437fa652016-05-03 15:13:24 -04002778 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002779 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002780 }
2781
Jamie Madill51f40ec2016-06-15 14:06:00 -04002782 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2783 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002784
2785 if (framebuffer->getReadBufferState() == GL_NONE)
2786 {
2787 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2788 return false;
2789 }
2790
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002791 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002792 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002793 {
Jamie Madill437fa652016-05-03 15:13:24 -04002794 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002795 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002796 }
2797 }
2798 break;
2799
2800 default:
2801 break;
2802 }
2803
2804 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002805 if (*numParams == 0)
2806 {
2807 return false;
2808 }
2809
2810 return true;
2811}
2812
2813bool ValidateRobustStateQuery(ValidationContext *context,
2814 GLenum pname,
2815 GLsizei bufSize,
2816 GLenum *nativeType,
2817 unsigned int *numParams)
2818{
2819 if (!ValidateRobustEntryPoint(context, bufSize))
2820 {
2821 return false;
2822 }
2823
2824 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2825 {
2826 return false;
2827 }
2828
2829 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002830 {
2831 return false;
2832 }
2833
2834 return true;
2835}
2836
Jamie Madillc29968b2016-01-20 11:17:23 -05002837bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2838 GLenum target,
2839 GLint level,
2840 GLenum internalformat,
2841 bool isSubImage,
2842 GLint xoffset,
2843 GLint yoffset,
2844 GLint zoffset,
2845 GLint x,
2846 GLint y,
2847 GLsizei width,
2848 GLsizei height,
2849 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002850 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002851{
Jamie Madill560a8d82014-05-21 13:06:20 -04002852 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2853 {
Jamie Madill437fa652016-05-03 15:13:24 -04002854 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002855 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002856 }
2857
2858 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2859 {
Jamie Madill437fa652016-05-03 15:13:24 -04002860 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002861 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002862 }
2863
2864 if (border != 0)
2865 {
Jamie Madill437fa652016-05-03 15:13:24 -04002866 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002867 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002868 }
2869
2870 if (!ValidMipLevel(context, target, level))
2871 {
Jamie Madill437fa652016-05-03 15:13:24 -04002872 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002873 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002874 }
2875
Jamie Madill51f40ec2016-06-15 14:06:00 -04002876 const auto &state = context->getGLState();
2877 auto readFramebuffer = state.getReadFramebuffer();
2878 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002879 {
Jamie Madill437fa652016-05-03 15:13:24 -04002880 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002881 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002882 }
2883
Jamie Madill51f40ec2016-06-15 14:06:00 -04002884 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002885 {
Jamie Madill437fa652016-05-03 15:13:24 -04002886 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002887 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002888 }
2889
Martin Radev138064f2016-07-15 12:03:41 +03002890 if (readFramebuffer->getReadBufferState() == GL_NONE)
2891 {
2892 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2893 return false;
2894 }
2895
Geoff Langaae65a42014-05-26 12:43:44 -04002896 const gl::Caps &caps = context->getCaps();
2897
Geoff Langaae65a42014-05-26 12:43:44 -04002898 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002899 switch (target)
2900 {
2901 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002902 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002903 break;
2904
2905 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2907 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2908 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2909 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2910 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002911 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002912 break;
2913
2914 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002915 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002916 break;
2917
2918 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002919 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002920 break;
2921
2922 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002923 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002925 }
2926
Jamie Madillc29968b2016-01-20 11:17:23 -05002927 gl::Texture *texture =
2928 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002929 if (!texture)
2930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002933 }
2934
Geoff Lang69cce582015-09-17 13:20:36 -04002935 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002936 {
Jamie Madill437fa652016-05-03 15:13:24 -04002937 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002938 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002939 }
2940
Geoff Lang5d601382014-07-22 15:14:06 -04002941 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2942
2943 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002944 {
Jamie Madill437fa652016-05-03 15:13:24 -04002945 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002946 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002947 }
2948
Geoff Langa9be0dc2014-12-17 12:34:40 -05002949 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002950 {
Jamie Madill437fa652016-05-03 15:13:24 -04002951 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002952 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002953 }
2954
2955 if (isSubImage)
2956 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002957 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2958 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2959 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002960 {
Jamie Madill437fa652016-05-03 15:13:24 -04002961 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002962 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002963 }
2964 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002965 else
2966 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002967 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002968 {
Jamie Madill437fa652016-05-03 15:13:24 -04002969 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002970 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002971 }
2972
Geoff Langeb66a6e2016-10-31 13:06:12 -04002973 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002974 {
Jamie Madill437fa652016-05-03 15:13:24 -04002975 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002976 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002977 }
2978
2979 int maxLevelDimension = (maxDimension >> level);
2980 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2981 {
Jamie Madill437fa652016-05-03 15:13:24 -04002982 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002984 }
2985 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002986
Jamie Madill0c8abca2016-07-22 20:21:26 -04002987 if (textureFormatOut)
2988 {
2989 *textureFormatOut = texture->getFormat(target, level);
2990 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002991 return true;
2992}
2993
Jamie Madillf25855c2015-11-03 11:06:18 -05002994static bool ValidateDrawBase(ValidationContext *context,
2995 GLenum mode,
2996 GLsizei count,
2997 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002998{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002999 switch (mode)
3000 {
3001 case GL_POINTS:
3002 case GL_LINES:
3003 case GL_LINE_LOOP:
3004 case GL_LINE_STRIP:
3005 case GL_TRIANGLES:
3006 case GL_TRIANGLE_STRIP:
3007 case GL_TRIANGLE_FAN:
3008 break;
3009 default:
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 Madill1aeb1312014-06-20 13:21:25 -04003012 }
3013
Jamie Madill250d33f2014-06-06 17:09:03 -04003014 if (count < 0)
3015 {
Jamie Madill437fa652016-05-03 15:13:24 -04003016 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003017 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003018 }
3019
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003020 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003021
Jamie Madill250d33f2014-06-06 17:09:03 -04003022 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003023 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003024 {
Jamie Madill437fa652016-05-03 15:13:24 -04003025 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003026 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003027 }
3028
Jamie Madill51f40ec2016-06-15 14:06:00 -04003029 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003030 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003031 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003032 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
3033 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3034 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
3035 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3036 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3037 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003038 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003039 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3040 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003041 {
3042 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3043 // Section 6.10 of the WebGL 1.0 spec
3044 ERR(
3045 "This ANGLE implementation does not support separate front/back stencil "
3046 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003047 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003048 return false;
3049 }
Jamie Madillac528012014-06-20 13:21:23 -04003050 }
3051
Jamie Madill51f40ec2016-06-15 14:06:00 -04003052 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003053 {
Jamie Madill437fa652016-05-03 15:13:24 -04003054 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003055 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003056 }
3057
Geoff Lang7dd2e102014-11-10 15:19:26 -05003058 gl::Program *program = state.getProgram();
3059 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -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 Madilld4cfa572014-07-08 10:00:32 -04003063 }
3064
Geoff Lang7dd2e102014-11-10 15:19:26 -05003065 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003066 {
Jamie Madill437fa652016-05-03 15:13:24 -04003067 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003068 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003069 }
3070
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003071 // Uniform buffer validation
3072 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
3073 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003074 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003075 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003076 const OffsetBindingPointer<Buffer> &uniformBuffer =
3077 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003078
Geoff Lang5d124a62015-09-15 13:03:27 -04003079 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003080 {
3081 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003082 context->handleError(
3083 Error(GL_INVALID_OPERATION,
3084 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003085 return false;
3086 }
3087
Geoff Lang5d124a62015-09-15 13:03:27 -04003088 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003089 if (uniformBufferSize == 0)
3090 {
3091 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003092 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003093 }
3094
Jamie Madill62d31cb2015-09-11 13:25:51 -04003095 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003096 {
3097 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003098 context->handleError(
3099 Error(GL_INVALID_OPERATION,
3100 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003101 return false;
3102 }
3103 }
3104
Jamie Madill250d33f2014-06-06 17:09:03 -04003105 // No-op if zero count
3106 return (count > 0);
3107}
3108
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003109bool ValidateDrawArrays(ValidationContext *context,
3110 GLenum mode,
3111 GLint first,
3112 GLsizei count,
3113 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003114{
Jamie Madillfd716582014-06-06 17:09:04 -04003115 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003116 {
Jamie Madill437fa652016-05-03 15:13:24 -04003117 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003118 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003119 }
3120
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003121 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003122 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003123 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
3124 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003125 {
3126 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
3127 // that does not match the current transform feedback object's draw mode (if transform feedback
3128 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003129 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003130 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003131 }
3132
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003133 if (!ValidateDrawBase(context, mode, count, primcount))
3134 {
3135 return false;
3136 }
3137
3138 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003139 {
3140 return false;
3141 }
3142
3143 return true;
3144}
3145
Geoff Langb1196682014-07-23 13:47:29 -04003146bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003147{
3148 if (primcount < 0)
3149 {
Jamie Madill437fa652016-05-03 15:13:24 -04003150 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003151 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003152 }
3153
Jamie Madill2b976812014-08-25 15:47:49 -04003154 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003155 {
3156 return false;
3157 }
3158
3159 // No-op if zero primitive count
3160 return (primcount > 0);
3161}
3162
Geoff Lang87a93302014-09-16 13:29:43 -04003163static bool ValidateDrawInstancedANGLE(Context *context)
3164{
3165 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003166 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003167
Geoff Lang7dd2e102014-11-10 15:19:26 -05003168 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003169
3170 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003171 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003172 {
3173 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003174 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003175 {
3176 return true;
3177 }
3178 }
3179
Jamie Madill437fa652016-05-03 15:13:24 -04003180 context->handleError(Error(GL_INVALID_OPERATION,
3181 "ANGLE_instanced_arrays requires that at least one active attribute"
3182 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003183 return false;
3184}
3185
3186bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
3187{
3188 if (!ValidateDrawInstancedANGLE(context))
3189 {
3190 return false;
3191 }
3192
3193 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3194}
3195
Jamie Madillf25855c2015-11-03 11:06:18 -05003196bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003197 GLenum mode,
3198 GLsizei count,
3199 GLenum type,
3200 const GLvoid *indices,
3201 GLsizei primcount,
3202 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003203{
Jamie Madill250d33f2014-06-06 17:09:03 -04003204 switch (type)
3205 {
3206 case GL_UNSIGNED_BYTE:
3207 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03003208 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003209 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03003210 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3211 {
3212 context->handleError(Error(GL_INVALID_ENUM));
3213 return false;
3214 }
3215 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003216 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003217 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003218 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003219 }
3220
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003221 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003222
3223 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003224 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003225 {
3226 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3227 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003228 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003229 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003230 }
3231
3232 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003233 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003234 {
Jamie Madill437fa652016-05-03 15:13:24 -04003235 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003236 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003237 }
3238
Jamie Madill2b976812014-08-25 15:47:49 -04003239 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003240 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003241 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003242 {
Jamie Madill437fa652016-05-03 15:13:24 -04003243 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003244 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003245 }
3246
Jamie Madillae3000b2014-08-25 15:47:51 -04003247 if (elementArrayBuffer)
3248 {
3249 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3250
3251 GLint64 offset = reinterpret_cast<GLint64>(indices);
3252 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3253
3254 // check for integer overflows
3255 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3256 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3257 {
Jamie Madill437fa652016-05-03 15:13:24 -04003258 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003260 }
3261
3262 // Check for reading past the end of the bound buffer object
3263 if (byteCount > elementArrayBuffer->getSize())
3264 {
Jamie Madill437fa652016-05-03 15:13:24 -04003265 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003266 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003267 }
3268 }
3269 else if (!indices)
3270 {
3271 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003272 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003273 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003274 }
3275
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003276 if (!ValidateDrawBase(context, mode, count, primcount))
3277 {
3278 return false;
3279 }
3280
Jamie Madill2b976812014-08-25 15:47:49 -04003281 // Use max index to validate if our vertex buffers are large enough for the pull.
3282 // TODO: offer fast path, with disabled index validation.
3283 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3284 if (elementArrayBuffer)
3285 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003286 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003287 Error error =
3288 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3289 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003290 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003291 {
Jamie Madill437fa652016-05-03 15:13:24 -04003292 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003293 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003294 }
3295 }
3296 else
3297 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003298 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003299 }
3300
Jamie Madille79b1e12015-11-04 16:36:37 -05003301 // If we use an index greater than our maximum supported index range, return an error.
3302 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3303 // return an error if possible here.
3304 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3305 {
Jamie Madill437fa652016-05-03 15:13:24 -04003306 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003307 return false;
3308 }
3309
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003310 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003311 {
3312 return false;
3313 }
3314
Geoff Lang3edfe032015-09-04 16:38:24 -04003315 // No op if there are no real indices in the index data (all are primitive restart).
3316 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003317}
3318
Geoff Langb1196682014-07-23 13:47:29 -04003319bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003320 GLenum mode,
3321 GLsizei count,
3322 GLenum type,
3323 const GLvoid *indices,
3324 GLsizei primcount,
3325 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003326{
3327 if (primcount < 0)
3328 {
Jamie Madill437fa652016-05-03 15:13:24 -04003329 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003330 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003331 }
3332
Jamie Madill2b976812014-08-25 15:47:49 -04003333 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003334 {
3335 return false;
3336 }
3337
3338 // No-op zero primitive count
3339 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003340}
3341
Geoff Lang3edfe032015-09-04 16:38:24 -04003342bool ValidateDrawElementsInstancedANGLE(Context *context,
3343 GLenum mode,
3344 GLsizei count,
3345 GLenum type,
3346 const GLvoid *indices,
3347 GLsizei primcount,
3348 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003349{
3350 if (!ValidateDrawInstancedANGLE(context))
3351 {
3352 return false;
3353 }
3354
3355 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3356}
3357
Geoff Langb1196682014-07-23 13:47:29 -04003358bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003359 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003360{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003361 if (!ValidFramebufferTarget(target))
3362 {
Jamie Madill437fa652016-05-03 15:13:24 -04003363 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003364 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003365 }
3366
3367 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003368 {
3369 return false;
3370 }
3371
Jamie Madill55ec3b12014-07-03 10:38:57 -04003372 if (texture != 0)
3373 {
3374 gl::Texture *tex = context->getTexture(texture);
3375
3376 if (tex == NULL)
3377 {
Jamie Madill437fa652016-05-03 15:13:24 -04003378 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003379 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003380 }
3381
3382 if (level < 0)
3383 {
Jamie Madill437fa652016-05-03 15:13:24 -04003384 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003385 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003386 }
3387 }
3388
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003389 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003390 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003391
Jamie Madill84115c92015-04-23 15:00:07 -04003392 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003393 {
Jamie Madill437fa652016-05-03 15:13:24 -04003394 context->handleError(
3395 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003396 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003397 }
3398
3399 return true;
3400}
3401
Geoff Langb1196682014-07-23 13:47:29 -04003402bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003403 GLenum textarget, GLuint texture, GLint level)
3404{
Geoff Lang95663912015-04-02 15:54:45 -04003405 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap extension
Martin Radev1be913c2016-07-11 17:59:16 +03003406 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3407 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003408 {
Jamie Madill437fa652016-05-03 15:13:24 -04003409 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003410 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003411 }
3412
3413 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003414 {
3415 return false;
3416 }
3417
Jamie Madill55ec3b12014-07-03 10:38:57 -04003418 if (texture != 0)
3419 {
3420 gl::Texture *tex = context->getTexture(texture);
3421 ASSERT(tex);
3422
Jamie Madill2a6564e2014-07-11 09:53:19 -04003423 const gl::Caps &caps = context->getCaps();
3424
Jamie Madill55ec3b12014-07-03 10:38:57 -04003425 switch (textarget)
3426 {
3427 case GL_TEXTURE_2D:
3428 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003429 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003430 {
Jamie Madill437fa652016-05-03 15:13:24 -04003431 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003432 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003433 }
3434 if (tex->getTarget() != GL_TEXTURE_2D)
3435 {
Jamie Madill437fa652016-05-03 15:13:24 -04003436 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003437 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003438 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003439 }
3440 break;
3441
3442 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3443 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3444 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3445 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3446 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3447 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3448 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003449 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003450 {
Jamie Madill437fa652016-05-03 15:13:24 -04003451 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003452 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003453 }
3454 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3455 {
Jamie Madill437fa652016-05-03 15:13:24 -04003456 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003457 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003458 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003459 }
3460 break;
3461
3462 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003463 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003464 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003465 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003466
Jamie Madilla3944d42016-07-22 22:13:26 -04003467 const Format &format = tex->getFormat(textarget, level);
3468 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003469 {
Jamie Madill437fa652016-05-03 15:13:24 -04003470 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003471 return false;
3472 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003473 }
3474
Jamie Madill570f7c82014-07-03 10:38:54 -04003475 return true;
3476}
3477
Geoff Langb1196682014-07-23 13:47:29 -04003478bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003479{
3480 if (program == 0)
3481 {
Jamie Madill437fa652016-05-03 15:13:24 -04003482 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003483 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003484 }
3485
Dian Xiang769769a2015-09-09 15:20:08 -07003486 gl::Program *programObject = GetValidProgram(context, program);
3487 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003488 {
3489 return false;
3490 }
3491
Jamie Madill0063c512014-08-25 15:47:53 -04003492 if (!programObject || !programObject->isLinked())
3493 {
Jamie Madill437fa652016-05-03 15:13:24 -04003494 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003495 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003496 }
3497
Geoff Lang7dd2e102014-11-10 15:19:26 -05003498 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003499 {
Jamie Madill437fa652016-05-03 15:13:24 -04003500 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003501 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003502 }
3503
Jamie Madill0063c512014-08-25 15:47:53 -04003504 return true;
3505}
3506
Geoff Langb1196682014-07-23 13:47:29 -04003507bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003508{
3509 return ValidateGetUniformBase(context, program, location);
3510}
3511
Geoff Langb1196682014-07-23 13:47:29 -04003512bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003513{
Jamie Madill78f41802014-08-25 15:47:55 -04003514 return ValidateGetUniformBase(context, program, location);
3515}
3516
Geoff Langf41d0ee2016-10-07 13:04:23 -04003517static bool ValidateSizedGetUniform(Context *context,
3518 GLuint program,
3519 GLint location,
3520 GLsizei bufSize,
3521 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003522{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003523 if (length)
3524 {
3525 *length = 0;
3526 }
3527
Jamie Madill78f41802014-08-25 15:47:55 -04003528 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003529 {
Jamie Madill78f41802014-08-25 15:47:55 -04003530 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003531 }
3532
Geoff Langf41d0ee2016-10-07 13:04:23 -04003533 if (bufSize < 0)
3534 {
3535 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3536 return false;
3537 }
3538
Jamie Madilla502c742014-08-28 17:19:13 -04003539 gl::Program *programObject = context->getProgram(program);
3540 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003541
Jamie Madill78f41802014-08-25 15:47:55 -04003542 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003543 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3544 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003545 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003546 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003547 context->handleError(
3548 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003549 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003550 }
3551
Geoff Langf41d0ee2016-10-07 13:04:23 -04003552 if (length)
3553 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003554 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003555 }
3556
Jamie Madill0063c512014-08-25 15:47:53 -04003557 return true;
3558}
3559
Geoff Langb1196682014-07-23 13:47:29 -04003560bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003561{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003562 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003563}
3564
Geoff Langb1196682014-07-23 13:47:29 -04003565bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003566{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003567 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3568}
3569
3570bool ValidateGetUniformfvRobustANGLE(Context *context,
3571 GLuint program,
3572 GLint location,
3573 GLsizei bufSize,
3574 GLsizei *length,
3575 GLfloat *params)
3576{
3577 if (!ValidateRobustEntryPoint(context, bufSize))
3578 {
3579 return false;
3580 }
3581
3582 // bufSize is validated in ValidateSizedGetUniform
3583 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3584}
3585
3586bool ValidateGetUniformivRobustANGLE(Context *context,
3587 GLuint program,
3588 GLint location,
3589 GLsizei bufSize,
3590 GLsizei *length,
3591 GLint *params)
3592{
3593 if (!ValidateRobustEntryPoint(context, bufSize))
3594 {
3595 return false;
3596 }
3597
3598 // bufSize is validated in ValidateSizedGetUniform
3599 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3600}
3601
3602bool ValidateGetUniformuivRobustANGLE(Context *context,
3603 GLuint program,
3604 GLint location,
3605 GLsizei bufSize,
3606 GLsizei *length,
3607 GLuint *params)
3608{
3609 if (!ValidateRobustEntryPoint(context, bufSize))
3610 {
3611 return false;
3612 }
3613
3614 if (context->getClientMajorVersion() < 3)
3615 {
3616 context->handleError(
3617 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3618 return false;
3619 }
3620
3621 // bufSize is validated in ValidateSizedGetUniform
3622 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003623}
3624
Austin Kinross08332632015-05-05 13:35:47 -07003625bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3626 const GLenum *attachments, bool defaultFramebuffer)
3627{
3628 if (numAttachments < 0)
3629 {
Jamie Madill437fa652016-05-03 15:13:24 -04003630 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003631 return false;
3632 }
3633
3634 for (GLsizei i = 0; i < numAttachments; ++i)
3635 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003636 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003637 {
3638 if (defaultFramebuffer)
3639 {
Jamie Madill437fa652016-05-03 15:13:24 -04003640 context->handleError(Error(
3641 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003642 return false;
3643 }
3644
3645 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3646 {
Jamie Madill437fa652016-05-03 15:13:24 -04003647 context->handleError(Error(GL_INVALID_OPERATION,
3648 "Requested color attachment is greater than the maximum "
3649 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003650 return false;
3651 }
3652 }
3653 else
3654 {
3655 switch (attachments[i])
3656 {
3657 case GL_DEPTH_ATTACHMENT:
3658 case GL_STENCIL_ATTACHMENT:
3659 case GL_DEPTH_STENCIL_ATTACHMENT:
3660 if (defaultFramebuffer)
3661 {
Jamie Madill437fa652016-05-03 15:13:24 -04003662 context->handleError(
3663 Error(GL_INVALID_ENUM,
3664 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003665 return false;
3666 }
3667 break;
3668 case GL_COLOR:
3669 case GL_DEPTH:
3670 case GL_STENCIL:
3671 if (!defaultFramebuffer)
3672 {
Jamie Madill437fa652016-05-03 15:13:24 -04003673 context->handleError(
3674 Error(GL_INVALID_ENUM,
3675 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003676 return false;
3677 }
3678 break;
3679 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003680 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003681 return false;
3682 }
3683 }
3684 }
3685
3686 return true;
3687}
3688
Austin Kinross6ee1e782015-05-29 17:05:37 -07003689bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3690{
3691 // Note that debug marker calls must not set error state
3692
3693 if (length < 0)
3694 {
3695 return false;
3696 }
3697
3698 if (marker == nullptr)
3699 {
3700 return false;
3701 }
3702
3703 return true;
3704}
3705
3706bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3707{
3708 // Note that debug marker calls must not set error state
3709
3710 if (length < 0)
3711 {
3712 return false;
3713 }
3714
3715 if (length > 0 && marker == nullptr)
3716 {
3717 return false;
3718 }
3719
3720 return true;
3721}
3722
Geoff Langdcab33b2015-07-21 13:03:16 -04003723bool ValidateEGLImageTargetTexture2DOES(Context *context,
3724 egl::Display *display,
3725 GLenum target,
3726 egl::Image *image)
3727{
Geoff Langa8406172015-07-21 16:53:39 -04003728 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003731 return false;
3732 }
3733
3734 switch (target)
3735 {
3736 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003737 if (!context->getExtensions().eglImage)
3738 {
3739 context->handleError(Error(
3740 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3741 }
3742 break;
3743
3744 case GL_TEXTURE_EXTERNAL_OES:
3745 if (!context->getExtensions().eglImageExternal)
3746 {
3747 context->handleError(Error(
3748 GL_INVALID_ENUM,
3749 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3750 }
Geoff Langa8406172015-07-21 16:53:39 -04003751 break;
3752
3753 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003754 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003755 return false;
3756 }
3757
3758 if (!display->isValidImage(image))
3759 {
Jamie Madill437fa652016-05-03 15:13:24 -04003760 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003761 return false;
3762 }
3763
3764 if (image->getSamples() > 0)
3765 {
Jamie Madill437fa652016-05-03 15:13:24 -04003766 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003767 "cannot create a 2D texture from a multisampled EGL image."));
3768 return false;
3769 }
3770
Jamie Madilla3944d42016-07-22 22:13:26 -04003771 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003772 if (!textureCaps.texturable)
3773 {
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003775 "EGL image internal format is not supported as a texture."));
3776 return false;
3777 }
3778
Geoff Langdcab33b2015-07-21 13:03:16 -04003779 return true;
3780}
3781
3782bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3783 egl::Display *display,
3784 GLenum target,
3785 egl::Image *image)
3786{
Geoff Langa8406172015-07-21 16:53:39 -04003787 if (!context->getExtensions().eglImage)
3788 {
Jamie Madill437fa652016-05-03 15:13:24 -04003789 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003790 return false;
3791 }
3792
3793 switch (target)
3794 {
3795 case GL_RENDERBUFFER:
3796 break;
3797
3798 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003799 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003800 return false;
3801 }
3802
3803 if (!display->isValidImage(image))
3804 {
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003806 return false;
3807 }
3808
Jamie Madilla3944d42016-07-22 22:13:26 -04003809 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003810 if (!textureCaps.renderable)
3811 {
Jamie Madill437fa652016-05-03 15:13:24 -04003812 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003813 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3814 return false;
3815 }
3816
Geoff Langdcab33b2015-07-21 13:03:16 -04003817 return true;
3818}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003819
3820bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3821{
Geoff Lang36167ab2015-12-07 10:27:14 -05003822 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003823 {
3824 // The default VAO should always exist
3825 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003826 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003827 return false;
3828 }
3829
3830 return true;
3831}
3832
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003833bool ValidateLinkProgram(Context *context, GLuint program)
3834{
3835 if (context->hasActiveTransformFeedback(program))
3836 {
3837 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003838 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003839 "Cannot link program while program is associated with an active "
3840 "transform feedback object."));
3841 return false;
3842 }
3843 return true;
3844}
3845
Geoff Langc5629752015-12-07 16:29:04 -05003846bool ValidateProgramBinaryBase(Context *context,
3847 GLuint program,
3848 GLenum binaryFormat,
3849 const void *binary,
3850 GLint length)
3851{
3852 Program *programObject = GetValidProgram(context, program);
3853 if (programObject == nullptr)
3854 {
3855 return false;
3856 }
3857
3858 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3859 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3860 programBinaryFormats.end())
3861 {
Jamie Madill437fa652016-05-03 15:13:24 -04003862 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003863 return false;
3864 }
3865
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003866 if (context->hasActiveTransformFeedback(program))
3867 {
3868 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003869 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003870 "Cannot change program binary while program is associated with "
3871 "an active transform feedback object."));
3872 return false;
3873 }
3874
Geoff Langc5629752015-12-07 16:29:04 -05003875 return true;
3876}
3877
3878bool ValidateGetProgramBinaryBase(Context *context,
3879 GLuint program,
3880 GLsizei bufSize,
3881 GLsizei *length,
3882 GLenum *binaryFormat,
3883 void *binary)
3884{
3885 Program *programObject = GetValidProgram(context, program);
3886 if (programObject == nullptr)
3887 {
3888 return false;
3889 }
3890
3891 if (!programObject->isLinked())
3892 {
Jamie Madill437fa652016-05-03 15:13:24 -04003893 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003894 return false;
3895 }
3896
3897 return true;
3898}
Jamie Madillc29968b2016-01-20 11:17:23 -05003899
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003900bool ValidateUseProgram(Context *context, GLuint program)
3901{
3902 if (program != 0)
3903 {
3904 Program *programObject = context->getProgram(program);
3905 if (!programObject)
3906 {
3907 // ES 3.1.0 section 7.3 page 72
3908 if (context->getShader(program))
3909 {
Jamie Madill437fa652016-05-03 15:13:24 -04003910 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003911 Error(GL_INVALID_OPERATION,
3912 "Attempted to use a single shader instead of a shader program."));
3913 return false;
3914 }
3915 else
3916 {
Jamie Madill437fa652016-05-03 15:13:24 -04003917 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003918 return false;
3919 }
3920 }
3921 if (!programObject->isLinked())
3922 {
Jamie Madill437fa652016-05-03 15:13:24 -04003923 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003924 return false;
3925 }
3926 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003927 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003928 {
3929 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003930 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003931 Error(GL_INVALID_OPERATION,
3932 "Cannot change active program while transform feedback is unpaused."));
3933 return false;
3934 }
3935
3936 return true;
3937}
3938
Jamie Madillc29968b2016-01-20 11:17:23 -05003939bool ValidateCopyTexImage2D(ValidationContext *context,
3940 GLenum target,
3941 GLint level,
3942 GLenum internalformat,
3943 GLint x,
3944 GLint y,
3945 GLsizei width,
3946 GLsizei height,
3947 GLint border)
3948{
Martin Radev1be913c2016-07-11 17:59:16 +03003949 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003950 {
3951 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3952 0, x, y, width, height, border);
3953 }
3954
Martin Radev1be913c2016-07-11 17:59:16 +03003955 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003956 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3957 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003958}
Jamie Madillc29968b2016-01-20 11:17:23 -05003959
3960bool ValidateFramebufferRenderbuffer(Context *context,
3961 GLenum target,
3962 GLenum attachment,
3963 GLenum renderbuffertarget,
3964 GLuint renderbuffer)
3965{
3966 if (!ValidFramebufferTarget(target) ||
3967 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3968 {
Jamie Madill437fa652016-05-03 15:13:24 -04003969 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003970 return false;
3971 }
3972
3973 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3974 renderbuffertarget, renderbuffer);
3975}
3976
3977bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3978{
3979 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3980 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3981 {
Jamie Madill437fa652016-05-03 15:13:24 -04003982 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003983 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3984 return false;
3985 }
3986
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003987 ASSERT(context->getGLState().getDrawFramebuffer());
3988 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003989 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3990
3991 // This should come first before the check for the default frame buffer
3992 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3993 // rather than INVALID_OPERATION
3994 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3995 {
3996 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3997
3998 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003999 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4000 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004001 {
4002 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004003 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4004 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4005 // 3.1 is still a bit ambiguous about the error, but future specs are
4006 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004007 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004008 return false;
4009 }
4010 else if (bufs[colorAttachment] >= maxColorAttachment)
4011 {
Jamie Madill437fa652016-05-03 15:13:24 -04004012 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004013 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004014 return false;
4015 }
4016 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4017 frameBufferId != 0)
4018 {
4019 // INVALID_OPERATION-GL is bound to buffer and ith argument
4020 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004021 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004022 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4023 return false;
4024 }
4025 }
4026
4027 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4028 // and n is not 1 or bufs is bound to value other than BACK and NONE
4029 if (frameBufferId == 0)
4030 {
4031 if (n != 1)
4032 {
Jamie Madill437fa652016-05-03 15:13:24 -04004033 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004034 "n must be 1 when GL is bound to the default framebuffer"));
4035 return false;
4036 }
4037
4038 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4039 {
Jamie Madill437fa652016-05-03 15:13:24 -04004040 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004041 GL_INVALID_OPERATION,
4042 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4043 return false;
4044 }
4045 }
4046
4047 return true;
4048}
4049
4050bool ValidateCopyTexSubImage2D(Context *context,
4051 GLenum target,
4052 GLint level,
4053 GLint xoffset,
4054 GLint yoffset,
4055 GLint x,
4056 GLint y,
4057 GLsizei width,
4058 GLsizei height)
4059{
Martin Radev1be913c2016-07-11 17:59:16 +03004060 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004061 {
4062 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4063 yoffset, x, y, width, height, 0);
4064 }
4065
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004066 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4067 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004068}
4069
Geoff Lang496c02d2016-10-20 11:38:11 -07004070bool ValidateGetBufferPointervBase(Context *context,
4071 GLenum target,
4072 GLenum pname,
4073 GLsizei *length,
4074 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004075{
Geoff Lang496c02d2016-10-20 11:38:11 -07004076 if (length)
4077 {
4078 *length = 0;
4079 }
4080
4081 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4082 {
4083 context->handleError(
4084 Error(GL_INVALID_OPERATION,
4085 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4086 return false;
4087 }
4088
Olli Etuaho4f667482016-03-30 15:56:35 +03004089 if (!ValidBufferTarget(context, target))
4090 {
Jamie Madill437fa652016-05-03 15:13:24 -04004091 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004092 return false;
4093 }
4094
Geoff Lang496c02d2016-10-20 11:38:11 -07004095 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004096 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004097 case GL_BUFFER_MAP_POINTER:
4098 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004099
Geoff Lang496c02d2016-10-20 11:38:11 -07004100 default:
4101 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4102 return false;
4103 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004104
4105 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4106 // target bound to zero generate an INVALID_OPERATION error."
4107 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004108 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004109 {
Jamie Madill437fa652016-05-03 15:13:24 -04004110 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004111 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4112 return false;
4113 }
4114
Geoff Lang496c02d2016-10-20 11:38:11 -07004115 if (length)
4116 {
4117 *length = 1;
4118 }
4119
Olli Etuaho4f667482016-03-30 15:56:35 +03004120 return true;
4121}
4122
4123bool ValidateUnmapBufferBase(Context *context, GLenum target)
4124{
4125 if (!ValidBufferTarget(context, target))
4126 {
Jamie Madill437fa652016-05-03 15:13:24 -04004127 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004128 return false;
4129 }
4130
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004131 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004132
4133 if (buffer == nullptr || !buffer->isMapped())
4134 {
Jamie Madill437fa652016-05-03 15:13:24 -04004135 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004136 return false;
4137 }
4138
4139 return true;
4140}
4141
4142bool ValidateMapBufferRangeBase(Context *context,
4143 GLenum target,
4144 GLintptr offset,
4145 GLsizeiptr length,
4146 GLbitfield access)
4147{
4148 if (!ValidBufferTarget(context, target))
4149 {
Jamie Madill437fa652016-05-03 15:13:24 -04004150 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004151 return false;
4152 }
4153
4154 if (offset < 0 || length < 0)
4155 {
Jamie Madill437fa652016-05-03 15:13:24 -04004156 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004157 return false;
4158 }
4159
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004160 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004161
4162 if (!buffer)
4163 {
Jamie Madill437fa652016-05-03 15:13:24 -04004164 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004165 return false;
4166 }
4167
4168 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004169 CheckedNumeric<size_t> checkedOffset(offset);
4170 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004171
Jamie Madille2e406c2016-06-02 13:04:10 -04004172 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004173 {
Jamie Madill437fa652016-05-03 15:13:24 -04004174 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004175 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4176 return false;
4177 }
4178
4179 // Check for invalid bits in the mask
4180 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4181 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4182 GL_MAP_UNSYNCHRONIZED_BIT;
4183
4184 if (access & ~(allAccessBits))
4185 {
Jamie Madill437fa652016-05-03 15:13:24 -04004186 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004187 return false;
4188 }
4189
4190 if (length == 0)
4191 {
Jamie Madill437fa652016-05-03 15:13:24 -04004192 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004193 return false;
4194 }
4195
4196 if (buffer->isMapped())
4197 {
Jamie Madill437fa652016-05-03 15:13:24 -04004198 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004199 return false;
4200 }
4201
4202 // Check for invalid bit combinations
4203 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4204 {
Jamie Madill437fa652016-05-03 15:13:24 -04004205 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004206 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4207 return false;
4208 }
4209
4210 GLbitfield writeOnlyBits =
4211 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4212
4213 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4214 {
Jamie Madill437fa652016-05-03 15:13:24 -04004215 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004216 "Invalid access bits when mapping buffer for reading: 0x%X.",
4217 access));
4218 return false;
4219 }
4220
4221 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4222 {
Jamie Madill437fa652016-05-03 15:13:24 -04004223 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004224 GL_INVALID_OPERATION,
4225 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4226 return false;
4227 }
4228 return true;
4229}
4230
4231bool ValidateFlushMappedBufferRangeBase(Context *context,
4232 GLenum target,
4233 GLintptr offset,
4234 GLsizeiptr length)
4235{
4236 if (offset < 0 || length < 0)
4237 {
Jamie Madill437fa652016-05-03 15:13:24 -04004238 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004239 return false;
4240 }
4241
4242 if (!ValidBufferTarget(context, target))
4243 {
Jamie Madill437fa652016-05-03 15:13:24 -04004244 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004245 return false;
4246 }
4247
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004248 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004249
4250 if (buffer == nullptr)
4251 {
Jamie Madill437fa652016-05-03 15:13:24 -04004252 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004253 return false;
4254 }
4255
4256 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4257 {
Jamie Madill437fa652016-05-03 15:13:24 -04004258 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004259 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4260 return false;
4261 }
4262
4263 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004264 CheckedNumeric<size_t> checkedOffset(offset);
4265 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004266
Jamie Madille2e406c2016-06-02 13:04:10 -04004267 if (!checkedSize.IsValid() ||
4268 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004269 {
Jamie Madill437fa652016-05-03 15:13:24 -04004270 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004271 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4272 return false;
4273 }
4274
4275 return true;
4276}
4277
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004278bool ValidateGenerateMipmap(Context *context, GLenum target)
4279{
4280 if (!ValidTextureTarget(context, target))
4281 {
4282 context->handleError(Error(GL_INVALID_ENUM));
4283 return false;
4284 }
4285
4286 Texture *texture = context->getTargetTexture(target);
4287
4288 if (texture == nullptr)
4289 {
4290 context->handleError(Error(GL_INVALID_OPERATION));
4291 return false;
4292 }
4293
4294 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4295
4296 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4297 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4298 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4299 {
4300 context->handleError(Error(GL_INVALID_OPERATION));
4301 return false;
4302 }
4303
Jamie Madilla3944d42016-07-22 22:13:26 -04004304 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4305 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4306 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004307
4308 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4309 // unsized formats or that are color renderable and filterable. Since we do not track if
4310 // the texture was created with sized or unsized format (only sized formats are stored),
4311 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4312 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4313 // textures since they're the only texture format that can be created with unsized formats
4314 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4315 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004316 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4317 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004318 {
4319 context->handleError(Error(GL_INVALID_OPERATION));
4320 return false;
4321 }
4322
4323 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004324 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004325 {
4326 context->handleError(Error(GL_INVALID_OPERATION));
4327 return false;
4328 }
4329
4330 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004331 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004332 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4333 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4334 {
Geoff Lang55482a12016-11-21 16:54:01 -05004335 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004336 context->handleError(Error(GL_INVALID_OPERATION));
4337 return false;
4338 }
4339
4340 // Cube completeness check
4341 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4342 {
4343 context->handleError(Error(GL_INVALID_OPERATION));
4344 return false;
4345 }
4346
4347 return true;
4348}
4349
Olli Etuaho41997e72016-03-10 13:38:39 +02004350bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4351{
4352 return ValidateGenOrDelete(context, n);
4353}
4354
4355bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4356{
4357 return ValidateGenOrDelete(context, n);
4358}
4359
4360bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4361{
4362 return ValidateGenOrDelete(context, n);
4363}
4364
4365bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4366{
4367 return ValidateGenOrDelete(context, n);
4368}
4369
4370bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4371{
4372 return ValidateGenOrDelete(context, n);
4373}
4374
4375bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4376{
4377 return ValidateGenOrDelete(context, n);
4378}
4379
4380bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4381{
4382 return ValidateGenOrDelete(context, n);
4383}
4384
4385bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4386{
4387 return ValidateGenOrDelete(context, n);
4388}
4389
4390bool ValidateGenOrDelete(Context *context, GLint n)
4391{
4392 if (n < 0)
4393 {
Jamie Madill437fa652016-05-03 15:13:24 -04004394 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004395 return false;
4396 }
4397 return true;
4398}
4399
Geoff Langf41a7152016-09-19 15:11:17 -04004400bool ValidateEnable(Context *context, GLenum cap)
4401{
4402 if (!ValidCap(context, cap, false))
4403 {
4404 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4405 return false;
4406 }
4407
4408 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4409 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4410 {
4411 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4412 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4413
4414 // We also output an error message to the debugger window if tracing is active, so that
4415 // developers can see the error message.
4416 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004417 return false;
4418 }
4419
4420 return true;
4421}
4422
4423bool ValidateDisable(Context *context, GLenum cap)
4424{
4425 if (!ValidCap(context, cap, false))
4426 {
4427 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4428 return false;
4429 }
4430
4431 return true;
4432}
4433
4434bool ValidateIsEnabled(Context *context, GLenum cap)
4435{
4436 if (!ValidCap(context, cap, true))
4437 {
4438 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4439 return false;
4440 }
4441
4442 return true;
4443}
4444
Geoff Langff5b2d52016-09-07 11:32:23 -04004445bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4446{
4447 if (!context->getExtensions().robustClientMemory)
4448 {
4449 context->handleError(
4450 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4451 return false;
4452 }
4453
4454 if (bufSize < 0)
4455 {
4456 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4457 return false;
4458 }
4459
4460 return true;
4461}
4462
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004463bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4464{
4465 if (bufSize < numParams)
4466 {
4467 context->handleError(Error(GL_INVALID_OPERATION,
4468 "%u parameters are required but %i were provided.", numParams,
4469 bufSize));
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
Geoff Langff5b2d52016-09-07 11:32:23 -04004476bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4477 GLenum target,
4478 GLenum attachment,
4479 GLenum pname,
4480 GLsizei *numParams)
4481{
4482 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4483 *numParams = 1;
4484
4485 if (!ValidFramebufferTarget(target))
4486 {
4487 context->handleError(Error(GL_INVALID_ENUM));
4488 return false;
4489 }
4490
4491 int clientVersion = context->getClientMajorVersion();
4492
4493 switch (pname)
4494 {
4495 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4496 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4497 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4498 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4499 break;
4500
4501 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4502 if (clientVersion < 3 && !context->getExtensions().sRGB)
4503 {
4504 context->handleError(Error(GL_INVALID_ENUM));
4505 return false;
4506 }
4507 break;
4508
4509 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4510 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4511 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4512 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4513 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4514 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4515 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4516 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4517 if (clientVersion < 3)
4518 {
4519 context->handleError(Error(GL_INVALID_ENUM));
4520 return false;
4521 }
4522 break;
4523
4524 default:
4525 context->handleError(Error(GL_INVALID_ENUM));
4526 return false;
4527 }
4528
4529 // Determine if the attachment is a valid enum
4530 switch (attachment)
4531 {
4532 case GL_BACK:
4533 case GL_FRONT:
4534 case GL_DEPTH:
4535 case GL_STENCIL:
4536 case GL_DEPTH_STENCIL_ATTACHMENT:
4537 if (clientVersion < 3)
4538 {
4539 context->handleError(Error(GL_INVALID_ENUM));
4540 return false;
4541 }
4542 break;
4543
4544 case GL_DEPTH_ATTACHMENT:
4545 case GL_STENCIL_ATTACHMENT:
4546 break;
4547
4548 default:
4549 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4550 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4551 {
4552 context->handleError(Error(GL_INVALID_ENUM));
4553 return false;
4554 }
4555 break;
4556 }
4557
4558 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4559 ASSERT(framebuffer);
4560
4561 if (framebuffer->id() == 0)
4562 {
4563 if (clientVersion < 3)
4564 {
4565 context->handleError(Error(GL_INVALID_OPERATION));
4566 return false;
4567 }
4568
4569 switch (attachment)
4570 {
4571 case GL_BACK:
4572 case GL_DEPTH:
4573 case GL_STENCIL:
4574 break;
4575
4576 default:
4577 context->handleError(Error(GL_INVALID_OPERATION));
4578 return false;
4579 }
4580 }
4581 else
4582 {
4583 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4584 {
4585 // Valid attachment query
4586 }
4587 else
4588 {
4589 switch (attachment)
4590 {
4591 case GL_DEPTH_ATTACHMENT:
4592 case GL_STENCIL_ATTACHMENT:
4593 break;
4594
4595 case GL_DEPTH_STENCIL_ATTACHMENT:
4596 if (!framebuffer->hasValidDepthStencil())
4597 {
4598 context->handleError(Error(GL_INVALID_OPERATION));
4599 return false;
4600 }
4601 break;
4602
4603 default:
4604 context->handleError(Error(GL_INVALID_OPERATION));
4605 return false;
4606 }
4607 }
4608 }
4609
4610 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4611 if (attachmentObject)
4612 {
4613 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4614 attachmentObject->type() == GL_TEXTURE ||
4615 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4616
4617 switch (pname)
4618 {
4619 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4620 if (attachmentObject->type() != GL_RENDERBUFFER &&
4621 attachmentObject->type() != GL_TEXTURE)
4622 {
4623 context->handleError(Error(GL_INVALID_ENUM));
4624 return false;
4625 }
4626 break;
4627
4628 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4629 if (attachmentObject->type() != GL_TEXTURE)
4630 {
4631 context->handleError(Error(GL_INVALID_ENUM));
4632 return false;
4633 }
4634 break;
4635
4636 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4637 if (attachmentObject->type() != GL_TEXTURE)
4638 {
4639 context->handleError(Error(GL_INVALID_ENUM));
4640 return false;
4641 }
4642 break;
4643
4644 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4645 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4646 {
4647 context->handleError(Error(GL_INVALID_OPERATION));
4648 return false;
4649 }
4650 break;
4651
4652 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4653 if (attachmentObject->type() != GL_TEXTURE)
4654 {
4655 context->handleError(Error(GL_INVALID_ENUM));
4656 return false;
4657 }
4658 break;
4659
4660 default:
4661 break;
4662 }
4663 }
4664 else
4665 {
4666 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4667 // is NONE, then querying any other pname will generate INVALID_ENUM.
4668
4669 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4670 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4671 // INVALID_OPERATION for all other pnames
4672
4673 switch (pname)
4674 {
4675 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4676 break;
4677
4678 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4679 if (clientVersion < 3)
4680 {
4681 context->handleError(Error(GL_INVALID_ENUM));
4682 return false;
4683 }
4684 break;
4685
4686 default:
4687 if (clientVersion < 3)
4688 {
4689 context->handleError(Error(GL_INVALID_ENUM));
4690 return false;
4691 }
4692 else
4693 {
4694 context->handleError(Error(GL_INVALID_OPERATION));
4695 return false;
4696 }
4697 }
4698 }
4699
4700 return true;
4701}
4702
4703bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4704 GLenum target,
4705 GLenum attachment,
4706 GLenum pname,
4707 GLsizei bufSize,
4708 GLsizei *numParams)
4709{
4710 if (!ValidateRobustEntryPoint(context, bufSize))
4711 {
4712 return false;
4713 }
4714
4715 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4716 {
4717 return false;
4718 }
4719
4720 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4721 {
4722 return false;
4723 }
4724
4725 return true;
4726}
4727
4728bool ValidateGetBufferParameteriv(ValidationContext *context,
4729 GLenum target,
4730 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004731 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004732{
Geoff Langebebe1c2016-10-14 12:01:31 -04004733 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004734}
4735
4736bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4737 GLenum target,
4738 GLenum pname,
4739 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004740 GLsizei *length,
4741 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004742{
4743 if (!ValidateRobustEntryPoint(context, bufSize))
4744 {
4745 return false;
4746 }
4747
Geoff Langebebe1c2016-10-14 12:01:31 -04004748 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004749 {
4750 return false;
4751 }
4752
Geoff Langebebe1c2016-10-14 12:01:31 -04004753 if (!ValidateRobustBufferSize(context, bufSize, *length))
4754 {
4755 return false;
4756 }
4757
4758 return true;
4759}
4760
4761bool ValidateGetBufferParameteri64v(ValidationContext *context,
4762 GLenum target,
4763 GLenum pname,
4764 GLint64 *params)
4765{
4766 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4767}
4768
4769bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4770 GLenum target,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 GLsizei *length,
4774 GLint64 *params)
4775{
4776 if (!ValidateRobustEntryPoint(context, bufSize))
4777 {
4778 return false;
4779 }
4780
4781 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4782 {
4783 return false;
4784 }
4785
4786 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004787 {
4788 return false;
4789 }
4790
4791 return true;
4792}
4793
4794bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4795{
4796 // Currently, all GetProgramiv queries return 1 parameter
4797 *numParams = 1;
4798
4799 Program *programObject = GetValidProgram(context, program);
4800 if (!programObject)
4801 {
4802 return false;
4803 }
4804
4805 switch (pname)
4806 {
4807 case GL_DELETE_STATUS:
4808 case GL_LINK_STATUS:
4809 case GL_VALIDATE_STATUS:
4810 case GL_INFO_LOG_LENGTH:
4811 case GL_ATTACHED_SHADERS:
4812 case GL_ACTIVE_ATTRIBUTES:
4813 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4814 case GL_ACTIVE_UNIFORMS:
4815 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4816 break;
4817
4818 case GL_PROGRAM_BINARY_LENGTH:
4819 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4820 {
4821 context->handleError(Error(GL_INVALID_ENUM,
4822 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4823 "GL_OES_get_program_binary or ES 3.0."));
4824 return false;
4825 }
4826 break;
4827
4828 case GL_ACTIVE_UNIFORM_BLOCKS:
4829 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4830 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4831 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4832 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4833 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4834 if (context->getClientMajorVersion() < 3)
4835 {
4836 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4837 return false;
4838 }
4839 break;
4840
4841 default:
4842 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4843 return false;
4844 }
4845
4846 return true;
4847}
4848
4849bool ValidateGetProgramivRobustANGLE(Context *context,
4850 GLuint program,
4851 GLenum pname,
4852 GLsizei bufSize,
4853 GLsizei *numParams)
4854{
4855 if (!ValidateRobustEntryPoint(context, bufSize))
4856 {
4857 return false;
4858 }
4859
4860 if (!ValidateGetProgramiv(context, program, pname, numParams))
4861 {
4862 return false;
4863 }
4864
4865 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4866 {
4867 return false;
4868 }
4869
4870 return true;
4871}
4872
Geoff Lang740d9022016-10-07 11:20:52 -04004873bool ValidateGetRenderbufferParameteriv(Context *context,
4874 GLenum target,
4875 GLenum pname,
4876 GLint *params)
4877{
4878 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4879}
4880
4881bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4882 GLenum target,
4883 GLenum pname,
4884 GLsizei bufSize,
4885 GLsizei *length,
4886 GLint *params)
4887{
4888 if (!ValidateRobustEntryPoint(context, bufSize))
4889 {
4890 return false;
4891 }
4892
4893 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4894 {
4895 return false;
4896 }
4897
4898 if (!ValidateRobustBufferSize(context, bufSize, *length))
4899 {
4900 return false;
4901 }
4902
4903 return true;
4904}
4905
Geoff Langd7d0ed32016-10-07 11:33:51 -04004906bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4907{
4908 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4909}
4910
4911bool ValidateGetShaderivRobustANGLE(Context *context,
4912 GLuint shader,
4913 GLenum pname,
4914 GLsizei bufSize,
4915 GLsizei *length,
4916 GLint *params)
4917{
4918 if (!ValidateRobustEntryPoint(context, bufSize))
4919 {
4920 return false;
4921 }
4922
4923 if (!ValidateGetShaderivBase(context, shader, pname, length))
4924 {
4925 return false;
4926 }
4927
4928 if (!ValidateRobustBufferSize(context, bufSize, *length))
4929 {
4930 return false;
4931 }
4932
4933 return true;
4934}
4935
Geoff Langc1984ed2016-10-07 12:41:00 -04004936bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4937{
4938 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4939}
4940
4941bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4942 GLenum target,
4943 GLenum pname,
4944 GLsizei bufSize,
4945 GLsizei *length,
4946 GLfloat *params)
4947{
4948 if (!ValidateRobustEntryPoint(context, bufSize))
4949 {
4950 return false;
4951 }
4952
4953 if (!ValidateGetTexParameterBase(context, target, pname, length))
4954 {
4955 return false;
4956 }
4957
4958 if (!ValidateRobustBufferSize(context, bufSize, *length))
4959 {
4960 return false;
4961 }
4962
4963 return true;
4964}
4965
4966bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4967{
4968 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4969}
4970
4971bool ValidateGetTexParameterivRobustANGLE(Context *context,
4972 GLenum target,
4973 GLenum pname,
4974 GLsizei bufSize,
4975 GLsizei *length,
4976 GLint *params)
4977{
4978 if (!ValidateRobustEntryPoint(context, bufSize))
4979 {
4980 return false;
4981 }
4982
4983 if (!ValidateGetTexParameterBase(context, target, pname, length))
4984 {
4985 return false;
4986 }
4987
4988 if (!ValidateRobustBufferSize(context, bufSize, *length))
4989 {
4990 return false;
4991 }
4992
4993 return true;
4994}
4995
4996bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4997{
4998 return ValidateTexParameterBase(context, target, pname, -1, &param);
4999}
5000
5001bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5002{
5003 return ValidateTexParameterBase(context, target, pname, -1, params);
5004}
5005
5006bool ValidateTexParameterfvRobustANGLE(Context *context,
5007 GLenum target,
5008 GLenum pname,
5009 GLsizei bufSize,
5010 const GLfloat *params)
5011{
5012 if (!ValidateRobustEntryPoint(context, bufSize))
5013 {
5014 return false;
5015 }
5016
5017 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5018}
5019
5020bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5021{
5022 return ValidateTexParameterBase(context, target, pname, -1, &param);
5023}
5024
5025bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5026{
5027 return ValidateTexParameterBase(context, target, pname, -1, params);
5028}
5029
5030bool ValidateTexParameterivRobustANGLE(Context *context,
5031 GLenum target,
5032 GLenum pname,
5033 GLsizei bufSize,
5034 const GLint *params)
5035{
5036 if (!ValidateRobustEntryPoint(context, bufSize))
5037 {
5038 return false;
5039 }
5040
5041 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5042}
5043
5044bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5045{
5046 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5047}
5048
5049bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5050 GLuint sampler,
5051 GLenum pname,
5052 GLuint bufSize,
5053 GLsizei *length,
5054 GLfloat *params)
5055{
5056 if (!ValidateRobustEntryPoint(context, bufSize))
5057 {
5058 return false;
5059 }
5060
5061 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5062 {
5063 return false;
5064 }
5065
5066 if (!ValidateRobustBufferSize(context, bufSize, *length))
5067 {
5068 return false;
5069 }
5070
5071 return true;
5072}
5073
5074bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5075{
5076 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5077}
5078
5079bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5080 GLuint sampler,
5081 GLenum pname,
5082 GLuint bufSize,
5083 GLsizei *length,
5084 GLint *params)
5085{
5086 if (!ValidateRobustEntryPoint(context, bufSize))
5087 {
5088 return false;
5089 }
5090
5091 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5092 {
5093 return false;
5094 }
5095
5096 if (!ValidateRobustBufferSize(context, bufSize, *length))
5097 {
5098 return false;
5099 }
5100
5101 return true;
5102}
5103
5104bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5105{
5106 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5107}
5108
5109bool ValidateSamplerParameterfv(Context *context,
5110 GLuint sampler,
5111 GLenum pname,
5112 const GLfloat *params)
5113{
5114 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5115}
5116
5117bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5118 GLuint sampler,
5119 GLenum pname,
5120 GLsizei bufSize,
5121 const GLfloat *params)
5122{
5123 if (!ValidateRobustEntryPoint(context, bufSize))
5124 {
5125 return false;
5126 }
5127
5128 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5129}
5130
5131bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5132{
5133 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5134}
5135
5136bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5137{
5138 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5139}
5140
5141bool ValidateSamplerParameterivRobustANGLE(Context *context,
5142 GLuint sampler,
5143 GLenum pname,
5144 GLsizei bufSize,
5145 const GLint *params)
5146{
5147 if (!ValidateRobustEntryPoint(context, bufSize))
5148 {
5149 return false;
5150 }
5151
5152 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5153}
5154
Geoff Lang0b031062016-10-13 14:30:04 -04005155bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5156{
5157 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5158}
5159
5160bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5161 GLuint index,
5162 GLenum pname,
5163 GLsizei bufSize,
5164 GLsizei *length,
5165 GLfloat *params)
5166{
5167 if (!ValidateRobustEntryPoint(context, bufSize))
5168 {
5169 return false;
5170 }
5171
5172 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5173 {
5174 return false;
5175 }
5176
5177 if (!ValidateRobustBufferSize(context, bufSize, *length))
5178 {
5179 return false;
5180 }
5181
5182 return true;
5183}
5184
5185bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5186{
5187 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5188}
5189
5190bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5191 GLuint index,
5192 GLenum pname,
5193 GLsizei bufSize,
5194 GLsizei *length,
5195 GLint *params)
5196{
5197 if (!ValidateRobustEntryPoint(context, bufSize))
5198 {
5199 return false;
5200 }
5201
5202 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5203 {
5204 return false;
5205 }
5206
5207 if (!ValidateRobustBufferSize(context, bufSize, *length))
5208 {
5209 return false;
5210 }
5211
5212 return true;
5213}
5214
5215bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5216{
5217 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5218}
5219
5220bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5221 GLuint index,
5222 GLenum pname,
5223 GLsizei bufSize,
5224 GLsizei *length,
5225 void **pointer)
5226{
5227 if (!ValidateRobustEntryPoint(context, bufSize))
5228 {
5229 return false;
5230 }
5231
5232 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5233 {
5234 return false;
5235 }
5236
5237 if (!ValidateRobustBufferSize(context, bufSize, *length))
5238 {
5239 return false;
5240 }
5241
5242 return true;
5243}
5244
5245bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5246{
5247 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5248}
5249
5250bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5251 GLuint index,
5252 GLenum pname,
5253 GLsizei bufSize,
5254 GLsizei *length,
5255 GLint *params)
5256{
5257 if (!ValidateRobustEntryPoint(context, bufSize))
5258 {
5259 return false;
5260 }
5261
5262 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5263 {
5264 return false;
5265 }
5266
5267 if (!ValidateRobustBufferSize(context, bufSize, *length))
5268 {
5269 return false;
5270 }
5271
5272 return true;
5273}
5274
5275bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5276{
5277 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5278}
5279
5280bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5281 GLuint index,
5282 GLenum pname,
5283 GLsizei bufSize,
5284 GLsizei *length,
5285 GLuint *params)
5286{
5287 if (!ValidateRobustEntryPoint(context, bufSize))
5288 {
5289 return false;
5290 }
5291
5292 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5293 {
5294 return false;
5295 }
5296
5297 if (!ValidateRobustBufferSize(context, bufSize, *length))
5298 {
5299 return false;
5300 }
5301
5302 return true;
5303}
5304
Geoff Lang6899b872016-10-14 11:30:13 -04005305bool ValidateGetActiveUniformBlockiv(Context *context,
5306 GLuint program,
5307 GLuint uniformBlockIndex,
5308 GLenum pname,
5309 GLint *params)
5310{
5311 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5312}
5313
5314bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5315 GLuint program,
5316 GLuint uniformBlockIndex,
5317 GLenum pname,
5318 GLsizei bufSize,
5319 GLsizei *length,
5320 GLint *params)
5321{
5322 if (!ValidateRobustEntryPoint(context, bufSize))
5323 {
5324 return false;
5325 }
5326
5327 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5328 {
5329 return false;
5330 }
5331
5332 if (!ValidateRobustBufferSize(context, bufSize, *length))
5333 {
5334 return false;
5335 }
5336
5337 return true;
5338}
5339
Geoff Lang0a9661f2016-10-20 10:59:20 -07005340bool ValidateGetInternalFormativ(Context *context,
5341 GLenum target,
5342 GLenum internalformat,
5343 GLenum pname,
5344 GLsizei bufSize,
5345 GLint *params)
5346{
5347 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5348 nullptr);
5349}
5350
5351bool ValidateGetInternalFormativRobustANGLE(Context *context,
5352 GLenum target,
5353 GLenum internalformat,
5354 GLenum pname,
5355 GLsizei bufSize,
5356 GLsizei *length,
5357 GLint *params)
5358{
5359 if (!ValidateRobustEntryPoint(context, bufSize))
5360 {
5361 return false;
5362 }
5363
5364 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5365 {
5366 return false;
5367 }
5368
5369 if (!ValidateRobustBufferSize(context, bufSize, *length))
5370 {
5371 return false;
5372 }
5373
5374 return true;
5375}
5376
Jamie Madillc29968b2016-01-20 11:17:23 -05005377} // namespace gl