blob: a45e1f2dce9f6c9cb731eed7ad40fe3cba74e504 [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
165 default:
166 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500167 }
168}
169
Geoff Lang62fce5b2016-09-30 10:46:35 -0400170bool ValidateReadPixelsBase(ValidationContext *context,
171 GLint x,
172 GLint y,
173 GLsizei width,
174 GLsizei height,
175 GLenum format,
176 GLenum type,
177 GLsizei bufSize,
178 GLsizei *length,
179 GLvoid *pixels)
180{
181 if (length != nullptr)
182 {
183 *length = 0;
184 }
185
186 if (width < 0 || height < 0)
187 {
188 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
189 return false;
190 }
191
192 auto readFramebuffer = context->getGLState().getReadFramebuffer();
193
194 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
195 {
196 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
197 return false;
198 }
199
200 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
201 {
202 context->handleError(Error(GL_INVALID_OPERATION));
203 return false;
204 }
205
206 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
207 ASSERT(framebuffer);
208
209 if (framebuffer->getReadBufferState() == GL_NONE)
210 {
211 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
212 return false;
213 }
214
215 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
216 if (!readBuffer)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION));
219 return false;
220 }
221
222 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
223 GLenum currentType = framebuffer->getImplementationColorReadType();
224 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
225
226 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
227 bool validFormatTypeCombination =
228 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
229
230 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
231 {
232 context->handleError(Error(GL_INVALID_OPERATION));
233 return false;
234 }
235
236 // Check for pixel pack buffer related API errors
237 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
238 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
239 {
240 // ...the buffer object's data store is currently mapped.
241 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
242 return false;
243 }
244
245 // .. the data would be packed to the buffer object such that the memory writes required
246 // would exceed the data store size.
247 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
248 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
249 const gl::Extents size(width, height, 1);
250 const auto &pack = context->getGLState().getPackState();
251
252 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
253 if (endByteOrErr.isError())
254 {
255 context->handleError(endByteOrErr.getError());
256 return false;
257 }
258
259 size_t endByte = endByteOrErr.getResult();
260 if (bufSize >= 0)
261 {
262
263 if (static_cast<size_t>(bufSize) < endByte)
264 {
265 context->handleError(
266 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
267 return false;
268 }
269 }
270
271 if (pixelPackBuffer != nullptr)
272 {
273 CheckedNumeric<size_t> checkedEndByte(endByte);
274 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
275 checkedEndByte += checkedOffset;
276
277 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
278 {
279 // Overflow past the end of the buffer
280 context->handleError(
281 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
282 return false;
283 }
284 }
285
286 if (length != nullptr)
287 {
288 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
289 {
290 context->handleError(
291 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
292 return false;
293 }
294
295 *length = static_cast<GLsizei>(endByte);
296 }
297
298 return true;
299}
300
Geoff Lang740d9022016-10-07 11:20:52 -0400301bool ValidateGetRenderbufferParameterivBase(Context *context,
302 GLenum target,
303 GLenum pname,
304 GLsizei *length)
305{
306 if (length)
307 {
308 *length = 0;
309 }
310
311 if (target != GL_RENDERBUFFER)
312 {
313 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
314 return false;
315 }
316
317 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
318 if (renderbuffer == nullptr)
319 {
320 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
321 return false;
322 }
323
324 switch (pname)
325 {
326 case GL_RENDERBUFFER_WIDTH:
327 case GL_RENDERBUFFER_HEIGHT:
328 case GL_RENDERBUFFER_INTERNAL_FORMAT:
329 case GL_RENDERBUFFER_RED_SIZE:
330 case GL_RENDERBUFFER_GREEN_SIZE:
331 case GL_RENDERBUFFER_BLUE_SIZE:
332 case GL_RENDERBUFFER_ALPHA_SIZE:
333 case GL_RENDERBUFFER_DEPTH_SIZE:
334 case GL_RENDERBUFFER_STENCIL_SIZE:
335 break;
336
337 case GL_RENDERBUFFER_SAMPLES_ANGLE:
338 if (!context->getExtensions().framebufferMultisample)
339 {
340 context->handleError(
341 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
342 return false;
343 }
344 break;
345
346 default:
347 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
348 return false;
349 }
350
351 if (length)
352 {
353 *length = 1;
354 }
355 return true;
356}
357
Geoff Langd7d0ed32016-10-07 11:33:51 -0400358bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
359{
360 if (length)
361 {
362 *length = 0;
363 }
364
365 if (GetValidShader(context, shader) == nullptr)
366 {
367 return false;
368 }
369
370 switch (pname)
371 {
372 case GL_SHADER_TYPE:
373 case GL_DELETE_STATUS:
374 case GL_COMPILE_STATUS:
375 case GL_INFO_LOG_LENGTH:
376 case GL_SHADER_SOURCE_LENGTH:
377 break;
378
379 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
380 if (!context->getExtensions().translatedShaderSource)
381 {
382 context->handleError(
383 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
384 return false;
385 }
386 break;
387
388 default:
389 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
390 return false;
391 }
392
393 if (length)
394 {
395 *length = 1;
396 }
397 return true;
398}
399
Geoff Langc1984ed2016-10-07 12:41:00 -0400400bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
401{
402 if (length)
403 {
404 *length = 0;
405 }
406
407 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
408 {
409 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
410 return false;
411 }
412
413 if (context->getTargetTexture(target) == nullptr)
414 {
415 // Should only be possible for external textures
416 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
417 return false;
418 }
419
420 switch (pname)
421 {
422 case GL_TEXTURE_MAG_FILTER:
423 case GL_TEXTURE_MIN_FILTER:
424 case GL_TEXTURE_WRAP_S:
425 case GL_TEXTURE_WRAP_T:
426 break;
427
428 case GL_TEXTURE_USAGE_ANGLE:
429 if (!context->getExtensions().textureUsage)
430 {
431 context->handleError(
432 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
438 if (!context->getExtensions().textureFilterAnisotropic)
439 {
440 context->handleError(
441 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
442 return false;
443 }
444 break;
445
446 case GL_TEXTURE_IMMUTABLE_FORMAT:
447 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
448 {
449 context->handleError(
450 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
451 return false;
452 }
453 break;
454
455 case GL_TEXTURE_WRAP_R:
456 case GL_TEXTURE_IMMUTABLE_LEVELS:
457 case GL_TEXTURE_SWIZZLE_R:
458 case GL_TEXTURE_SWIZZLE_G:
459 case GL_TEXTURE_SWIZZLE_B:
460 case GL_TEXTURE_SWIZZLE_A:
461 case GL_TEXTURE_BASE_LEVEL:
462 case GL_TEXTURE_MAX_LEVEL:
463 case GL_TEXTURE_MIN_LOD:
464 case GL_TEXTURE_MAX_LOD:
465 case GL_TEXTURE_COMPARE_MODE:
466 case GL_TEXTURE_COMPARE_FUNC:
467 if (context->getClientMajorVersion() < 3)
468 {
469 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
470 return false;
471 }
472 break;
473
Geoff Lang81c6b572016-10-19 14:07:52 -0700474 case GL_TEXTURE_SRGB_DECODE_EXT:
475 if (!context->getExtensions().textureSRGBDecode)
476 {
477 context->handleError(
478 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
479 return false;
480 }
481 break;
482
Geoff Langc1984ed2016-10-07 12:41:00 -0400483 default:
484 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
485 return false;
486 }
487
488 if (length)
489 {
490 *length = 1;
491 }
492 return true;
493}
494
495template <typename ParamType>
496bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
497{
498 switch (ConvertToGLenum(params[0]))
499 {
500 case GL_CLAMP_TO_EDGE:
501 break;
502
503 case GL_REPEAT:
504 case GL_MIRRORED_REPEAT:
505 if (isExternalTextureTarget)
506 {
507 // OES_EGL_image_external specifies this error.
508 context->handleError(Error(
509 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
510 return false;
511 }
512 break;
513
514 default:
515 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
516 return false;
517 }
518
519 return true;
520}
521
522template <typename ParamType>
523bool ValidateTextureMinFilterValue(Context *context,
524 ParamType *params,
525 bool isExternalTextureTarget)
526{
527 switch (ConvertToGLenum(params[0]))
528 {
529 case GL_NEAREST:
530 case GL_LINEAR:
531 break;
532
533 case GL_NEAREST_MIPMAP_NEAREST:
534 case GL_LINEAR_MIPMAP_NEAREST:
535 case GL_NEAREST_MIPMAP_LINEAR:
536 case GL_LINEAR_MIPMAP_LINEAR:
537 if (isExternalTextureTarget)
538 {
539 // OES_EGL_image_external specifies this error.
540 context->handleError(
541 Error(GL_INVALID_ENUM,
542 "external textures only support NEAREST and LINEAR filtering"));
543 return false;
544 }
545 break;
546
547 default:
548 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
549 return false;
550 }
551
552 return true;
553}
554
555template <typename ParamType>
556bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
557{
558 switch (ConvertToGLenum(params[0]))
559 {
560 case GL_NEAREST:
561 case GL_LINEAR:
562 break;
563
564 default:
565 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
566 return false;
567 }
568
569 return true;
570}
571
572template <typename ParamType>
573bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
574{
575 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
576 switch (ConvertToGLenum(params[0]))
577 {
578 case GL_NONE:
579 case GL_COMPARE_REF_TO_TEXTURE:
580 break;
581
582 default:
583 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
584 return false;
585 }
586
587 return true;
588}
589
590template <typename ParamType>
591bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
592{
593 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
594 switch (ConvertToGLenum(params[0]))
595 {
596 case GL_LEQUAL:
597 case GL_GEQUAL:
598 case GL_LESS:
599 case GL_GREATER:
600 case GL_EQUAL:
601 case GL_NOTEQUAL:
602 case GL_ALWAYS:
603 case GL_NEVER:
604 break;
605
606 default:
607 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
608 return false;
609 }
610
611 return true;
612}
613
614template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700615bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
616{
617 if (!context->getExtensions().textureSRGBDecode)
618 {
619 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
620 return false;
621 }
622
623 switch (ConvertToGLenum(params[0]))
624 {
625 case GL_DECODE_EXT:
626 case GL_SKIP_DECODE_EXT:
627 break;
628
629 default:
630 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
631 return false;
632 }
633
634 return true;
635}
636
637template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400638bool ValidateTexParameterBase(Context *context,
639 GLenum target,
640 GLenum pname,
641 GLsizei bufSize,
642 ParamType *params)
643{
644 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
645 {
646 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
647 return false;
648 }
649
650 if (context->getTargetTexture(target) == nullptr)
651 {
652 // Should only be possible for external textures
653 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
654 return false;
655 }
656
657 const GLsizei minBufSize = 1;
658 if (bufSize >= 0 && bufSize < minBufSize)
659 {
660 context->handleError(
661 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
662 return false;
663 }
664
665 switch (pname)
666 {
667 case GL_TEXTURE_WRAP_R:
668 case GL_TEXTURE_SWIZZLE_R:
669 case GL_TEXTURE_SWIZZLE_G:
670 case GL_TEXTURE_SWIZZLE_B:
671 case GL_TEXTURE_SWIZZLE_A:
672 case GL_TEXTURE_BASE_LEVEL:
673 case GL_TEXTURE_MAX_LEVEL:
674 case GL_TEXTURE_COMPARE_MODE:
675 case GL_TEXTURE_COMPARE_FUNC:
676 case GL_TEXTURE_MIN_LOD:
677 case GL_TEXTURE_MAX_LOD:
678 if (context->getClientMajorVersion() < 3)
679 {
680 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
681 return false;
682 }
683 if (target == GL_TEXTURE_EXTERNAL_OES &&
684 !context->getExtensions().eglImageExternalEssl3)
685 {
686 context->handleError(Error(GL_INVALID_ENUM,
687 "ES3 texture parameters are not available without "
688 "GL_OES_EGL_image_external_essl3."));
689 return false;
690 }
691 break;
692
693 default:
694 break;
695 }
696
697 switch (pname)
698 {
699 case GL_TEXTURE_WRAP_S:
700 case GL_TEXTURE_WRAP_T:
701 case GL_TEXTURE_WRAP_R:
702 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
703 {
704 return false;
705 }
706 break;
707
708 case GL_TEXTURE_MIN_FILTER:
709 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
710 {
711 return false;
712 }
713 break;
714
715 case GL_TEXTURE_MAG_FILTER:
716 if (!ValidateTextureMagFilterValue(context, params))
717 {
718 return false;
719 }
720 break;
721
722 case GL_TEXTURE_USAGE_ANGLE:
723 switch (ConvertToGLenum(params[0]))
724 {
725 case GL_NONE:
726 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
727 break;
728
729 default:
730 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
731 return false;
732 }
733 break;
734
735 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
736 if (!context->getExtensions().textureFilterAnisotropic)
737 {
738 context->handleError(
739 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
740 return false;
741 }
742
743 // we assume the parameter passed to this validation method is truncated, not rounded
744 if (params[0] < 1)
745 {
746 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
747 return false;
748 }
749 break;
750
751 case GL_TEXTURE_MIN_LOD:
752 case GL_TEXTURE_MAX_LOD:
753 // any value is permissible
754 break;
755
756 case GL_TEXTURE_COMPARE_MODE:
757 if (!ValidateTextureCompareModeValue(context, params))
758 {
759 return false;
760 }
761 break;
762
763 case GL_TEXTURE_COMPARE_FUNC:
764 if (!ValidateTextureCompareFuncValue(context, params))
765 {
766 return false;
767 }
768 break;
769
770 case GL_TEXTURE_SWIZZLE_R:
771 case GL_TEXTURE_SWIZZLE_G:
772 case GL_TEXTURE_SWIZZLE_B:
773 case GL_TEXTURE_SWIZZLE_A:
774 switch (ConvertToGLenum(params[0]))
775 {
776 case GL_RED:
777 case GL_GREEN:
778 case GL_BLUE:
779 case GL_ALPHA:
780 case GL_ZERO:
781 case GL_ONE:
782 break;
783
784 default:
785 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
786 return false;
787 }
788 break;
789
790 case GL_TEXTURE_BASE_LEVEL:
791 if (params[0] < 0)
792 {
793 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
794 return false;
795 }
796 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
797 {
798 context->handleError(
799 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
800 return false;
801 }
802 break;
803
804 case GL_TEXTURE_MAX_LEVEL:
805 if (params[0] < 0)
806 {
807 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
808 return false;
809 }
810 break;
811
Geoff Lang81c6b572016-10-19 14:07:52 -0700812 case GL_TEXTURE_SRGB_DECODE_EXT:
813 if (!ValidateTextureSRGBDecodeValue(context, params))
814 {
815 return false;
816 }
817 break;
818
Geoff Langc1984ed2016-10-07 12:41:00 -0400819 default:
820 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
821 return false;
822 }
823
824 return true;
825}
826
827template <typename ParamType>
828bool ValidateSamplerParameterBase(Context *context,
829 GLuint sampler,
830 GLenum pname,
831 GLsizei bufSize,
832 ParamType *params)
833{
834 if (context->getClientMajorVersion() < 3)
835 {
836 context->handleError(
837 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
838 return false;
839 }
840
841 if (!context->isSampler(sampler))
842 {
843 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
844 return false;
845 }
846
847 const GLsizei minBufSize = 1;
848 if (bufSize >= 0 && bufSize < minBufSize)
849 {
850 context->handleError(
851 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
852 return false;
853 }
854
855 switch (pname)
856 {
857 case GL_TEXTURE_WRAP_S:
858 case GL_TEXTURE_WRAP_T:
859 case GL_TEXTURE_WRAP_R:
860 if (!ValidateTextureWrapModeValue(context, params, false))
861 {
862 return false;
863 }
864 break;
865
866 case GL_TEXTURE_MIN_FILTER:
867 if (!ValidateTextureMinFilterValue(context, params, false))
868 {
869 return false;
870 }
871 break;
872
873 case GL_TEXTURE_MAG_FILTER:
874 if (!ValidateTextureMagFilterValue(context, params))
875 {
876 return false;
877 }
878 break;
879
880 case GL_TEXTURE_MIN_LOD:
881 case GL_TEXTURE_MAX_LOD:
882 // any value is permissible
883 break;
884
885 case GL_TEXTURE_COMPARE_MODE:
886 if (!ValidateTextureCompareModeValue(context, params))
887 {
888 return false;
889 }
890 break;
891
892 case GL_TEXTURE_COMPARE_FUNC:
893 if (!ValidateTextureCompareFuncValue(context, params))
894 {
895 return false;
896 }
897 break;
898
Geoff Lang81c6b572016-10-19 14:07:52 -0700899 case GL_TEXTURE_SRGB_DECODE_EXT:
900 if (!ValidateTextureSRGBDecodeValue(context, params))
901 {
902 return false;
903 }
904 break;
905
Geoff Langc1984ed2016-10-07 12:41:00 -0400906 default:
907 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
908 return false;
909 }
910
911 return true;
912}
913
914bool ValidateGetSamplerParameterBase(Context *context,
915 GLuint sampler,
916 GLenum pname,
917 GLsizei *length)
918{
919 if (length)
920 {
921 *length = 0;
922 }
923
924 if (context->getClientMajorVersion() < 3)
925 {
926 context->handleError(
927 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
928 return false;
929 }
930
931 if (!context->isSampler(sampler))
932 {
933 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
934 return false;
935 }
936
937 switch (pname)
938 {
939 case GL_TEXTURE_WRAP_S:
940 case GL_TEXTURE_WRAP_T:
941 case GL_TEXTURE_WRAP_R:
942 case GL_TEXTURE_MIN_FILTER:
943 case GL_TEXTURE_MAG_FILTER:
944 case GL_TEXTURE_MIN_LOD:
945 case GL_TEXTURE_MAX_LOD:
946 case GL_TEXTURE_COMPARE_MODE:
947 case GL_TEXTURE_COMPARE_FUNC:
948 break;
949
Geoff Lang81c6b572016-10-19 14:07:52 -0700950 case GL_TEXTURE_SRGB_DECODE_EXT:
951 if (!context->getExtensions().textureSRGBDecode)
952 {
953 context->handleError(
954 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
955 return false;
956 }
957 break;
958
Geoff Langc1984ed2016-10-07 12:41:00 -0400959 default:
960 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
961 return false;
962 }
963
964 if (length)
965 {
966 *length = 1;
967 }
968 return true;
969}
970
Geoff Lang0b031062016-10-13 14:30:04 -0400971bool ValidateGetVertexAttribBase(Context *context,
972 GLuint index,
973 GLenum pname,
974 GLsizei *length,
975 bool pointer,
976 bool pureIntegerEntryPoint)
977{
978 if (length)
979 {
980 *length = 0;
981 }
982
983 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
984 {
985 context->handleError(
986 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
987 return false;
988 }
989
990 if (index >= context->getCaps().maxVertexAttributes)
991 {
992 context->handleError(Error(
993 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
994 return false;
995 }
996
997 if (pointer)
998 {
999 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1000 {
1001 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1002 return false;
1003 }
1004 }
1005 else
1006 {
1007 switch (pname)
1008 {
1009 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1010 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1011 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1012 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1013 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1014 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1015 case GL_CURRENT_VERTEX_ATTRIB:
1016 break;
1017
1018 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1019 static_assert(
1020 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1021 "ANGLE extension enums not equal to GL enums.");
1022 if (context->getClientMajorVersion() < 3 &&
1023 !context->getExtensions().instancedArrays)
1024 {
1025 context->handleError(Error(GL_INVALID_ENUM,
1026 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1027 "3.0 or GL_ANGLE_instanced_arrays."));
1028 return false;
1029 }
1030 break;
1031
1032 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1033 if (context->getClientMajorVersion() < 3)
1034 {
1035 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1036 return false;
1037 }
1038 break;
1039
1040 default:
1041 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1042 return false;
1043 }
1044 }
1045
1046 if (length)
1047 {
1048 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1049 {
1050 *length = 4;
1051 }
1052 else
1053 {
1054 *length = 1;
1055 }
1056 }
1057
1058 return true;
1059}
1060
Geoff Lang6899b872016-10-14 11:30:13 -04001061bool ValidateGetActiveUniformBlockivBase(Context *context,
1062 GLuint program,
1063 GLuint uniformBlockIndex,
1064 GLenum pname,
1065 GLsizei *length)
1066{
1067 if (length)
1068 {
1069 *length = 0;
1070 }
1071
1072 if (context->getClientMajorVersion() < 3)
1073 {
1074 context->handleError(
1075 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1076 return false;
1077 }
1078
1079 Program *programObject = GetValidProgram(context, program);
1080 if (!programObject)
1081 {
1082 return false;
1083 }
1084
1085 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1086 {
1087 context->handleError(
1088 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1089 return false;
1090 }
1091
1092 switch (pname)
1093 {
1094 case GL_UNIFORM_BLOCK_BINDING:
1095 case GL_UNIFORM_BLOCK_DATA_SIZE:
1096 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1097 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1098 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1099 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1100 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1101 break;
1102
1103 default:
1104 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1105 return false;
1106 }
1107
1108 if (length)
1109 {
1110 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1111 {
1112 const UniformBlock &uniformBlock =
1113 programObject->getUniformBlockByIndex(uniformBlockIndex);
1114 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1115 }
1116 else
1117 {
1118 *length = 1;
1119 }
1120 }
1121
1122 return true;
1123}
1124
Geoff Langebebe1c2016-10-14 12:01:31 -04001125bool ValidateGetBufferParameterBase(ValidationContext *context,
1126 GLenum target,
1127 GLenum pname,
1128 bool pointerVersion,
1129 GLsizei *numParams)
1130{
1131 if (numParams)
1132 {
1133 *numParams = 0;
1134 }
1135
1136 if (!ValidBufferTarget(context, target))
1137 {
1138 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1139 return false;
1140 }
1141
1142 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1143 if (!buffer)
1144 {
1145 // A null buffer means that "0" is bound to the requested buffer target
1146 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1147 return false;
1148 }
1149
1150 const Extensions &extensions = context->getExtensions();
1151
1152 switch (pname)
1153 {
1154 case GL_BUFFER_USAGE:
1155 case GL_BUFFER_SIZE:
1156 break;
1157
1158 case GL_BUFFER_ACCESS_OES:
1159 if (!extensions.mapBuffer)
1160 {
1161 context->handleError(
1162 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1163 return false;
1164 }
1165 break;
1166
1167 case GL_BUFFER_MAPPED:
1168 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1169 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1170 !extensions.mapBufferRange)
1171 {
1172 context->handleError(Error(
1173 GL_INVALID_ENUM,
1174 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1175 return false;
1176 }
1177 break;
1178
1179 case GL_BUFFER_MAP_POINTER:
1180 if (!pointerVersion)
1181 {
1182 context->handleError(
1183 Error(GL_INVALID_ENUM,
1184 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1185 return false;
1186 }
1187 break;
1188
1189 case GL_BUFFER_ACCESS_FLAGS:
1190 case GL_BUFFER_MAP_OFFSET:
1191 case GL_BUFFER_MAP_LENGTH:
1192 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1193 {
1194 context->handleError(Error(
1195 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1196 return false;
1197 }
1198 break;
1199
1200 default:
1201 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1202 return false;
1203 }
1204
1205 // All buffer parameter queries return one value.
1206 if (numParams)
1207 {
1208 *numParams = 1;
1209 }
1210
1211 return true;
1212}
1213
Geoff Lang0a9661f2016-10-20 10:59:20 -07001214bool ValidateGetInternalFormativBase(Context *context,
1215 GLenum target,
1216 GLenum internalformat,
1217 GLenum pname,
1218 GLsizei bufSize,
1219 GLsizei *numParams)
1220{
1221 if (numParams)
1222 {
1223 *numParams = 0;
1224 }
1225
1226 if (context->getClientMajorVersion() < 3)
1227 {
1228 context->handleError(
1229 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1230 return false;
1231 }
1232
1233 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1234 if (!formatCaps.renderable)
1235 {
1236 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1237 return false;
1238 }
1239
1240 switch (target)
1241 {
1242 case GL_RENDERBUFFER:
1243 break;
1244
1245 default:
1246 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1247 return false;
1248 }
1249
1250 if (bufSize < 0)
1251 {
1252 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1253 return false;
1254 }
1255
1256 GLsizei maxWriteParams = 0;
1257 switch (pname)
1258 {
1259 case GL_NUM_SAMPLE_COUNTS:
1260 maxWriteParams = 1;
1261 break;
1262
1263 case GL_SAMPLES:
1264 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1265 break;
1266
1267 default:
1268 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1269 return false;
1270 }
1271
1272 if (numParams)
1273 {
1274 // glGetInternalFormativ will not overflow bufSize
1275 *numParams = std::min(bufSize, maxWriteParams);
1276 }
1277
1278 return true;
1279}
1280
Geoff Langf41a7152016-09-19 15:11:17 -04001281} // anonymous namespace
1282
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001283bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001284{
Jamie Madilld7460c72014-01-21 16:38:14 -05001285 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001286 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001287 case GL_TEXTURE_2D:
1288 case GL_TEXTURE_CUBE_MAP:
1289 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001290
Jamie Madilld7460c72014-01-21 16:38:14 -05001291 case GL_TEXTURE_3D:
1292 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001293 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001294
1295 default:
1296 return false;
1297 }
Jamie Madill35d15012013-10-07 10:46:37 -04001298}
1299
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001300bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1301{
1302 switch (target)
1303 {
1304 case GL_TEXTURE_2D:
1305 case GL_TEXTURE_CUBE_MAP:
1306 return true;
1307
1308 default:
1309 return false;
1310 }
1311}
1312
1313bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1314{
1315 switch (target)
1316 {
1317 case GL_TEXTURE_3D:
1318 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001319 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001320
1321 default:
1322 return false;
1323 }
1324}
1325
Ian Ewellbda75592016-04-18 17:25:54 -04001326// Most texture GL calls are not compatible with external textures, so we have a separate validation
1327// function for use in the GL calls that do
1328bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1329{
1330 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1331 (context->getExtensions().eglImageExternal ||
1332 context->getExtensions().eglStreamConsumerExternal);
1333}
1334
Shannon Woods4dfed832014-03-17 20:03:39 -04001335// This function differs from ValidTextureTarget in that the target must be
1336// usable as the destination of a 2D operation-- so a cube face is valid, but
1337// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001338// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001339bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001340{
1341 switch (target)
1342 {
1343 case GL_TEXTURE_2D:
1344 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1345 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1346 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1347 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1348 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1349 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1350 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001351 default:
1352 return false;
1353 }
1354}
1355
1356bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1357{
1358 switch (target)
1359 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001360 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001361 case GL_TEXTURE_2D_ARRAY:
1362 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001363 default:
1364 return false;
1365 }
1366}
1367
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001368bool ValidFramebufferTarget(GLenum target)
1369{
Geoff Langd4475812015-03-18 10:53:05 -04001370 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1371 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001372
1373 switch (target)
1374 {
1375 case GL_FRAMEBUFFER: return true;
1376 case GL_READ_FRAMEBUFFER: return true;
1377 case GL_DRAW_FRAMEBUFFER: return true;
1378 default: return false;
1379 }
1380}
1381
Jamie Madill29639852016-09-02 15:00:09 -04001382bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001383{
1384 switch (target)
1385 {
1386 case GL_ARRAY_BUFFER:
1387 case GL_ELEMENT_ARRAY_BUFFER:
1388 return true;
1389
Jamie Madill8c96d582014-03-05 15:01:23 -05001390 case GL_PIXEL_PACK_BUFFER:
1391 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001392 return (context->getExtensions().pixelBufferObject ||
1393 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001394
Shannon Woodsb3801742014-03-27 14:59:19 -04001395 case GL_COPY_READ_BUFFER:
1396 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001397 case GL_TRANSFORM_FEEDBACK_BUFFER:
1398 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001399 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001400
1401 default:
1402 return false;
1403 }
1404}
1405
Jamie Madillc29968b2016-01-20 11:17:23 -05001406bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001407{
Jamie Madillc29968b2016-01-20 11:17:23 -05001408 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001409 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001410 switch (target)
1411 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001412 case GL_TEXTURE_2D:
1413 maxDimension = caps.max2DTextureSize;
1414 break;
Geoff Langce635692013-09-24 13:56:32 -04001415 case GL_TEXTURE_CUBE_MAP:
1416 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1417 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1418 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1419 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1420 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001421 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1422 maxDimension = caps.maxCubeMapTextureSize;
1423 break;
1424 case GL_TEXTURE_3D:
1425 maxDimension = caps.max3DTextureSize;
1426 break;
1427 case GL_TEXTURE_2D_ARRAY:
1428 maxDimension = caps.max2DTextureSize;
1429 break;
Geoff Langce635692013-09-24 13:56:32 -04001430 default: UNREACHABLE();
1431 }
1432
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001433 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001434}
1435
Austin Kinross08528e12015-10-07 16:24:40 -07001436bool ValidImageSizeParameters(const Context *context,
1437 GLenum target,
1438 GLint level,
1439 GLsizei width,
1440 GLsizei height,
1441 GLsizei depth,
1442 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001443{
1444 if (level < 0 || width < 0 || height < 0 || depth < 0)
1445 {
1446 return false;
1447 }
1448
Austin Kinross08528e12015-10-07 16:24:40 -07001449 // TexSubImage parameters can be NPOT without textureNPOT extension,
1450 // as long as the destination texture is POT.
1451 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001452 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001453 {
1454 return false;
1455 }
1456
1457 if (!ValidMipLevel(context, target, level))
1458 {
1459 return false;
1460 }
1461
1462 return true;
1463}
1464
Geoff Lang0d8b7242015-09-09 14:56:53 -04001465bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1466{
1467 // List of compressed format that require that the texture size is smaller than or a multiple of
1468 // the compressed block size.
1469 switch (internalFormat)
1470 {
1471 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1472 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1473 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1474 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001475 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001476 return true;
1477
1478 default:
1479 return false;
1480 }
1481}
1482
Jamie Madillc29968b2016-01-20 11:17:23 -05001483bool ValidCompressedImageSize(const ValidationContext *context,
1484 GLenum internalFormat,
1485 GLsizei width,
1486 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001487{
Geoff Lang5d601382014-07-22 15:14:06 -04001488 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1489 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001490 {
1491 return false;
1492 }
1493
Geoff Lang0d8b7242015-09-09 14:56:53 -04001494 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001495 {
1496 return false;
1497 }
1498
Geoff Lang0d8b7242015-09-09 14:56:53 -04001499 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1500 {
1501 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1502 width % formatInfo.compressedBlockWidth != 0) ||
1503 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1504 height % formatInfo.compressedBlockHeight != 0))
1505 {
1506 return false;
1507 }
1508 }
1509
Geoff Langd4f180b2013-09-24 13:57:44 -04001510 return true;
1511}
1512
Geoff Langff5b2d52016-09-07 11:32:23 -04001513bool ValidImageDataSize(ValidationContext *context,
1514 GLenum textureTarget,
1515 GLsizei width,
1516 GLsizei height,
1517 GLsizei depth,
1518 GLenum internalFormat,
1519 GLenum type,
1520 const GLvoid *pixels,
1521 GLsizei imageSize)
1522{
1523 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1524 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1525 {
1526 // Checks are not required
1527 return true;
1528 }
1529
1530 // ...the data would be unpacked from the buffer object such that the memory reads required
1531 // would exceed the data store size.
1532 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1533 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1534 const gl::Extents size(width, height, depth);
1535 const auto &unpack = context->getGLState().getUnpackState();
1536
1537 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1538 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1539 if (endByteOrErr.isError())
1540 {
1541 context->handleError(endByteOrErr.getError());
1542 return false;
1543 }
1544
1545 GLuint endByte = endByteOrErr.getResult();
1546
1547 if (pixelUnpackBuffer)
1548 {
1549 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1550 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1551 checkedEndByte += checkedOffset;
1552
1553 if (!checkedEndByte.IsValid() ||
1554 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1555 {
1556 // Overflow past the end of the buffer
1557 context->handleError(Error(GL_INVALID_OPERATION));
1558 return false;
1559 }
1560 }
1561 else
1562 {
1563 ASSERT(imageSize >= 0);
1564 if (pixels == nullptr && imageSize != 0)
1565 {
1566 context->handleError(
1567 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1568 }
1569
1570 if (endByte > static_cast<GLuint>(imageSize))
1571 {
1572 context->handleError(
1573 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1574 return false;
1575 }
1576 }
1577
1578 return true;
1579}
1580
Geoff Lang37dde692014-01-31 16:34:54 -05001581bool ValidQueryType(const Context *context, GLenum queryType)
1582{
Geoff Langd4475812015-03-18 10:53:05 -04001583 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1584 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 -05001585
1586 switch (queryType)
1587 {
1588 case GL_ANY_SAMPLES_PASSED:
1589 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1590 return true;
1591 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001592 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001593 case GL_TIME_ELAPSED_EXT:
1594 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001595 case GL_COMMANDS_COMPLETED_CHROMIUM:
1596 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001597 default:
1598 return false;
1599 }
1600}
1601
Jamie Madillef300b12016-10-07 15:12:09 -04001602Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001603{
1604 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1605 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1606 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1607
Dian Xiang769769a2015-09-09 15:20:08 -07001608 Program *validProgram = context->getProgram(id);
1609
1610 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001611 {
Dian Xiang769769a2015-09-09 15:20:08 -07001612 if (context->getShader(id))
1613 {
Jamie Madill437fa652016-05-03 15:13:24 -04001614 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001615 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1616 }
1617 else
1618 {
Jamie Madill437fa652016-05-03 15:13:24 -04001619 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001620 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001621 }
Dian Xiang769769a2015-09-09 15:20:08 -07001622
1623 return validProgram;
1624}
1625
Jamie Madillef300b12016-10-07 15:12:09 -04001626Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001627{
1628 // See ValidProgram for spec details.
1629
1630 Shader *validShader = context->getShader(id);
1631
1632 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001633 {
Dian Xiang769769a2015-09-09 15:20:08 -07001634 if (context->getProgram(id))
1635 {
Jamie Madill437fa652016-05-03 15:13:24 -04001636 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001637 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1638 }
1639 else
1640 {
Jamie Madill437fa652016-05-03 15:13:24 -04001641 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001642 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001643 }
Dian Xiang769769a2015-09-09 15:20:08 -07001644
1645 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001646}
1647
Geoff Langb1196682014-07-23 13:47:29 -04001648bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001649{
1650 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1651 {
1652 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1653
Geoff Langaae65a42014-05-26 12:43:44 -04001654 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001655 {
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001658 }
1659 }
1660 else
1661 {
1662 switch (attachment)
1663 {
1664 case GL_DEPTH_ATTACHMENT:
1665 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001666 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001667
1668 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001669 if (!context->getExtensions().webglCompatibility &&
1670 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001671 {
1672 context->handleError(Error(GL_INVALID_ENUM));
1673 return false;
1674 }
1675 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001676
1677 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001679 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001680 }
1681 }
1682
1683 return true;
1684}
1685
Corentin Walleze0902642014-11-04 12:32:15 -08001686bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1687 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001688{
1689 switch (target)
1690 {
1691 case GL_RENDERBUFFER:
1692 break;
1693 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001695 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001696 }
1697
1698 if (width < 0 || height < 0 || samples < 0)
1699 {
Jamie Madill437fa652016-05-03 15:13:24 -04001700 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001701 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001702 }
1703
Geoff Langd87878e2014-09-19 15:42:59 -04001704 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1705 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001708 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001709 }
1710
1711 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1712 // 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 -08001713 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001714 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001715 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001716 {
Jamie Madill437fa652016-05-03 15:13:24 -04001717 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001718 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001719 }
1720
Geoff Langaae65a42014-05-26 12:43:44 -04001721 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 }
1726
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001727 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 if (handle == 0)
1729 {
Jamie Madill437fa652016-05-03 15:13:24 -04001730 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001731 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001732 }
1733
1734 return true;
1735}
1736
Corentin Walleze0902642014-11-04 12:32:15 -08001737bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1738 GLenum internalformat, GLsizei width, GLsizei height)
1739{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001740 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001741
1742 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001743 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001744 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001745 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001746 {
Jamie Madill437fa652016-05-03 15:13:24 -04001747 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001748 return false;
1749 }
1750
1751 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1752 // the specified storage. This is different than ES 3.0 in which a sample number higher
1753 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001754 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001755 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001756 {
Geoff Langa4903b72015-03-02 16:02:48 -08001757 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1758 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001761 return false;
1762 }
Corentin Walleze0902642014-11-04 12:32:15 -08001763 }
1764
1765 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1766}
1767
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001768bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1769 GLenum renderbuffertarget, GLuint renderbuffer)
1770{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001771 if (!ValidFramebufferTarget(target))
1772 {
Jamie Madill437fa652016-05-03 15:13:24 -04001773 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001774 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001775 }
1776
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001777 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001778
Jamie Madill84115c92015-04-23 15:00:07 -04001779 ASSERT(framebuffer);
1780 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001781 {
Jamie Madill437fa652016-05-03 15:13:24 -04001782 context->handleError(
1783 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001784 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001785 }
1786
Jamie Madillb4472272014-07-03 10:38:55 -04001787 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001788 {
Jamie Madillb4472272014-07-03 10:38:55 -04001789 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001790 }
1791
Jamie Madillab9d82c2014-01-21 16:38:14 -05001792 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1793 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1794 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1795 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1796 if (renderbuffer != 0)
1797 {
1798 if (!context->getRenderbuffer(renderbuffer))
1799 {
Jamie Madill437fa652016-05-03 15:13:24 -04001800 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001801 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001802 }
1803 }
1804
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001805 return true;
1806}
1807
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001808bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001809 GLint srcX0,
1810 GLint srcY0,
1811 GLint srcX1,
1812 GLint srcY1,
1813 GLint dstX0,
1814 GLint dstY0,
1815 GLint dstX1,
1816 GLint dstY1,
1817 GLbitfield mask,
1818 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001819{
1820 switch (filter)
1821 {
1822 case GL_NEAREST:
1823 break;
1824 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001825 break;
1826 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001827 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001828 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001829 }
1830
1831 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001834 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001835 }
1836
1837 if (mask == 0)
1838 {
1839 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1840 // buffers are copied.
1841 return false;
1842 }
1843
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001844 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1845 // color buffer, leaving only nearest being unfiltered from above
1846 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1847 {
Jamie Madill437fa652016-05-03 15:13:24 -04001848 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001849 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001850 }
1851
Jamie Madill51f40ec2016-06-15 14:06:00 -04001852 const auto &glState = context->getGLState();
1853 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1854 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001855
1856 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001859 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001860 }
1861
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001862 if (readFramebuffer->id() == drawFramebuffer->id())
1863 {
1864 context->handleError(Error(GL_INVALID_OPERATION));
1865 return false;
1866 }
1867
Jamie Madill51f40ec2016-06-15 14:06:00 -04001868 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001869 {
Jamie Madill437fa652016-05-03 15:13:24 -04001870 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001871 return false;
1872 }
1873
Jamie Madill51f40ec2016-06-15 14:06:00 -04001874 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001875 {
Jamie Madill437fa652016-05-03 15:13:24 -04001876 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001877 return false;
1878 }
1879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001880 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001881 {
Jamie Madill437fa652016-05-03 15:13:24 -04001882 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001883 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001884 }
1885
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001886 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1887
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001888 if (mask & GL_COLOR_BUFFER_BIT)
1889 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001890 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1891 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001892 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001893
1894 if (readColorBuffer && drawColorBuffer)
1895 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001896 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001897
Geoff Langa15472a2015-08-11 11:48:03 -04001898 for (size_t drawbufferIdx = 0;
1899 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001900 {
Geoff Langa15472a2015-08-11 11:48:03 -04001901 const FramebufferAttachment *attachment =
1902 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1903 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001904 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001905 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001906
Geoff Langb2f3d052013-08-13 12:49:27 -04001907 // The GL ES 3.0.2 spec (pg 193) states that:
1908 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1909 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1910 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001911 // Changes with EXT_color_buffer_float:
1912 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001913 GLenum readComponentType = readFormat.info->componentType;
1914 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001915 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1916 readComponentType == GL_SIGNED_NORMALIZED);
1917 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1918 drawComponentType == GL_SIGNED_NORMALIZED);
1919
1920 if (extensions.colorBufferFloat)
1921 {
1922 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1923 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1924
1925 if (readFixedOrFloat != drawFixedOrFloat)
1926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001928 "If the read buffer contains fixed-point or "
1929 "floating-point values, the draw buffer "
1930 "must as well."));
1931 return false;
1932 }
1933 }
1934 else if (readFixedPoint != drawFixedPoint)
1935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001937 "If the read buffer contains fixed-point "
1938 "values, the draw buffer must as well."));
1939 return false;
1940 }
1941
1942 if (readComponentType == GL_UNSIGNED_INT &&
1943 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001944 {
Jamie Madill437fa652016-05-03 15:13:24 -04001945 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001946 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001947 }
1948
Jamie Madill6163c752015-12-07 16:32:59 -05001949 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001950 {
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001952 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001953 }
1954
Jamie Madilla3944d42016-07-22 22:13:26 -04001955 if (readColorBuffer->getSamples() > 0 &&
1956 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001957 {
Jamie Madill437fa652016-05-03 15:13:24 -04001958 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001960 }
1961 }
1962 }
1963
Jamie Madilla3944d42016-07-22 22:13:26 -04001964 if ((readFormat.info->componentType == GL_INT ||
1965 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1966 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 {
Jamie Madill437fa652016-05-03 15:13:24 -04001968 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001969 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001970 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 }
1972 }
1973
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001974 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1975 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1976 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001977 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001978 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001979 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001980 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1981 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001982
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001983 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001984 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001985 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001986 {
Jamie Madill437fa652016-05-03 15:13:24 -04001987 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001988 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001989 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001990
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001991 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001992 {
Jamie Madill437fa652016-05-03 15:13:24 -04001993 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001995 }
1996 }
1997 }
1998 }
1999
2000 return true;
2001}
2002
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002003bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002004 GLint x,
2005 GLint y,
2006 GLsizei width,
2007 GLsizei height,
2008 GLenum format,
2009 GLenum type,
2010 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002011{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002012 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2013}
2014
2015bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2016 GLint x,
2017 GLint y,
2018 GLsizei width,
2019 GLsizei height,
2020 GLenum format,
2021 GLenum type,
2022 GLsizei bufSize,
2023 GLsizei *length,
2024 GLvoid *pixels)
2025{
2026 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002027 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002028 return false;
2029 }
2030
Geoff Lang62fce5b2016-09-30 10:46:35 -04002031 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2032 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002033 {
Geoff Langb1196682014-07-23 13:47:29 -04002034 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002035 }
2036
Geoff Lang62fce5b2016-09-30 10:46:35 -04002037 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002038 {
Geoff Langb1196682014-07-23 13:47:29 -04002039 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002040 }
2041
Jamie Madillc29968b2016-01-20 11:17:23 -05002042 return true;
2043}
2044
2045bool ValidateReadnPixelsEXT(Context *context,
2046 GLint x,
2047 GLint y,
2048 GLsizei width,
2049 GLsizei height,
2050 GLenum format,
2051 GLenum type,
2052 GLsizei bufSize,
2053 GLvoid *pixels)
2054{
2055 if (bufSize < 0)
2056 {
Jamie Madill437fa652016-05-03 15:13:24 -04002057 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002058 return false;
2059 }
2060
Geoff Lang62fce5b2016-09-30 10:46:35 -04002061 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2062 pixels);
2063}
Jamie Madill26e91952014-03-05 15:01:27 -05002064
Geoff Lang62fce5b2016-09-30 10:46:35 -04002065bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2066 GLint x,
2067 GLint y,
2068 GLsizei width,
2069 GLsizei height,
2070 GLenum format,
2071 GLenum type,
2072 GLsizei bufSize,
2073 GLsizei *length,
2074 GLvoid *data)
2075{
2076 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002077 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002078 return false;
2079 }
2080
Geoff Lang62fce5b2016-09-30 10:46:35 -04002081 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002082 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002083 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002084 }
2085
Geoff Lang62fce5b2016-09-30 10:46:35 -04002086 if (!ValidateRobustBufferSize(context, bufSize, *length))
2087 {
2088 return false;
2089 }
2090
2091 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002092}
2093
Olli Etuaho41997e72016-03-10 13:38:39 +02002094bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002095{
2096 if (!context->getExtensions().occlusionQueryBoolean &&
2097 !context->getExtensions().disjointTimerQuery)
2098 {
Jamie Madill437fa652016-05-03 15:13:24 -04002099 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002100 return false;
2101 }
2102
Olli Etuaho41997e72016-03-10 13:38:39 +02002103 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002104}
2105
Olli Etuaho41997e72016-03-10 13:38:39 +02002106bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002107{
2108 if (!context->getExtensions().occlusionQueryBoolean &&
2109 !context->getExtensions().disjointTimerQuery)
2110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002112 return false;
2113 }
2114
Olli Etuaho41997e72016-03-10 13:38:39 +02002115 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002116}
2117
2118bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002119{
2120 if (!ValidQueryType(context, target))
2121 {
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002123 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002124 }
2125
2126 if (id == 0)
2127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002129 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002130 }
2131
2132 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2133 // of zero, if the active query object name for <target> is non-zero (for the
2134 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2135 // the active query for either target is non-zero), if <id> is the name of an
2136 // existing query object whose type does not match <target>, or if <id> is the
2137 // active query object name for any query type, the error INVALID_OPERATION is
2138 // generated.
2139
2140 // Ensure no other queries are active
2141 // NOTE: If other queries than occlusion are supported, we will need to check
2142 // separately that:
2143 // a) The query ID passed is not the current active query for any target/type
2144 // b) There are no active queries for the requested target (and in the case
2145 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2146 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002147
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002148 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002149 {
Jamie Madill437fa652016-05-03 15:13:24 -04002150 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002151 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002152 }
2153
2154 Query *queryObject = context->getQuery(id, true, target);
2155
2156 // check that name was obtained with glGenQueries
2157 if (!queryObject)
2158 {
Jamie Madill437fa652016-05-03 15:13:24 -04002159 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002160 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002161 }
2162
2163 // check for type mismatch
2164 if (queryObject->getType() != target)
2165 {
Jamie Madill437fa652016-05-03 15:13:24 -04002166 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002167 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002168 }
2169
2170 return true;
2171}
2172
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002173bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2174{
2175 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002176 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002179 return false;
2180 }
2181
2182 return ValidateBeginQueryBase(context, target, id);
2183}
2184
2185bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002186{
2187 if (!ValidQueryType(context, target))
2188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002191 }
2192
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002193 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002194
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002195 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002196 {
Jamie Madill437fa652016-05-03 15:13:24 -04002197 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002198 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002199 }
2200
Jamie Madill45c785d2014-05-13 14:09:34 -04002201 return true;
2202}
2203
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002204bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2205{
2206 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002207 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002210 return false;
2211 }
2212
2213 return ValidateEndQueryBase(context, target);
2214}
2215
2216bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2217{
2218 if (!context->getExtensions().disjointTimerQuery)
2219 {
Jamie Madill437fa652016-05-03 15:13:24 -04002220 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002221 return false;
2222 }
2223
2224 if (target != GL_TIMESTAMP_EXT)
2225 {
Jamie Madill437fa652016-05-03 15:13:24 -04002226 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002227 return false;
2228 }
2229
2230 Query *queryObject = context->getQuery(id, true, target);
2231 if (queryObject == nullptr)
2232 {
Jamie Madill437fa652016-05-03 15:13:24 -04002233 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002234 return false;
2235 }
2236
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002237 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002238 {
Jamie Madill437fa652016-05-03 15:13:24 -04002239 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002240 return false;
2241 }
2242
2243 return true;
2244}
2245
Geoff Lang2186c382016-10-14 10:54:54 -04002246bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002247{
Geoff Lang2186c382016-10-14 10:54:54 -04002248 if (numParams)
2249 {
2250 *numParams = 0;
2251 }
2252
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002253 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2254 {
Jamie Madill437fa652016-05-03 15:13:24 -04002255 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002256 return false;
2257 }
2258
2259 switch (pname)
2260 {
2261 case GL_CURRENT_QUERY_EXT:
2262 if (target == GL_TIMESTAMP_EXT)
2263 {
Jamie Madill437fa652016-05-03 15:13:24 -04002264 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002265 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2266 return false;
2267 }
2268 break;
2269 case GL_QUERY_COUNTER_BITS_EXT:
2270 if (!context->getExtensions().disjointTimerQuery ||
2271 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2272 {
Jamie Madill437fa652016-05-03 15:13:24 -04002273 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274 return false;
2275 }
2276 break;
2277 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002278 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002279 return false;
2280 }
2281
Geoff Lang2186c382016-10-14 10:54:54 -04002282 if (numParams)
2283 {
2284 // All queries return only one value
2285 *numParams = 1;
2286 }
2287
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002288 return true;
2289}
2290
2291bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2292{
2293 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002294 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002295 {
Jamie Madill437fa652016-05-03 15:13:24 -04002296 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002297 return false;
2298 }
2299
Geoff Lang2186c382016-10-14 10:54:54 -04002300 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002301}
2302
Geoff Lang2186c382016-10-14 10:54:54 -04002303bool ValidateGetQueryivRobustANGLE(Context *context,
2304 GLenum target,
2305 GLenum pname,
2306 GLsizei bufSize,
2307 GLsizei *length,
2308 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002309{
Geoff Lang2186c382016-10-14 10:54:54 -04002310 if (!ValidateRobustEntryPoint(context, bufSize))
2311 {
2312 return false;
2313 }
2314
2315 if (!ValidateGetQueryivBase(context, target, pname, length))
2316 {
2317 return false;
2318 }
2319
2320 if (!ValidateRobustBufferSize(context, bufSize, *length))
2321 {
2322 return false;
2323 }
2324
2325 return true;
2326}
2327
2328bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2329{
2330 if (numParams)
2331 {
2332 *numParams = 0;
2333 }
2334
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002335 Query *queryObject = context->getQuery(id, false, GL_NONE);
2336
2337 if (!queryObject)
2338 {
Jamie Madill437fa652016-05-03 15:13:24 -04002339 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002340 return false;
2341 }
2342
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002343 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002344 {
Jamie Madill437fa652016-05-03 15:13:24 -04002345 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002346 return false;
2347 }
2348
2349 switch (pname)
2350 {
2351 case GL_QUERY_RESULT_EXT:
2352 case GL_QUERY_RESULT_AVAILABLE_EXT:
2353 break;
2354
2355 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002356 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002357 return false;
2358 }
2359
Geoff Lang2186c382016-10-14 10:54:54 -04002360 if (numParams)
2361 {
2362 *numParams = 1;
2363 }
2364
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002365 return true;
2366}
2367
2368bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2369{
2370 if (!context->getExtensions().disjointTimerQuery)
2371 {
Jamie Madill437fa652016-05-03 15:13:24 -04002372 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002373 return false;
2374 }
Geoff Lang2186c382016-10-14 10:54:54 -04002375 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2376}
2377
2378bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2379 GLuint id,
2380 GLenum pname,
2381 GLsizei bufSize,
2382 GLsizei *length,
2383 GLint *params)
2384{
2385 if (!context->getExtensions().disjointTimerQuery)
2386 {
2387 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2388 return false;
2389 }
2390
2391 if (!ValidateRobustEntryPoint(context, bufSize))
2392 {
2393 return false;
2394 }
2395
2396 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2397 {
2398 return false;
2399 }
2400
2401 if (!ValidateRobustBufferSize(context, bufSize, *length))
2402 {
2403 return false;
2404 }
2405
2406 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002407}
2408
2409bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2410{
2411 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002412 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002413 {
Jamie Madill437fa652016-05-03 15:13:24 -04002414 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002415 return false;
2416 }
Geoff Lang2186c382016-10-14 10:54:54 -04002417 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2418}
2419
2420bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2421 GLuint id,
2422 GLenum pname,
2423 GLsizei bufSize,
2424 GLsizei *length,
2425 GLuint *params)
2426{
2427 if (!context->getExtensions().disjointTimerQuery &&
2428 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2429 {
2430 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2431 return false;
2432 }
2433
2434 if (!ValidateRobustEntryPoint(context, bufSize))
2435 {
2436 return false;
2437 }
2438
2439 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2440 {
2441 return false;
2442 }
2443
2444 if (!ValidateRobustBufferSize(context, bufSize, *length))
2445 {
2446 return false;
2447 }
2448
2449 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002450}
2451
2452bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2453{
2454 if (!context->getExtensions().disjointTimerQuery)
2455 {
Jamie Madill437fa652016-05-03 15:13:24 -04002456 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002457 return false;
2458 }
Geoff Lang2186c382016-10-14 10:54:54 -04002459 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2460}
2461
2462bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2463 GLuint id,
2464 GLenum pname,
2465 GLsizei bufSize,
2466 GLsizei *length,
2467 GLint64 *params)
2468{
2469 if (!context->getExtensions().disjointTimerQuery)
2470 {
2471 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2472 return false;
2473 }
2474
2475 if (!ValidateRobustEntryPoint(context, bufSize))
2476 {
2477 return false;
2478 }
2479
2480 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2481 {
2482 return false;
2483 }
2484
2485 if (!ValidateRobustBufferSize(context, bufSize, *length))
2486 {
2487 return false;
2488 }
2489
2490 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002491}
2492
2493bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2494{
2495 if (!context->getExtensions().disjointTimerQuery)
2496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 return false;
2499 }
Geoff Lang2186c382016-10-14 10:54:54 -04002500 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2501}
2502
2503bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2504 GLuint id,
2505 GLenum pname,
2506 GLsizei bufSize,
2507 GLsizei *length,
2508 GLuint64 *params)
2509{
2510 if (!context->getExtensions().disjointTimerQuery)
2511 {
2512 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2513 return false;
2514 }
2515
2516 if (!ValidateRobustEntryPoint(context, bufSize))
2517 {
2518 return false;
2519 }
2520
2521 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2522 {
2523 return false;
2524 }
2525
2526 if (!ValidateRobustBufferSize(context, bufSize, *length))
2527 {
2528 return false;
2529 }
2530
2531 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002532}
2533
Jamie Madill62d31cb2015-09-11 13:25:51 -04002534static bool ValidateUniformCommonBase(gl::Context *context,
2535 GLenum targetUniformType,
2536 GLint location,
2537 GLsizei count,
2538 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002539{
2540 if (count < 0)
2541 {
Jamie Madill437fa652016-05-03 15:13:24 -04002542 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002544 }
2545
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002546 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002547 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002548 {
Jamie Madill437fa652016-05-03 15:13:24 -04002549 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002550 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002551 }
2552
Geoff Langd8605522016-04-13 10:19:12 -04002553 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002554 {
2555 // Silently ignore the uniform command
2556 return false;
2557 }
2558
Geoff Lang7dd2e102014-11-10 15:19:26 -05002559 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002560 {
Jamie Madill437fa652016-05-03 15:13:24 -04002561 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002562 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002563 }
2564
Jamie Madill62d31cb2015-09-11 13:25:51 -04002565 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002566
2567 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002568 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002569 {
Jamie Madill437fa652016-05-03 15:13:24 -04002570 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002571 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002572 }
2573
Jamie Madill62d31cb2015-09-11 13:25:51 -04002574 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002575 return true;
2576}
2577
Jamie Madillaa981bd2014-05-20 10:55:55 -04002578bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2579{
2580 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002581 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2582 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002583 {
Jamie Madill437fa652016-05-03 15:13:24 -04002584 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002585 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002586 }
2587
Jamie Madill62d31cb2015-09-11 13:25:51 -04002588 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002589 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2590 {
2591 return false;
2592 }
2593
Jamie Madillf2575982014-06-25 16:04:54 -04002594 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002595 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002596 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2597 {
Jamie Madill437fa652016-05-03 15:13:24 -04002598 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002599 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002600 }
2601
2602 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002603}
2604
2605bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2606 GLboolean transpose)
2607{
2608 // Check for ES3 uniform entry points
2609 int rows = VariableRowCount(matrixType);
2610 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002611 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002612 {
Jamie Madill437fa652016-05-03 15:13:24 -04002613 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002614 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002615 }
2616
Martin Radev1be913c2016-07-11 17:59:16 +03002617 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002618 {
Jamie Madill437fa652016-05-03 15:13:24 -04002619 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002620 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002621 }
2622
Jamie Madill62d31cb2015-09-11 13:25:51 -04002623 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002624 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2625 {
2626 return false;
2627 }
2628
2629 if (uniform->type != matrixType)
2630 {
Jamie Madill437fa652016-05-03 15:13:24 -04002631 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002632 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002633 }
2634
2635 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002636}
2637
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002638bool ValidateStateQuery(ValidationContext *context,
2639 GLenum pname,
2640 GLenum *nativeType,
2641 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002642{
2643 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2644 {
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002646 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002647 }
2648
Jamie Madill0af26e12015-03-05 19:54:33 -05002649 const Caps &caps = context->getCaps();
2650
Jamie Madill893ab082014-05-16 16:56:10 -04002651 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2652 {
2653 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2654
Jamie Madill0af26e12015-03-05 19:54:33 -05002655 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002656 {
Jamie Madill437fa652016-05-03 15:13:24 -04002657 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002658 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002659 }
2660 }
2661
2662 switch (pname)
2663 {
2664 case GL_TEXTURE_BINDING_2D:
2665 case GL_TEXTURE_BINDING_CUBE_MAP:
2666 case GL_TEXTURE_BINDING_3D:
2667 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002668 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002669 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002670 if (!context->getExtensions().eglStreamConsumerExternal &&
2671 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002672 {
John Bauman18319182016-09-28 14:22:27 -07002673 context->handleError(Error(GL_INVALID_ENUM,
2674 "Neither NV_EGL_stream_consumer_external nor "
2675 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002676 return false;
2677 }
2678 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002679
2680 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2681 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2682 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002683 if (context->getGLState().getReadFramebuffer()->checkStatus(
2684 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002685 {
Jamie Madill437fa652016-05-03 15:13:24 -04002686 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002687 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002688 }
2689
Jamie Madill51f40ec2016-06-15 14:06:00 -04002690 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2691 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002692
2693 if (framebuffer->getReadBufferState() == GL_NONE)
2694 {
2695 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2696 return false;
2697 }
2698
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002699 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002700 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002701 {
Jamie Madill437fa652016-05-03 15:13:24 -04002702 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002703 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002704 }
2705 }
2706 break;
2707
2708 default:
2709 break;
2710 }
2711
2712 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002713 if (*numParams == 0)
2714 {
2715 return false;
2716 }
2717
2718 return true;
2719}
2720
2721bool ValidateRobustStateQuery(ValidationContext *context,
2722 GLenum pname,
2723 GLsizei bufSize,
2724 GLenum *nativeType,
2725 unsigned int *numParams)
2726{
2727 if (!ValidateRobustEntryPoint(context, bufSize))
2728 {
2729 return false;
2730 }
2731
2732 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2733 {
2734 return false;
2735 }
2736
2737 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002738 {
2739 return false;
2740 }
2741
2742 return true;
2743}
2744
Jamie Madillc29968b2016-01-20 11:17:23 -05002745bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2746 GLenum target,
2747 GLint level,
2748 GLenum internalformat,
2749 bool isSubImage,
2750 GLint xoffset,
2751 GLint yoffset,
2752 GLint zoffset,
2753 GLint x,
2754 GLint y,
2755 GLsizei width,
2756 GLsizei height,
2757 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002758 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002759{
Jamie Madill560a8d82014-05-21 13:06:20 -04002760 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2761 {
Jamie Madill437fa652016-05-03 15:13:24 -04002762 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002763 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002764 }
2765
2766 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2767 {
Jamie Madill437fa652016-05-03 15:13:24 -04002768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002769 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002770 }
2771
2772 if (border != 0)
2773 {
Jamie Madill437fa652016-05-03 15:13:24 -04002774 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002775 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002776 }
2777
2778 if (!ValidMipLevel(context, target, level))
2779 {
Jamie Madill437fa652016-05-03 15:13:24 -04002780 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002781 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002782 }
2783
Jamie Madill51f40ec2016-06-15 14:06:00 -04002784 const auto &state = context->getGLState();
2785 auto readFramebuffer = state.getReadFramebuffer();
2786 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002787 {
Jamie Madill437fa652016-05-03 15:13:24 -04002788 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002789 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002790 }
2791
Jamie Madill51f40ec2016-06-15 14:06:00 -04002792 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -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 Madill560a8d82014-05-21 13:06:20 -04002796 }
2797
Martin Radev138064f2016-07-15 12:03:41 +03002798 if (readFramebuffer->getReadBufferState() == GL_NONE)
2799 {
2800 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2801 return false;
2802 }
2803
Geoff Langaae65a42014-05-26 12:43:44 -04002804 const gl::Caps &caps = context->getCaps();
2805
Geoff Langaae65a42014-05-26 12:43:44 -04002806 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002807 switch (target)
2808 {
2809 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002810 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002811 break;
2812
2813 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2814 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2815 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2816 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2817 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2818 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002819 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002820 break;
2821
2822 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002823 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002824 break;
2825
2826 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002827 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002828 break;
2829
2830 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002831 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002832 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002833 }
2834
Jamie Madillc29968b2016-01-20 11:17:23 -05002835 gl::Texture *texture =
2836 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002837 if (!texture)
2838 {
Jamie Madill437fa652016-05-03 15:13:24 -04002839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002840 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002841 }
2842
Geoff Lang69cce582015-09-17 13:20:36 -04002843 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002844 {
Jamie Madill437fa652016-05-03 15:13:24 -04002845 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002846 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002847 }
2848
Geoff Lang5d601382014-07-22 15:14:06 -04002849 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2850
2851 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002852 {
Jamie Madill437fa652016-05-03 15:13:24 -04002853 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002854 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002855 }
2856
Geoff Langa9be0dc2014-12-17 12:34:40 -05002857 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002858 {
Jamie Madill437fa652016-05-03 15:13:24 -04002859 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002860 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002861 }
2862
2863 if (isSubImage)
2864 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002865 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2866 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2867 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002868 {
Jamie Madill437fa652016-05-03 15:13:24 -04002869 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002870 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002871 }
2872 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002873 else
2874 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002875 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002876 {
Jamie Madill437fa652016-05-03 15:13:24 -04002877 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002878 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002879 }
2880
Martin Radev1be913c2016-07-11 17:59:16 +03002881 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002882 {
Jamie Madill437fa652016-05-03 15:13:24 -04002883 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002884 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002885 }
2886
2887 int maxLevelDimension = (maxDimension >> level);
2888 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2889 {
Jamie Madill437fa652016-05-03 15:13:24 -04002890 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002891 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002892 }
2893 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002894
Jamie Madill0c8abca2016-07-22 20:21:26 -04002895 if (textureFormatOut)
2896 {
2897 *textureFormatOut = texture->getFormat(target, level);
2898 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002899 return true;
2900}
2901
Jamie Madillf25855c2015-11-03 11:06:18 -05002902static bool ValidateDrawBase(ValidationContext *context,
2903 GLenum mode,
2904 GLsizei count,
2905 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002906{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002907 switch (mode)
2908 {
2909 case GL_POINTS:
2910 case GL_LINES:
2911 case GL_LINE_LOOP:
2912 case GL_LINE_STRIP:
2913 case GL_TRIANGLES:
2914 case GL_TRIANGLE_STRIP:
2915 case GL_TRIANGLE_FAN:
2916 break;
2917 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002918 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002919 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002920 }
2921
Jamie Madill250d33f2014-06-06 17:09:03 -04002922 if (count < 0)
2923 {
Jamie Madill437fa652016-05-03 15:13:24 -04002924 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002925 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002926 }
2927
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002928 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002929
Jamie Madill250d33f2014-06-06 17:09:03 -04002930 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002931 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002932 {
Jamie Madill437fa652016-05-03 15:13:24 -04002933 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002934 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002935 }
2936
Jamie Madill51f40ec2016-06-15 14:06:00 -04002937 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002938 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002939 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002940 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2941 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2942 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2943 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2944 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2945 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002946 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002947 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2948 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002949 {
2950 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2951 // Section 6.10 of the WebGL 1.0 spec
2952 ERR(
2953 "This ANGLE implementation does not support separate front/back stencil "
2954 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002955 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002956 return false;
2957 }
Jamie Madillac528012014-06-20 13:21:23 -04002958 }
2959
Jamie Madill51f40ec2016-06-15 14:06:00 -04002960 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002961 {
Jamie Madill437fa652016-05-03 15:13:24 -04002962 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002963 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002964 }
2965
Geoff Lang7dd2e102014-11-10 15:19:26 -05002966 gl::Program *program = state.getProgram();
2967 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002968 {
Jamie Madill437fa652016-05-03 15:13:24 -04002969 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002970 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002971 }
2972
Geoff Lang7dd2e102014-11-10 15:19:26 -05002973 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002974 {
Jamie Madill437fa652016-05-03 15:13:24 -04002975 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002976 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002977 }
2978
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002979 // Uniform buffer validation
2980 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2981 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002982 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002983 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002984 const OffsetBindingPointer<Buffer> &uniformBuffer =
2985 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002986
Geoff Lang5d124a62015-09-15 13:03:27 -04002987 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002988 {
2989 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002990 context->handleError(
2991 Error(GL_INVALID_OPERATION,
2992 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002993 return false;
2994 }
2995
Geoff Lang5d124a62015-09-15 13:03:27 -04002996 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002997 if (uniformBufferSize == 0)
2998 {
2999 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003000 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003001 }
3002
Jamie Madill62d31cb2015-09-11 13:25:51 -04003003 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003004 {
3005 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003006 context->handleError(
3007 Error(GL_INVALID_OPERATION,
3008 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003009 return false;
3010 }
3011 }
3012
Jamie Madill250d33f2014-06-06 17:09:03 -04003013 // No-op if zero count
3014 return (count > 0);
3015}
3016
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003017bool ValidateDrawArrays(ValidationContext *context,
3018 GLenum mode,
3019 GLint first,
3020 GLsizei count,
3021 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003022{
Jamie Madillfd716582014-06-06 17:09:04 -04003023 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003024 {
Jamie Madill437fa652016-05-03 15:13:24 -04003025 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003026 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003027 }
3028
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003029 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003030 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003031 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
3032 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003033 {
3034 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
3035 // that does not match the current transform feedback object's draw mode (if transform feedback
3036 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003037 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003038 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003039 }
3040
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003041 if (!ValidateDrawBase(context, mode, count, primcount))
3042 {
3043 return false;
3044 }
3045
3046 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003047 {
3048 return false;
3049 }
3050
3051 return true;
3052}
3053
Geoff Langb1196682014-07-23 13:47:29 -04003054bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003055{
3056 if (primcount < 0)
3057 {
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003060 }
3061
Jamie Madill2b976812014-08-25 15:47:49 -04003062 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003063 {
3064 return false;
3065 }
3066
3067 // No-op if zero primitive count
3068 return (primcount > 0);
3069}
3070
Geoff Lang87a93302014-09-16 13:29:43 -04003071static bool ValidateDrawInstancedANGLE(Context *context)
3072{
3073 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003074 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003075
Geoff Lang7dd2e102014-11-10 15:19:26 -05003076 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003077
3078 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003079 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003080 {
3081 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003082 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003083 {
3084 return true;
3085 }
3086 }
3087
Jamie Madill437fa652016-05-03 15:13:24 -04003088 context->handleError(Error(GL_INVALID_OPERATION,
3089 "ANGLE_instanced_arrays requires that at least one active attribute"
3090 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003091 return false;
3092}
3093
3094bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
3095{
3096 if (!ValidateDrawInstancedANGLE(context))
3097 {
3098 return false;
3099 }
3100
3101 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3102}
3103
Jamie Madillf25855c2015-11-03 11:06:18 -05003104bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003105 GLenum mode,
3106 GLsizei count,
3107 GLenum type,
3108 const GLvoid *indices,
3109 GLsizei primcount,
3110 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003111{
Jamie Madill250d33f2014-06-06 17:09:03 -04003112 switch (type)
3113 {
3114 case GL_UNSIGNED_BYTE:
3115 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03003116 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003117 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03003118 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3119 {
3120 context->handleError(Error(GL_INVALID_ENUM));
3121 return false;
3122 }
3123 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003124 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003126 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003127 }
3128
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003129 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003130
3131 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003132 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003133 {
3134 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3135 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003136 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003137 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003138 }
3139
3140 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003141 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003142 {
Jamie Madill437fa652016-05-03 15:13:24 -04003143 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003144 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003145 }
3146
Jamie Madill2b976812014-08-25 15:47:49 -04003147 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003148 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003149 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003150 {
Jamie Madill437fa652016-05-03 15:13:24 -04003151 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003152 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003153 }
3154
Jamie Madillae3000b2014-08-25 15:47:51 -04003155 if (elementArrayBuffer)
3156 {
3157 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3158
3159 GLint64 offset = reinterpret_cast<GLint64>(indices);
3160 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3161
3162 // check for integer overflows
3163 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3164 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003168 }
3169
3170 // Check for reading past the end of the bound buffer object
3171 if (byteCount > elementArrayBuffer->getSize())
3172 {
Jamie Madill437fa652016-05-03 15:13:24 -04003173 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003174 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003175 }
3176 }
3177 else if (!indices)
3178 {
3179 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003180 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003181 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003182 }
3183
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003184 if (!ValidateDrawBase(context, mode, count, primcount))
3185 {
3186 return false;
3187 }
3188
Jamie Madill2b976812014-08-25 15:47:49 -04003189 // Use max index to validate if our vertex buffers are large enough for the pull.
3190 // TODO: offer fast path, with disabled index validation.
3191 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3192 if (elementArrayBuffer)
3193 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003194 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003195 Error error =
3196 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3197 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003198 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003199 {
Jamie Madill437fa652016-05-03 15:13:24 -04003200 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003201 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003202 }
3203 }
3204 else
3205 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003206 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003207 }
3208
Jamie Madille79b1e12015-11-04 16:36:37 -05003209 // If we use an index greater than our maximum supported index range, return an error.
3210 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3211 // return an error if possible here.
3212 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3213 {
Jamie Madill437fa652016-05-03 15:13:24 -04003214 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003215 return false;
3216 }
3217
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003218 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003219 {
3220 return false;
3221 }
3222
Geoff Lang3edfe032015-09-04 16:38:24 -04003223 // No op if there are no real indices in the index data (all are primitive restart).
3224 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003225}
3226
Geoff Langb1196682014-07-23 13:47:29 -04003227bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003228 GLenum mode,
3229 GLsizei count,
3230 GLenum type,
3231 const GLvoid *indices,
3232 GLsizei primcount,
3233 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003234{
3235 if (primcount < 0)
3236 {
Jamie Madill437fa652016-05-03 15:13:24 -04003237 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003238 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003239 }
3240
Jamie Madill2b976812014-08-25 15:47:49 -04003241 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003242 {
3243 return false;
3244 }
3245
3246 // No-op zero primitive count
3247 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003248}
3249
Geoff Lang3edfe032015-09-04 16:38:24 -04003250bool ValidateDrawElementsInstancedANGLE(Context *context,
3251 GLenum mode,
3252 GLsizei count,
3253 GLenum type,
3254 const GLvoid *indices,
3255 GLsizei primcount,
3256 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003257{
3258 if (!ValidateDrawInstancedANGLE(context))
3259 {
3260 return false;
3261 }
3262
3263 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3264}
3265
Geoff Langb1196682014-07-23 13:47:29 -04003266bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003267 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003268{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003269 if (!ValidFramebufferTarget(target))
3270 {
Jamie Madill437fa652016-05-03 15:13:24 -04003271 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003272 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003273 }
3274
3275 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003276 {
3277 return false;
3278 }
3279
Jamie Madill55ec3b12014-07-03 10:38:57 -04003280 if (texture != 0)
3281 {
3282 gl::Texture *tex = context->getTexture(texture);
3283
3284 if (tex == NULL)
3285 {
Jamie Madill437fa652016-05-03 15:13:24 -04003286 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003287 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003288 }
3289
3290 if (level < 0)
3291 {
Jamie Madill437fa652016-05-03 15:13:24 -04003292 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003293 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003294 }
3295 }
3296
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003297 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003298 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003299
Jamie Madill84115c92015-04-23 15:00:07 -04003300 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003301 {
Jamie Madill437fa652016-05-03 15:13:24 -04003302 context->handleError(
3303 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003304 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003305 }
3306
3307 return true;
3308}
3309
Geoff Langb1196682014-07-23 13:47:29 -04003310bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003311 GLenum textarget, GLuint texture, GLint level)
3312{
Geoff Lang95663912015-04-02 15:54:45 -04003313 // 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 +03003314 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3315 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003316 {
Jamie Madill437fa652016-05-03 15:13:24 -04003317 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003318 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003319 }
3320
3321 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003322 {
3323 return false;
3324 }
3325
Jamie Madill55ec3b12014-07-03 10:38:57 -04003326 if (texture != 0)
3327 {
3328 gl::Texture *tex = context->getTexture(texture);
3329 ASSERT(tex);
3330
Jamie Madill2a6564e2014-07-11 09:53:19 -04003331 const gl::Caps &caps = context->getCaps();
3332
Jamie Madill55ec3b12014-07-03 10:38:57 -04003333 switch (textarget)
3334 {
3335 case GL_TEXTURE_2D:
3336 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003337 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003338 {
Jamie Madill437fa652016-05-03 15:13:24 -04003339 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003340 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003341 }
3342 if (tex->getTarget() != GL_TEXTURE_2D)
3343 {
Jamie Madill437fa652016-05-03 15:13:24 -04003344 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003345 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003346 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003347 }
3348 break;
3349
3350 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3351 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3352 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3353 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3354 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3355 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3356 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003357 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003358 {
Jamie Madill437fa652016-05-03 15:13:24 -04003359 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003360 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003361 }
3362 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3363 {
Jamie Madill437fa652016-05-03 15:13:24 -04003364 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003365 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003366 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003367 }
3368 break;
3369
3370 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003371 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003372 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003373 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003374
Jamie Madilla3944d42016-07-22 22:13:26 -04003375 const Format &format = tex->getFormat(textarget, level);
3376 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003377 {
Jamie Madill437fa652016-05-03 15:13:24 -04003378 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003379 return false;
3380 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003381 }
3382
Jamie Madill570f7c82014-07-03 10:38:54 -04003383 return true;
3384}
3385
Geoff Langb1196682014-07-23 13:47:29 -04003386bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003387{
3388 if (program == 0)
3389 {
Jamie Madill437fa652016-05-03 15:13:24 -04003390 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003391 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003392 }
3393
Dian Xiang769769a2015-09-09 15:20:08 -07003394 gl::Program *programObject = GetValidProgram(context, program);
3395 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003396 {
3397 return false;
3398 }
3399
Jamie Madill0063c512014-08-25 15:47:53 -04003400 if (!programObject || !programObject->isLinked())
3401 {
Jamie Madill437fa652016-05-03 15:13:24 -04003402 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003403 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003404 }
3405
Geoff Lang7dd2e102014-11-10 15:19:26 -05003406 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003407 {
Jamie Madill437fa652016-05-03 15:13:24 -04003408 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003409 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003410 }
3411
Jamie Madill0063c512014-08-25 15:47:53 -04003412 return true;
3413}
3414
Geoff Langb1196682014-07-23 13:47:29 -04003415bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003416{
3417 return ValidateGetUniformBase(context, program, location);
3418}
3419
Geoff Langb1196682014-07-23 13:47:29 -04003420bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003421{
Jamie Madill78f41802014-08-25 15:47:55 -04003422 return ValidateGetUniformBase(context, program, location);
3423}
3424
Geoff Langf41d0ee2016-10-07 13:04:23 -04003425static bool ValidateSizedGetUniform(Context *context,
3426 GLuint program,
3427 GLint location,
3428 GLsizei bufSize,
3429 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003430{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003431 if (length)
3432 {
3433 *length = 0;
3434 }
3435
Jamie Madill78f41802014-08-25 15:47:55 -04003436 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003437 {
Jamie Madill78f41802014-08-25 15:47:55 -04003438 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003439 }
3440
Geoff Langf41d0ee2016-10-07 13:04:23 -04003441 if (bufSize < 0)
3442 {
3443 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3444 return false;
3445 }
3446
Jamie Madilla502c742014-08-28 17:19:13 -04003447 gl::Program *programObject = context->getProgram(program);
3448 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003449
Jamie Madill78f41802014-08-25 15:47:55 -04003450 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003451 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3452 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003453 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003454 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003455 context->handleError(
3456 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003457 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003458 }
3459
Geoff Langf41d0ee2016-10-07 13:04:23 -04003460 if (length)
3461 {
3462 // Cast is safe because of comparison to bufSize.
3463 *length = static_cast<GLsizei>(requiredBytes);
3464 }
3465
Jamie Madill0063c512014-08-25 15:47:53 -04003466 return true;
3467}
3468
Geoff Langb1196682014-07-23 13:47:29 -04003469bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003470{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003471 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003472}
3473
Geoff Langb1196682014-07-23 13:47:29 -04003474bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003475{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003476 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3477}
3478
3479bool ValidateGetUniformfvRobustANGLE(Context *context,
3480 GLuint program,
3481 GLint location,
3482 GLsizei bufSize,
3483 GLsizei *length,
3484 GLfloat *params)
3485{
3486 if (!ValidateRobustEntryPoint(context, bufSize))
3487 {
3488 return false;
3489 }
3490
3491 // bufSize is validated in ValidateSizedGetUniform
3492 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3493}
3494
3495bool ValidateGetUniformivRobustANGLE(Context *context,
3496 GLuint program,
3497 GLint location,
3498 GLsizei bufSize,
3499 GLsizei *length,
3500 GLint *params)
3501{
3502 if (!ValidateRobustEntryPoint(context, bufSize))
3503 {
3504 return false;
3505 }
3506
3507 // bufSize is validated in ValidateSizedGetUniform
3508 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3509}
3510
3511bool ValidateGetUniformuivRobustANGLE(Context *context,
3512 GLuint program,
3513 GLint location,
3514 GLsizei bufSize,
3515 GLsizei *length,
3516 GLuint *params)
3517{
3518 if (!ValidateRobustEntryPoint(context, bufSize))
3519 {
3520 return false;
3521 }
3522
3523 if (context->getClientMajorVersion() < 3)
3524 {
3525 context->handleError(
3526 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3527 return false;
3528 }
3529
3530 // bufSize is validated in ValidateSizedGetUniform
3531 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003532}
3533
Austin Kinross08332632015-05-05 13:35:47 -07003534bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3535 const GLenum *attachments, bool defaultFramebuffer)
3536{
3537 if (numAttachments < 0)
3538 {
Jamie Madill437fa652016-05-03 15:13:24 -04003539 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003540 return false;
3541 }
3542
3543 for (GLsizei i = 0; i < numAttachments; ++i)
3544 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003545 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003546 {
3547 if (defaultFramebuffer)
3548 {
Jamie Madill437fa652016-05-03 15:13:24 -04003549 context->handleError(Error(
3550 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003551 return false;
3552 }
3553
3554 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3555 {
Jamie Madill437fa652016-05-03 15:13:24 -04003556 context->handleError(Error(GL_INVALID_OPERATION,
3557 "Requested color attachment is greater than the maximum "
3558 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003559 return false;
3560 }
3561 }
3562 else
3563 {
3564 switch (attachments[i])
3565 {
3566 case GL_DEPTH_ATTACHMENT:
3567 case GL_STENCIL_ATTACHMENT:
3568 case GL_DEPTH_STENCIL_ATTACHMENT:
3569 if (defaultFramebuffer)
3570 {
Jamie Madill437fa652016-05-03 15:13:24 -04003571 context->handleError(
3572 Error(GL_INVALID_ENUM,
3573 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003574 return false;
3575 }
3576 break;
3577 case GL_COLOR:
3578 case GL_DEPTH:
3579 case GL_STENCIL:
3580 if (!defaultFramebuffer)
3581 {
Jamie Madill437fa652016-05-03 15:13:24 -04003582 context->handleError(
3583 Error(GL_INVALID_ENUM,
3584 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003585 return false;
3586 }
3587 break;
3588 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003589 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003590 return false;
3591 }
3592 }
3593 }
3594
3595 return true;
3596}
3597
Austin Kinross6ee1e782015-05-29 17:05:37 -07003598bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3599{
3600 // Note that debug marker calls must not set error state
3601
3602 if (length < 0)
3603 {
3604 return false;
3605 }
3606
3607 if (marker == nullptr)
3608 {
3609 return false;
3610 }
3611
3612 return true;
3613}
3614
3615bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3616{
3617 // Note that debug marker calls must not set error state
3618
3619 if (length < 0)
3620 {
3621 return false;
3622 }
3623
3624 if (length > 0 && marker == nullptr)
3625 {
3626 return false;
3627 }
3628
3629 return true;
3630}
3631
Geoff Langdcab33b2015-07-21 13:03:16 -04003632bool ValidateEGLImageTargetTexture2DOES(Context *context,
3633 egl::Display *display,
3634 GLenum target,
3635 egl::Image *image)
3636{
Geoff Langa8406172015-07-21 16:53:39 -04003637 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3638 {
Jamie Madill437fa652016-05-03 15:13:24 -04003639 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003640 return false;
3641 }
3642
3643 switch (target)
3644 {
3645 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003646 if (!context->getExtensions().eglImage)
3647 {
3648 context->handleError(Error(
3649 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3650 }
3651 break;
3652
3653 case GL_TEXTURE_EXTERNAL_OES:
3654 if (!context->getExtensions().eglImageExternal)
3655 {
3656 context->handleError(Error(
3657 GL_INVALID_ENUM,
3658 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3659 }
Geoff Langa8406172015-07-21 16:53:39 -04003660 break;
3661
3662 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003663 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003664 return false;
3665 }
3666
3667 if (!display->isValidImage(image))
3668 {
Jamie Madill437fa652016-05-03 15:13:24 -04003669 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003670 return false;
3671 }
3672
3673 if (image->getSamples() > 0)
3674 {
Jamie Madill437fa652016-05-03 15:13:24 -04003675 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003676 "cannot create a 2D texture from a multisampled EGL image."));
3677 return false;
3678 }
3679
Jamie Madilla3944d42016-07-22 22:13:26 -04003680 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003681 if (!textureCaps.texturable)
3682 {
Jamie Madill437fa652016-05-03 15:13:24 -04003683 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003684 "EGL image internal format is not supported as a texture."));
3685 return false;
3686 }
3687
Geoff Langdcab33b2015-07-21 13:03:16 -04003688 return true;
3689}
3690
3691bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3692 egl::Display *display,
3693 GLenum target,
3694 egl::Image *image)
3695{
Geoff Langa8406172015-07-21 16:53:39 -04003696 if (!context->getExtensions().eglImage)
3697 {
Jamie Madill437fa652016-05-03 15:13:24 -04003698 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003699 return false;
3700 }
3701
3702 switch (target)
3703 {
3704 case GL_RENDERBUFFER:
3705 break;
3706
3707 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003708 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003709 return false;
3710 }
3711
3712 if (!display->isValidImage(image))
3713 {
Jamie Madill437fa652016-05-03 15:13:24 -04003714 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003715 return false;
3716 }
3717
Jamie Madilla3944d42016-07-22 22:13:26 -04003718 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003719 if (!textureCaps.renderable)
3720 {
Jamie Madill437fa652016-05-03 15:13:24 -04003721 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003722 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3723 return false;
3724 }
3725
Geoff Langdcab33b2015-07-21 13:03:16 -04003726 return true;
3727}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003728
3729bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3730{
Geoff Lang36167ab2015-12-07 10:27:14 -05003731 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003732 {
3733 // The default VAO should always exist
3734 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003735 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003736 return false;
3737 }
3738
3739 return true;
3740}
3741
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003742bool ValidateLinkProgram(Context *context, GLuint program)
3743{
3744 if (context->hasActiveTransformFeedback(program))
3745 {
3746 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003747 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003748 "Cannot link program while program is associated with an active "
3749 "transform feedback object."));
3750 return false;
3751 }
3752 return true;
3753}
3754
Geoff Langc5629752015-12-07 16:29:04 -05003755bool ValidateProgramBinaryBase(Context *context,
3756 GLuint program,
3757 GLenum binaryFormat,
3758 const void *binary,
3759 GLint length)
3760{
3761 Program *programObject = GetValidProgram(context, program);
3762 if (programObject == nullptr)
3763 {
3764 return false;
3765 }
3766
3767 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3768 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3769 programBinaryFormats.end())
3770 {
Jamie Madill437fa652016-05-03 15:13:24 -04003771 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003772 return false;
3773 }
3774
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003775 if (context->hasActiveTransformFeedback(program))
3776 {
3777 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003778 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003779 "Cannot change program binary while program is associated with "
3780 "an active transform feedback object."));
3781 return false;
3782 }
3783
Geoff Langc5629752015-12-07 16:29:04 -05003784 return true;
3785}
3786
3787bool ValidateGetProgramBinaryBase(Context *context,
3788 GLuint program,
3789 GLsizei bufSize,
3790 GLsizei *length,
3791 GLenum *binaryFormat,
3792 void *binary)
3793{
3794 Program *programObject = GetValidProgram(context, program);
3795 if (programObject == nullptr)
3796 {
3797 return false;
3798 }
3799
3800 if (!programObject->isLinked())
3801 {
Jamie Madill437fa652016-05-03 15:13:24 -04003802 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003803 return false;
3804 }
3805
3806 return true;
3807}
Jamie Madillc29968b2016-01-20 11:17:23 -05003808
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003809bool ValidateUseProgram(Context *context, GLuint program)
3810{
3811 if (program != 0)
3812 {
3813 Program *programObject = context->getProgram(program);
3814 if (!programObject)
3815 {
3816 // ES 3.1.0 section 7.3 page 72
3817 if (context->getShader(program))
3818 {
Jamie Madill437fa652016-05-03 15:13:24 -04003819 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003820 Error(GL_INVALID_OPERATION,
3821 "Attempted to use a single shader instead of a shader program."));
3822 return false;
3823 }
3824 else
3825 {
Jamie Madill437fa652016-05-03 15:13:24 -04003826 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003827 return false;
3828 }
3829 }
3830 if (!programObject->isLinked())
3831 {
Jamie Madill437fa652016-05-03 15:13:24 -04003832 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003833 return false;
3834 }
3835 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003836 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003837 {
3838 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003839 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003840 Error(GL_INVALID_OPERATION,
3841 "Cannot change active program while transform feedback is unpaused."));
3842 return false;
3843 }
3844
3845 return true;
3846}
3847
Jamie Madillc29968b2016-01-20 11:17:23 -05003848bool ValidateCopyTexImage2D(ValidationContext *context,
3849 GLenum target,
3850 GLint level,
3851 GLenum internalformat,
3852 GLint x,
3853 GLint y,
3854 GLsizei width,
3855 GLsizei height,
3856 GLint border)
3857{
Martin Radev1be913c2016-07-11 17:59:16 +03003858 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003859 {
3860 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3861 0, x, y, width, height, border);
3862 }
3863
Martin Radev1be913c2016-07-11 17:59:16 +03003864 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003865 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3866 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003867}
Jamie Madillc29968b2016-01-20 11:17:23 -05003868
3869bool ValidateFramebufferRenderbuffer(Context *context,
3870 GLenum target,
3871 GLenum attachment,
3872 GLenum renderbuffertarget,
3873 GLuint renderbuffer)
3874{
3875 if (!ValidFramebufferTarget(target) ||
3876 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3877 {
Jamie Madill437fa652016-05-03 15:13:24 -04003878 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003879 return false;
3880 }
3881
3882 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3883 renderbuffertarget, renderbuffer);
3884}
3885
3886bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3887{
3888 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3889 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3890 {
Jamie Madill437fa652016-05-03 15:13:24 -04003891 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003892 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3893 return false;
3894 }
3895
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003896 ASSERT(context->getGLState().getDrawFramebuffer());
3897 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003898 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3899
3900 // This should come first before the check for the default frame buffer
3901 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3902 // rather than INVALID_OPERATION
3903 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3904 {
3905 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3906
3907 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003908 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3909 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003910 {
3911 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003912 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3913 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3914 // 3.1 is still a bit ambiguous about the error, but future specs are
3915 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003916 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003917 return false;
3918 }
3919 else if (bufs[colorAttachment] >= maxColorAttachment)
3920 {
Jamie Madill437fa652016-05-03 15:13:24 -04003921 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003922 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003923 return false;
3924 }
3925 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3926 frameBufferId != 0)
3927 {
3928 // INVALID_OPERATION-GL is bound to buffer and ith argument
3929 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003930 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003931 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3932 return false;
3933 }
3934 }
3935
3936 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3937 // and n is not 1 or bufs is bound to value other than BACK and NONE
3938 if (frameBufferId == 0)
3939 {
3940 if (n != 1)
3941 {
Jamie Madill437fa652016-05-03 15:13:24 -04003942 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003943 "n must be 1 when GL is bound to the default framebuffer"));
3944 return false;
3945 }
3946
3947 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3948 {
Jamie Madill437fa652016-05-03 15:13:24 -04003949 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003950 GL_INVALID_OPERATION,
3951 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3952 return false;
3953 }
3954 }
3955
3956 return true;
3957}
3958
3959bool ValidateCopyTexSubImage2D(Context *context,
3960 GLenum target,
3961 GLint level,
3962 GLint xoffset,
3963 GLint yoffset,
3964 GLint x,
3965 GLint y,
3966 GLsizei width,
3967 GLsizei height)
3968{
Martin Radev1be913c2016-07-11 17:59:16 +03003969 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003970 {
3971 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3972 yoffset, x, y, width, height, 0);
3973 }
3974
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003975 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3976 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003977}
3978
Geoff Lang496c02d2016-10-20 11:38:11 -07003979bool ValidateGetBufferPointervBase(Context *context,
3980 GLenum target,
3981 GLenum pname,
3982 GLsizei *length,
3983 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003984{
Geoff Lang496c02d2016-10-20 11:38:11 -07003985 if (length)
3986 {
3987 *length = 0;
3988 }
3989
3990 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3991 {
3992 context->handleError(
3993 Error(GL_INVALID_OPERATION,
3994 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
3995 return false;
3996 }
3997
Olli Etuaho4f667482016-03-30 15:56:35 +03003998 if (!ValidBufferTarget(context, target))
3999 {
Jamie Madill437fa652016-05-03 15:13:24 -04004000 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004001 return false;
4002 }
4003
Geoff Lang496c02d2016-10-20 11:38:11 -07004004 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004005 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004006 case GL_BUFFER_MAP_POINTER:
4007 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004008
Geoff Lang496c02d2016-10-20 11:38:11 -07004009 default:
4010 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4011 return false;
4012 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004013
4014 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4015 // target bound to zero generate an INVALID_OPERATION error."
4016 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004017 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004018 {
Jamie Madill437fa652016-05-03 15:13:24 -04004019 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004020 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4021 return false;
4022 }
4023
Geoff Lang496c02d2016-10-20 11:38:11 -07004024 if (length)
4025 {
4026 *length = 1;
4027 }
4028
Olli Etuaho4f667482016-03-30 15:56:35 +03004029 return true;
4030}
4031
4032bool ValidateUnmapBufferBase(Context *context, GLenum target)
4033{
4034 if (!ValidBufferTarget(context, target))
4035 {
Jamie Madill437fa652016-05-03 15:13:24 -04004036 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004037 return false;
4038 }
4039
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004040 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004041
4042 if (buffer == nullptr || !buffer->isMapped())
4043 {
Jamie Madill437fa652016-05-03 15:13:24 -04004044 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004045 return false;
4046 }
4047
4048 return true;
4049}
4050
4051bool ValidateMapBufferRangeBase(Context *context,
4052 GLenum target,
4053 GLintptr offset,
4054 GLsizeiptr length,
4055 GLbitfield access)
4056{
4057 if (!ValidBufferTarget(context, target))
4058 {
Jamie Madill437fa652016-05-03 15:13:24 -04004059 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004060 return false;
4061 }
4062
4063 if (offset < 0 || length < 0)
4064 {
Jamie Madill437fa652016-05-03 15:13:24 -04004065 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004066 return false;
4067 }
4068
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004069 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004070
4071 if (!buffer)
4072 {
Jamie Madill437fa652016-05-03 15:13:24 -04004073 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004074 return false;
4075 }
4076
4077 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004078 CheckedNumeric<size_t> checkedOffset(offset);
4079 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004080
Jamie Madille2e406c2016-06-02 13:04:10 -04004081 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004082 {
Jamie Madill437fa652016-05-03 15:13:24 -04004083 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004084 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4085 return false;
4086 }
4087
4088 // Check for invalid bits in the mask
4089 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4090 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4091 GL_MAP_UNSYNCHRONIZED_BIT;
4092
4093 if (access & ~(allAccessBits))
4094 {
Jamie Madill437fa652016-05-03 15:13:24 -04004095 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004096 return false;
4097 }
4098
4099 if (length == 0)
4100 {
Jamie Madill437fa652016-05-03 15:13:24 -04004101 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004102 return false;
4103 }
4104
4105 if (buffer->isMapped())
4106 {
Jamie Madill437fa652016-05-03 15:13:24 -04004107 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004108 return false;
4109 }
4110
4111 // Check for invalid bit combinations
4112 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4113 {
Jamie Madill437fa652016-05-03 15:13:24 -04004114 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004115 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4116 return false;
4117 }
4118
4119 GLbitfield writeOnlyBits =
4120 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4121
4122 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4123 {
Jamie Madill437fa652016-05-03 15:13:24 -04004124 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004125 "Invalid access bits when mapping buffer for reading: 0x%X.",
4126 access));
4127 return false;
4128 }
4129
4130 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4131 {
Jamie Madill437fa652016-05-03 15:13:24 -04004132 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004133 GL_INVALID_OPERATION,
4134 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4135 return false;
4136 }
4137 return true;
4138}
4139
4140bool ValidateFlushMappedBufferRangeBase(Context *context,
4141 GLenum target,
4142 GLintptr offset,
4143 GLsizeiptr length)
4144{
4145 if (offset < 0 || length < 0)
4146 {
Jamie Madill437fa652016-05-03 15:13:24 -04004147 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004148 return false;
4149 }
4150
4151 if (!ValidBufferTarget(context, target))
4152 {
Jamie Madill437fa652016-05-03 15:13:24 -04004153 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004154 return false;
4155 }
4156
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004157 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004158
4159 if (buffer == nullptr)
4160 {
Jamie Madill437fa652016-05-03 15:13:24 -04004161 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004162 return false;
4163 }
4164
4165 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4166 {
Jamie Madill437fa652016-05-03 15:13:24 -04004167 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004168 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4169 return false;
4170 }
4171
4172 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004173 CheckedNumeric<size_t> checkedOffset(offset);
4174 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004175
Jamie Madille2e406c2016-06-02 13:04:10 -04004176 if (!checkedSize.IsValid() ||
4177 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004178 {
Jamie Madill437fa652016-05-03 15:13:24 -04004179 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004180 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4181 return false;
4182 }
4183
4184 return true;
4185}
4186
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004187bool ValidateGenerateMipmap(Context *context, GLenum target)
4188{
4189 if (!ValidTextureTarget(context, target))
4190 {
4191 context->handleError(Error(GL_INVALID_ENUM));
4192 return false;
4193 }
4194
4195 Texture *texture = context->getTargetTexture(target);
4196
4197 if (texture == nullptr)
4198 {
4199 context->handleError(Error(GL_INVALID_OPERATION));
4200 return false;
4201 }
4202
4203 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4204
4205 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4206 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4207 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4208 {
4209 context->handleError(Error(GL_INVALID_OPERATION));
4210 return false;
4211 }
4212
Jamie Madilla3944d42016-07-22 22:13:26 -04004213 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4214 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4215 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004216
4217 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4218 // unsized formats or that are color renderable and filterable. Since we do not track if
4219 // the texture was created with sized or unsized format (only sized formats are stored),
4220 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4221 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4222 // textures since they're the only texture format that can be created with unsized formats
4223 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4224 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004225 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4226 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004227 {
4228 context->handleError(Error(GL_INVALID_OPERATION));
4229 return false;
4230 }
4231
4232 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004233 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004234 {
4235 context->handleError(Error(GL_INVALID_OPERATION));
4236 return false;
4237 }
4238
4239 // Non-power of 2 ES2 check
4240 if (!context->getExtensions().textureNPOT &&
4241 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4242 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4243 {
Martin Radev1be913c2016-07-11 17:59:16 +03004244 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004245 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
4246 context->handleError(Error(GL_INVALID_OPERATION));
4247 return false;
4248 }
4249
4250 // Cube completeness check
4251 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4252 {
4253 context->handleError(Error(GL_INVALID_OPERATION));
4254 return false;
4255 }
4256
4257 return true;
4258}
4259
Olli Etuaho41997e72016-03-10 13:38:39 +02004260bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4261{
4262 return ValidateGenOrDelete(context, n);
4263}
4264
4265bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4266{
4267 return ValidateGenOrDelete(context, n);
4268}
4269
4270bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4271{
4272 return ValidateGenOrDelete(context, n);
4273}
4274
4275bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4276{
4277 return ValidateGenOrDelete(context, n);
4278}
4279
4280bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4281{
4282 return ValidateGenOrDelete(context, n);
4283}
4284
4285bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4286{
4287 return ValidateGenOrDelete(context, n);
4288}
4289
4290bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4291{
4292 return ValidateGenOrDelete(context, n);
4293}
4294
4295bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4296{
4297 return ValidateGenOrDelete(context, n);
4298}
4299
4300bool ValidateGenOrDelete(Context *context, GLint n)
4301{
4302 if (n < 0)
4303 {
Jamie Madill437fa652016-05-03 15:13:24 -04004304 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004305 return false;
4306 }
4307 return true;
4308}
4309
Geoff Langf41a7152016-09-19 15:11:17 -04004310bool ValidateEnable(Context *context, GLenum cap)
4311{
4312 if (!ValidCap(context, cap, false))
4313 {
4314 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4315 return false;
4316 }
4317
4318 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4319 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4320 {
4321 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4322 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4323
4324 // We also output an error message to the debugger window if tracing is active, so that
4325 // developers can see the error message.
4326 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004327 return false;
4328 }
4329
4330 return true;
4331}
4332
4333bool ValidateDisable(Context *context, GLenum cap)
4334{
4335 if (!ValidCap(context, cap, false))
4336 {
4337 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4338 return false;
4339 }
4340
4341 return true;
4342}
4343
4344bool ValidateIsEnabled(Context *context, GLenum cap)
4345{
4346 if (!ValidCap(context, cap, true))
4347 {
4348 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4349 return false;
4350 }
4351
4352 return true;
4353}
4354
Geoff Langff5b2d52016-09-07 11:32:23 -04004355bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4356{
4357 if (!context->getExtensions().robustClientMemory)
4358 {
4359 context->handleError(
4360 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4361 return false;
4362 }
4363
4364 if (bufSize < 0)
4365 {
4366 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4367 return false;
4368 }
4369
4370 return true;
4371}
4372
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004373bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4374{
4375 if (bufSize < numParams)
4376 {
4377 context->handleError(Error(GL_INVALID_OPERATION,
4378 "%u parameters are required but %i were provided.", numParams,
4379 bufSize));
4380 return false;
4381 }
4382
4383 return true;
4384}
4385
Geoff Langff5b2d52016-09-07 11:32:23 -04004386bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4387 GLenum target,
4388 GLenum attachment,
4389 GLenum pname,
4390 GLsizei *numParams)
4391{
4392 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4393 *numParams = 1;
4394
4395 if (!ValidFramebufferTarget(target))
4396 {
4397 context->handleError(Error(GL_INVALID_ENUM));
4398 return false;
4399 }
4400
4401 int clientVersion = context->getClientMajorVersion();
4402
4403 switch (pname)
4404 {
4405 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4406 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4407 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4408 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4409 break;
4410
4411 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4412 if (clientVersion < 3 && !context->getExtensions().sRGB)
4413 {
4414 context->handleError(Error(GL_INVALID_ENUM));
4415 return false;
4416 }
4417 break;
4418
4419 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4420 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4421 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4422 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4423 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4424 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4425 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4426 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4427 if (clientVersion < 3)
4428 {
4429 context->handleError(Error(GL_INVALID_ENUM));
4430 return false;
4431 }
4432 break;
4433
4434 default:
4435 context->handleError(Error(GL_INVALID_ENUM));
4436 return false;
4437 }
4438
4439 // Determine if the attachment is a valid enum
4440 switch (attachment)
4441 {
4442 case GL_BACK:
4443 case GL_FRONT:
4444 case GL_DEPTH:
4445 case GL_STENCIL:
4446 case GL_DEPTH_STENCIL_ATTACHMENT:
4447 if (clientVersion < 3)
4448 {
4449 context->handleError(Error(GL_INVALID_ENUM));
4450 return false;
4451 }
4452 break;
4453
4454 case GL_DEPTH_ATTACHMENT:
4455 case GL_STENCIL_ATTACHMENT:
4456 break;
4457
4458 default:
4459 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4460 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4461 {
4462 context->handleError(Error(GL_INVALID_ENUM));
4463 return false;
4464 }
4465 break;
4466 }
4467
4468 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4469 ASSERT(framebuffer);
4470
4471 if (framebuffer->id() == 0)
4472 {
4473 if (clientVersion < 3)
4474 {
4475 context->handleError(Error(GL_INVALID_OPERATION));
4476 return false;
4477 }
4478
4479 switch (attachment)
4480 {
4481 case GL_BACK:
4482 case GL_DEPTH:
4483 case GL_STENCIL:
4484 break;
4485
4486 default:
4487 context->handleError(Error(GL_INVALID_OPERATION));
4488 return false;
4489 }
4490 }
4491 else
4492 {
4493 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4494 {
4495 // Valid attachment query
4496 }
4497 else
4498 {
4499 switch (attachment)
4500 {
4501 case GL_DEPTH_ATTACHMENT:
4502 case GL_STENCIL_ATTACHMENT:
4503 break;
4504
4505 case GL_DEPTH_STENCIL_ATTACHMENT:
4506 if (!framebuffer->hasValidDepthStencil())
4507 {
4508 context->handleError(Error(GL_INVALID_OPERATION));
4509 return false;
4510 }
4511 break;
4512
4513 default:
4514 context->handleError(Error(GL_INVALID_OPERATION));
4515 return false;
4516 }
4517 }
4518 }
4519
4520 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4521 if (attachmentObject)
4522 {
4523 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4524 attachmentObject->type() == GL_TEXTURE ||
4525 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4526
4527 switch (pname)
4528 {
4529 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4530 if (attachmentObject->type() != GL_RENDERBUFFER &&
4531 attachmentObject->type() != GL_TEXTURE)
4532 {
4533 context->handleError(Error(GL_INVALID_ENUM));
4534 return false;
4535 }
4536 break;
4537
4538 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4539 if (attachmentObject->type() != GL_TEXTURE)
4540 {
4541 context->handleError(Error(GL_INVALID_ENUM));
4542 return false;
4543 }
4544 break;
4545
4546 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4547 if (attachmentObject->type() != GL_TEXTURE)
4548 {
4549 context->handleError(Error(GL_INVALID_ENUM));
4550 return false;
4551 }
4552 break;
4553
4554 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4555 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4556 {
4557 context->handleError(Error(GL_INVALID_OPERATION));
4558 return false;
4559 }
4560 break;
4561
4562 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4563 if (attachmentObject->type() != GL_TEXTURE)
4564 {
4565 context->handleError(Error(GL_INVALID_ENUM));
4566 return false;
4567 }
4568 break;
4569
4570 default:
4571 break;
4572 }
4573 }
4574 else
4575 {
4576 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4577 // is NONE, then querying any other pname will generate INVALID_ENUM.
4578
4579 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4580 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4581 // INVALID_OPERATION for all other pnames
4582
4583 switch (pname)
4584 {
4585 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4586 break;
4587
4588 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4589 if (clientVersion < 3)
4590 {
4591 context->handleError(Error(GL_INVALID_ENUM));
4592 return false;
4593 }
4594 break;
4595
4596 default:
4597 if (clientVersion < 3)
4598 {
4599 context->handleError(Error(GL_INVALID_ENUM));
4600 return false;
4601 }
4602 else
4603 {
4604 context->handleError(Error(GL_INVALID_OPERATION));
4605 return false;
4606 }
4607 }
4608 }
4609
4610 return true;
4611}
4612
4613bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4614 GLenum target,
4615 GLenum attachment,
4616 GLenum pname,
4617 GLsizei bufSize,
4618 GLsizei *numParams)
4619{
4620 if (!ValidateRobustEntryPoint(context, bufSize))
4621 {
4622 return false;
4623 }
4624
4625 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4626 {
4627 return false;
4628 }
4629
4630 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4631 {
4632 return false;
4633 }
4634
4635 return true;
4636}
4637
4638bool ValidateGetBufferParameteriv(ValidationContext *context,
4639 GLenum target,
4640 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004641 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004642{
Geoff Langebebe1c2016-10-14 12:01:31 -04004643 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004644}
4645
4646bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4647 GLenum target,
4648 GLenum pname,
4649 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004650 GLsizei *length,
4651 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004652{
4653 if (!ValidateRobustEntryPoint(context, bufSize))
4654 {
4655 return false;
4656 }
4657
Geoff Langebebe1c2016-10-14 12:01:31 -04004658 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004659 {
4660 return false;
4661 }
4662
Geoff Langebebe1c2016-10-14 12:01:31 -04004663 if (!ValidateRobustBufferSize(context, bufSize, *length))
4664 {
4665 return false;
4666 }
4667
4668 return true;
4669}
4670
4671bool ValidateGetBufferParameteri64v(ValidationContext *context,
4672 GLenum target,
4673 GLenum pname,
4674 GLint64 *params)
4675{
4676 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4677}
4678
4679bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4680 GLenum target,
4681 GLenum pname,
4682 GLsizei bufSize,
4683 GLsizei *length,
4684 GLint64 *params)
4685{
4686 if (!ValidateRobustEntryPoint(context, bufSize))
4687 {
4688 return false;
4689 }
4690
4691 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4692 {
4693 return false;
4694 }
4695
4696 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004697 {
4698 return false;
4699 }
4700
4701 return true;
4702}
4703
4704bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4705{
4706 // Currently, all GetProgramiv queries return 1 parameter
4707 *numParams = 1;
4708
4709 Program *programObject = GetValidProgram(context, program);
4710 if (!programObject)
4711 {
4712 return false;
4713 }
4714
4715 switch (pname)
4716 {
4717 case GL_DELETE_STATUS:
4718 case GL_LINK_STATUS:
4719 case GL_VALIDATE_STATUS:
4720 case GL_INFO_LOG_LENGTH:
4721 case GL_ATTACHED_SHADERS:
4722 case GL_ACTIVE_ATTRIBUTES:
4723 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4724 case GL_ACTIVE_UNIFORMS:
4725 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4726 break;
4727
4728 case GL_PROGRAM_BINARY_LENGTH:
4729 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4730 {
4731 context->handleError(Error(GL_INVALID_ENUM,
4732 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4733 "GL_OES_get_program_binary or ES 3.0."));
4734 return false;
4735 }
4736 break;
4737
4738 case GL_ACTIVE_UNIFORM_BLOCKS:
4739 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4740 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4741 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4742 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4743 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4744 if (context->getClientMajorVersion() < 3)
4745 {
4746 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4747 return false;
4748 }
4749 break;
4750
4751 default:
4752 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4753 return false;
4754 }
4755
4756 return true;
4757}
4758
4759bool ValidateGetProgramivRobustANGLE(Context *context,
4760 GLuint program,
4761 GLenum pname,
4762 GLsizei bufSize,
4763 GLsizei *numParams)
4764{
4765 if (!ValidateRobustEntryPoint(context, bufSize))
4766 {
4767 return false;
4768 }
4769
4770 if (!ValidateGetProgramiv(context, program, pname, numParams))
4771 {
4772 return false;
4773 }
4774
4775 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4776 {
4777 return false;
4778 }
4779
4780 return true;
4781}
4782
Geoff Lang740d9022016-10-07 11:20:52 -04004783bool ValidateGetRenderbufferParameteriv(Context *context,
4784 GLenum target,
4785 GLenum pname,
4786 GLint *params)
4787{
4788 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4789}
4790
4791bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4792 GLenum target,
4793 GLenum pname,
4794 GLsizei bufSize,
4795 GLsizei *length,
4796 GLint *params)
4797{
4798 if (!ValidateRobustEntryPoint(context, bufSize))
4799 {
4800 return false;
4801 }
4802
4803 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4804 {
4805 return false;
4806 }
4807
4808 if (!ValidateRobustBufferSize(context, bufSize, *length))
4809 {
4810 return false;
4811 }
4812
4813 return true;
4814}
4815
Geoff Langd7d0ed32016-10-07 11:33:51 -04004816bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4817{
4818 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4819}
4820
4821bool ValidateGetShaderivRobustANGLE(Context *context,
4822 GLuint shader,
4823 GLenum pname,
4824 GLsizei bufSize,
4825 GLsizei *length,
4826 GLint *params)
4827{
4828 if (!ValidateRobustEntryPoint(context, bufSize))
4829 {
4830 return false;
4831 }
4832
4833 if (!ValidateGetShaderivBase(context, shader, pname, length))
4834 {
4835 return false;
4836 }
4837
4838 if (!ValidateRobustBufferSize(context, bufSize, *length))
4839 {
4840 return false;
4841 }
4842
4843 return true;
4844}
4845
Geoff Langc1984ed2016-10-07 12:41:00 -04004846bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4847{
4848 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4849}
4850
4851bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4852 GLenum target,
4853 GLenum pname,
4854 GLsizei bufSize,
4855 GLsizei *length,
4856 GLfloat *params)
4857{
4858 if (!ValidateRobustEntryPoint(context, bufSize))
4859 {
4860 return false;
4861 }
4862
4863 if (!ValidateGetTexParameterBase(context, target, pname, length))
4864 {
4865 return false;
4866 }
4867
4868 if (!ValidateRobustBufferSize(context, bufSize, *length))
4869 {
4870 return false;
4871 }
4872
4873 return true;
4874}
4875
4876bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4877{
4878 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4879}
4880
4881bool ValidateGetTexParameterivRobustANGLE(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 (!ValidateGetTexParameterBase(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
4906bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4907{
4908 return ValidateTexParameterBase(context, target, pname, -1, &param);
4909}
4910
4911bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4912{
4913 return ValidateTexParameterBase(context, target, pname, -1, params);
4914}
4915
4916bool ValidateTexParameterfvRobustANGLE(Context *context,
4917 GLenum target,
4918 GLenum pname,
4919 GLsizei bufSize,
4920 const GLfloat *params)
4921{
4922 if (!ValidateRobustEntryPoint(context, bufSize))
4923 {
4924 return false;
4925 }
4926
4927 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4928}
4929
4930bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4931{
4932 return ValidateTexParameterBase(context, target, pname, -1, &param);
4933}
4934
4935bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4936{
4937 return ValidateTexParameterBase(context, target, pname, -1, params);
4938}
4939
4940bool ValidateTexParameterivRobustANGLE(Context *context,
4941 GLenum target,
4942 GLenum pname,
4943 GLsizei bufSize,
4944 const GLint *params)
4945{
4946 if (!ValidateRobustEntryPoint(context, bufSize))
4947 {
4948 return false;
4949 }
4950
4951 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4952}
4953
4954bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4955{
4956 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4957}
4958
4959bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4960 GLuint sampler,
4961 GLenum pname,
4962 GLuint bufSize,
4963 GLsizei *length,
4964 GLfloat *params)
4965{
4966 if (!ValidateRobustEntryPoint(context, bufSize))
4967 {
4968 return false;
4969 }
4970
4971 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4972 {
4973 return false;
4974 }
4975
4976 if (!ValidateRobustBufferSize(context, bufSize, *length))
4977 {
4978 return false;
4979 }
4980
4981 return true;
4982}
4983
4984bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4985{
4986 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4987}
4988
4989bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4990 GLuint sampler,
4991 GLenum pname,
4992 GLuint bufSize,
4993 GLsizei *length,
4994 GLint *params)
4995{
4996 if (!ValidateRobustEntryPoint(context, bufSize))
4997 {
4998 return false;
4999 }
5000
5001 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5002 {
5003 return false;
5004 }
5005
5006 if (!ValidateRobustBufferSize(context, bufSize, *length))
5007 {
5008 return false;
5009 }
5010
5011 return true;
5012}
5013
5014bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5015{
5016 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5017}
5018
5019bool ValidateSamplerParameterfv(Context *context,
5020 GLuint sampler,
5021 GLenum pname,
5022 const GLfloat *params)
5023{
5024 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5025}
5026
5027bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5028 GLuint sampler,
5029 GLenum pname,
5030 GLsizei bufSize,
5031 const GLfloat *params)
5032{
5033 if (!ValidateRobustEntryPoint(context, bufSize))
5034 {
5035 return false;
5036 }
5037
5038 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5039}
5040
5041bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5042{
5043 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5044}
5045
5046bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5047{
5048 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5049}
5050
5051bool ValidateSamplerParameterivRobustANGLE(Context *context,
5052 GLuint sampler,
5053 GLenum pname,
5054 GLsizei bufSize,
5055 const GLint *params)
5056{
5057 if (!ValidateRobustEntryPoint(context, bufSize))
5058 {
5059 return false;
5060 }
5061
5062 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5063}
5064
Geoff Lang0b031062016-10-13 14:30:04 -04005065bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5066{
5067 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5068}
5069
5070bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5071 GLuint index,
5072 GLenum pname,
5073 GLsizei bufSize,
5074 GLsizei *length,
5075 GLfloat *params)
5076{
5077 if (!ValidateRobustEntryPoint(context, bufSize))
5078 {
5079 return false;
5080 }
5081
5082 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5083 {
5084 return false;
5085 }
5086
5087 if (!ValidateRobustBufferSize(context, bufSize, *length))
5088 {
5089 return false;
5090 }
5091
5092 return true;
5093}
5094
5095bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5096{
5097 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5098}
5099
5100bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5101 GLuint index,
5102 GLenum pname,
5103 GLsizei bufSize,
5104 GLsizei *length,
5105 GLint *params)
5106{
5107 if (!ValidateRobustEntryPoint(context, bufSize))
5108 {
5109 return false;
5110 }
5111
5112 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5113 {
5114 return false;
5115 }
5116
5117 if (!ValidateRobustBufferSize(context, bufSize, *length))
5118 {
5119 return false;
5120 }
5121
5122 return true;
5123}
5124
5125bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5126{
5127 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5128}
5129
5130bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5131 GLuint index,
5132 GLenum pname,
5133 GLsizei bufSize,
5134 GLsizei *length,
5135 void **pointer)
5136{
5137 if (!ValidateRobustEntryPoint(context, bufSize))
5138 {
5139 return false;
5140 }
5141
5142 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5143 {
5144 return false;
5145 }
5146
5147 if (!ValidateRobustBufferSize(context, bufSize, *length))
5148 {
5149 return false;
5150 }
5151
5152 return true;
5153}
5154
5155bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5156{
5157 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5158}
5159
5160bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5161 GLuint index,
5162 GLenum pname,
5163 GLsizei bufSize,
5164 GLsizei *length,
5165 GLint *params)
5166{
5167 if (!ValidateRobustEntryPoint(context, bufSize))
5168 {
5169 return false;
5170 }
5171
5172 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5173 {
5174 return false;
5175 }
5176
5177 if (!ValidateRobustBufferSize(context, bufSize, *length))
5178 {
5179 return false;
5180 }
5181
5182 return true;
5183}
5184
5185bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5186{
5187 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5188}
5189
5190bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5191 GLuint index,
5192 GLenum pname,
5193 GLsizei bufSize,
5194 GLsizei *length,
5195 GLuint *params)
5196{
5197 if (!ValidateRobustEntryPoint(context, bufSize))
5198 {
5199 return false;
5200 }
5201
5202 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5203 {
5204 return false;
5205 }
5206
5207 if (!ValidateRobustBufferSize(context, bufSize, *length))
5208 {
5209 return false;
5210 }
5211
5212 return true;
5213}
5214
Geoff Lang6899b872016-10-14 11:30:13 -04005215bool ValidateGetActiveUniformBlockiv(Context *context,
5216 GLuint program,
5217 GLuint uniformBlockIndex,
5218 GLenum pname,
5219 GLint *params)
5220{
5221 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5222}
5223
5224bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5225 GLuint program,
5226 GLuint uniformBlockIndex,
5227 GLenum pname,
5228 GLsizei bufSize,
5229 GLsizei *length,
5230 GLint *params)
5231{
5232 if (!ValidateRobustEntryPoint(context, bufSize))
5233 {
5234 return false;
5235 }
5236
5237 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5238 {
5239 return false;
5240 }
5241
5242 if (!ValidateRobustBufferSize(context, bufSize, *length))
5243 {
5244 return false;
5245 }
5246
5247 return true;
5248}
5249
Geoff Lang0a9661f2016-10-20 10:59:20 -07005250bool ValidateGetInternalFormativ(Context *context,
5251 GLenum target,
5252 GLenum internalformat,
5253 GLenum pname,
5254 GLsizei bufSize,
5255 GLint *params)
5256{
5257 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5258 nullptr);
5259}
5260
5261bool ValidateGetInternalFormativRobustANGLE(Context *context,
5262 GLenum target,
5263 GLenum internalformat,
5264 GLenum pname,
5265 GLsizei bufSize,
5266 GLsizei *length,
5267 GLint *params)
5268{
5269 if (!ValidateRobustEntryPoint(context, bufSize))
5270 {
5271 return false;
5272 }
5273
5274 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5275 {
5276 return false;
5277 }
5278
5279 if (!ValidateRobustBufferSize(context, bufSize, *length))
5280 {
5281 return false;
5282 }
5283
5284 return true;
5285}
5286
Jamie Madillc29968b2016-01-20 11:17:23 -05005287} // namespace gl