blob: a7b9f9a1d4de454717d3afb2a0e53e0ef6a29bff [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
474 default:
475 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
476 return false;
477 }
478
479 if (length)
480 {
481 *length = 1;
482 }
483 return true;
484}
485
486template <typename ParamType>
487bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
488{
489 switch (ConvertToGLenum(params[0]))
490 {
491 case GL_CLAMP_TO_EDGE:
492 break;
493
494 case GL_REPEAT:
495 case GL_MIRRORED_REPEAT:
496 if (isExternalTextureTarget)
497 {
498 // OES_EGL_image_external specifies this error.
499 context->handleError(Error(
500 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
501 return false;
502 }
503 break;
504
505 default:
506 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
507 return false;
508 }
509
510 return true;
511}
512
513template <typename ParamType>
514bool ValidateTextureMinFilterValue(Context *context,
515 ParamType *params,
516 bool isExternalTextureTarget)
517{
518 switch (ConvertToGLenum(params[0]))
519 {
520 case GL_NEAREST:
521 case GL_LINEAR:
522 break;
523
524 case GL_NEAREST_MIPMAP_NEAREST:
525 case GL_LINEAR_MIPMAP_NEAREST:
526 case GL_NEAREST_MIPMAP_LINEAR:
527 case GL_LINEAR_MIPMAP_LINEAR:
528 if (isExternalTextureTarget)
529 {
530 // OES_EGL_image_external specifies this error.
531 context->handleError(
532 Error(GL_INVALID_ENUM,
533 "external textures only support NEAREST and LINEAR filtering"));
534 return false;
535 }
536 break;
537
538 default:
539 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
540 return false;
541 }
542
543 return true;
544}
545
546template <typename ParamType>
547bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
548{
549 switch (ConvertToGLenum(params[0]))
550 {
551 case GL_NEAREST:
552 case GL_LINEAR:
553 break;
554
555 default:
556 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
557 return false;
558 }
559
560 return true;
561}
562
563template <typename ParamType>
564bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
565{
566 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
567 switch (ConvertToGLenum(params[0]))
568 {
569 case GL_NONE:
570 case GL_COMPARE_REF_TO_TEXTURE:
571 break;
572
573 default:
574 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
575 return false;
576 }
577
578 return true;
579}
580
581template <typename ParamType>
582bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
583{
584 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
585 switch (ConvertToGLenum(params[0]))
586 {
587 case GL_LEQUAL:
588 case GL_GEQUAL:
589 case GL_LESS:
590 case GL_GREATER:
591 case GL_EQUAL:
592 case GL_NOTEQUAL:
593 case GL_ALWAYS:
594 case GL_NEVER:
595 break;
596
597 default:
598 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
599 return false;
600 }
601
602 return true;
603}
604
605template <typename ParamType>
606bool ValidateTexParameterBase(Context *context,
607 GLenum target,
608 GLenum pname,
609 GLsizei bufSize,
610 ParamType *params)
611{
612 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
613 {
614 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
615 return false;
616 }
617
618 if (context->getTargetTexture(target) == nullptr)
619 {
620 // Should only be possible for external textures
621 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
622 return false;
623 }
624
625 const GLsizei minBufSize = 1;
626 if (bufSize >= 0 && bufSize < minBufSize)
627 {
628 context->handleError(
629 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
630 return false;
631 }
632
633 switch (pname)
634 {
635 case GL_TEXTURE_WRAP_R:
636 case GL_TEXTURE_SWIZZLE_R:
637 case GL_TEXTURE_SWIZZLE_G:
638 case GL_TEXTURE_SWIZZLE_B:
639 case GL_TEXTURE_SWIZZLE_A:
640 case GL_TEXTURE_BASE_LEVEL:
641 case GL_TEXTURE_MAX_LEVEL:
642 case GL_TEXTURE_COMPARE_MODE:
643 case GL_TEXTURE_COMPARE_FUNC:
644 case GL_TEXTURE_MIN_LOD:
645 case GL_TEXTURE_MAX_LOD:
646 if (context->getClientMajorVersion() < 3)
647 {
648 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
649 return false;
650 }
651 if (target == GL_TEXTURE_EXTERNAL_OES &&
652 !context->getExtensions().eglImageExternalEssl3)
653 {
654 context->handleError(Error(GL_INVALID_ENUM,
655 "ES3 texture parameters are not available without "
656 "GL_OES_EGL_image_external_essl3."));
657 return false;
658 }
659 break;
660
661 default:
662 break;
663 }
664
665 switch (pname)
666 {
667 case GL_TEXTURE_WRAP_S:
668 case GL_TEXTURE_WRAP_T:
669 case GL_TEXTURE_WRAP_R:
670 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
671 {
672 return false;
673 }
674 break;
675
676 case GL_TEXTURE_MIN_FILTER:
677 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
678 {
679 return false;
680 }
681 break;
682
683 case GL_TEXTURE_MAG_FILTER:
684 if (!ValidateTextureMagFilterValue(context, params))
685 {
686 return false;
687 }
688 break;
689
690 case GL_TEXTURE_USAGE_ANGLE:
691 switch (ConvertToGLenum(params[0]))
692 {
693 case GL_NONE:
694 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
695 break;
696
697 default:
698 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
699 return false;
700 }
701 break;
702
703 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
704 if (!context->getExtensions().textureFilterAnisotropic)
705 {
706 context->handleError(
707 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
708 return false;
709 }
710
711 // we assume the parameter passed to this validation method is truncated, not rounded
712 if (params[0] < 1)
713 {
714 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
715 return false;
716 }
717 break;
718
719 case GL_TEXTURE_MIN_LOD:
720 case GL_TEXTURE_MAX_LOD:
721 // any value is permissible
722 break;
723
724 case GL_TEXTURE_COMPARE_MODE:
725 if (!ValidateTextureCompareModeValue(context, params))
726 {
727 return false;
728 }
729 break;
730
731 case GL_TEXTURE_COMPARE_FUNC:
732 if (!ValidateTextureCompareFuncValue(context, params))
733 {
734 return false;
735 }
736 break;
737
738 case GL_TEXTURE_SWIZZLE_R:
739 case GL_TEXTURE_SWIZZLE_G:
740 case GL_TEXTURE_SWIZZLE_B:
741 case GL_TEXTURE_SWIZZLE_A:
742 switch (ConvertToGLenum(params[0]))
743 {
744 case GL_RED:
745 case GL_GREEN:
746 case GL_BLUE:
747 case GL_ALPHA:
748 case GL_ZERO:
749 case GL_ONE:
750 break;
751
752 default:
753 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
754 return false;
755 }
756 break;
757
758 case GL_TEXTURE_BASE_LEVEL:
759 if (params[0] < 0)
760 {
761 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
762 return false;
763 }
764 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
765 {
766 context->handleError(
767 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
768 return false;
769 }
770 break;
771
772 case GL_TEXTURE_MAX_LEVEL:
773 if (params[0] < 0)
774 {
775 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
776 return false;
777 }
778 break;
779
780 default:
781 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
782 return false;
783 }
784
785 return true;
786}
787
788template <typename ParamType>
789bool ValidateSamplerParameterBase(Context *context,
790 GLuint sampler,
791 GLenum pname,
792 GLsizei bufSize,
793 ParamType *params)
794{
795 if (context->getClientMajorVersion() < 3)
796 {
797 context->handleError(
798 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
799 return false;
800 }
801
802 if (!context->isSampler(sampler))
803 {
804 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
805 return false;
806 }
807
808 const GLsizei minBufSize = 1;
809 if (bufSize >= 0 && bufSize < minBufSize)
810 {
811 context->handleError(
812 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
813 return false;
814 }
815
816 switch (pname)
817 {
818 case GL_TEXTURE_WRAP_S:
819 case GL_TEXTURE_WRAP_T:
820 case GL_TEXTURE_WRAP_R:
821 if (!ValidateTextureWrapModeValue(context, params, false))
822 {
823 return false;
824 }
825 break;
826
827 case GL_TEXTURE_MIN_FILTER:
828 if (!ValidateTextureMinFilterValue(context, params, false))
829 {
830 return false;
831 }
832 break;
833
834 case GL_TEXTURE_MAG_FILTER:
835 if (!ValidateTextureMagFilterValue(context, params))
836 {
837 return false;
838 }
839 break;
840
841 case GL_TEXTURE_MIN_LOD:
842 case GL_TEXTURE_MAX_LOD:
843 // any value is permissible
844 break;
845
846 case GL_TEXTURE_COMPARE_MODE:
847 if (!ValidateTextureCompareModeValue(context, params))
848 {
849 return false;
850 }
851 break;
852
853 case GL_TEXTURE_COMPARE_FUNC:
854 if (!ValidateTextureCompareFuncValue(context, params))
855 {
856 return false;
857 }
858 break;
859
860 default:
861 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
862 return false;
863 }
864
865 return true;
866}
867
868bool ValidateGetSamplerParameterBase(Context *context,
869 GLuint sampler,
870 GLenum pname,
871 GLsizei *length)
872{
873 if (length)
874 {
875 *length = 0;
876 }
877
878 if (context->getClientMajorVersion() < 3)
879 {
880 context->handleError(
881 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
882 return false;
883 }
884
885 if (!context->isSampler(sampler))
886 {
887 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
888 return false;
889 }
890
891 switch (pname)
892 {
893 case GL_TEXTURE_WRAP_S:
894 case GL_TEXTURE_WRAP_T:
895 case GL_TEXTURE_WRAP_R:
896 case GL_TEXTURE_MIN_FILTER:
897 case GL_TEXTURE_MAG_FILTER:
898 case GL_TEXTURE_MIN_LOD:
899 case GL_TEXTURE_MAX_LOD:
900 case GL_TEXTURE_COMPARE_MODE:
901 case GL_TEXTURE_COMPARE_FUNC:
902 break;
903
904 default:
905 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
906 return false;
907 }
908
909 if (length)
910 {
911 *length = 1;
912 }
913 return true;
914}
915
Geoff Lang0b031062016-10-13 14:30:04 -0400916bool ValidateGetVertexAttribBase(Context *context,
917 GLuint index,
918 GLenum pname,
919 GLsizei *length,
920 bool pointer,
921 bool pureIntegerEntryPoint)
922{
923 if (length)
924 {
925 *length = 0;
926 }
927
928 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
929 {
930 context->handleError(
931 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
932 return false;
933 }
934
935 if (index >= context->getCaps().maxVertexAttributes)
936 {
937 context->handleError(Error(
938 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
939 return false;
940 }
941
942 if (pointer)
943 {
944 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
945 {
946 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
947 return false;
948 }
949 }
950 else
951 {
952 switch (pname)
953 {
954 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
955 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
956 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
957 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
958 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
959 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
960 case GL_CURRENT_VERTEX_ATTRIB:
961 break;
962
963 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
964 static_assert(
965 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
966 "ANGLE extension enums not equal to GL enums.");
967 if (context->getClientMajorVersion() < 3 &&
968 !context->getExtensions().instancedArrays)
969 {
970 context->handleError(Error(GL_INVALID_ENUM,
971 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
972 "3.0 or GL_ANGLE_instanced_arrays."));
973 return false;
974 }
975 break;
976
977 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
978 if (context->getClientMajorVersion() < 3)
979 {
980 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
981 return false;
982 }
983 break;
984
985 default:
986 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
987 return false;
988 }
989 }
990
991 if (length)
992 {
993 if (pname == GL_CURRENT_VERTEX_ATTRIB)
994 {
995 *length = 4;
996 }
997 else
998 {
999 *length = 1;
1000 }
1001 }
1002
1003 return true;
1004}
1005
Geoff Lang6899b872016-10-14 11:30:13 -04001006bool ValidateGetActiveUniformBlockivBase(Context *context,
1007 GLuint program,
1008 GLuint uniformBlockIndex,
1009 GLenum pname,
1010 GLsizei *length)
1011{
1012 if (length)
1013 {
1014 *length = 0;
1015 }
1016
1017 if (context->getClientMajorVersion() < 3)
1018 {
1019 context->handleError(
1020 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1021 return false;
1022 }
1023
1024 Program *programObject = GetValidProgram(context, program);
1025 if (!programObject)
1026 {
1027 return false;
1028 }
1029
1030 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1031 {
1032 context->handleError(
1033 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1034 return false;
1035 }
1036
1037 switch (pname)
1038 {
1039 case GL_UNIFORM_BLOCK_BINDING:
1040 case GL_UNIFORM_BLOCK_DATA_SIZE:
1041 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1042 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1043 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1044 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1045 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1046 break;
1047
1048 default:
1049 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1050 return false;
1051 }
1052
1053 if (length)
1054 {
1055 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1056 {
1057 const UniformBlock &uniformBlock =
1058 programObject->getUniformBlockByIndex(uniformBlockIndex);
1059 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1060 }
1061 else
1062 {
1063 *length = 1;
1064 }
1065 }
1066
1067 return true;
1068}
1069
Geoff Langebebe1c2016-10-14 12:01:31 -04001070bool ValidateGetBufferParameterBase(ValidationContext *context,
1071 GLenum target,
1072 GLenum pname,
1073 bool pointerVersion,
1074 GLsizei *numParams)
1075{
1076 if (numParams)
1077 {
1078 *numParams = 0;
1079 }
1080
1081 if (!ValidBufferTarget(context, target))
1082 {
1083 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1084 return false;
1085 }
1086
1087 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1088 if (!buffer)
1089 {
1090 // A null buffer means that "0" is bound to the requested buffer target
1091 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1092 return false;
1093 }
1094
1095 const Extensions &extensions = context->getExtensions();
1096
1097 switch (pname)
1098 {
1099 case GL_BUFFER_USAGE:
1100 case GL_BUFFER_SIZE:
1101 break;
1102
1103 case GL_BUFFER_ACCESS_OES:
1104 if (!extensions.mapBuffer)
1105 {
1106 context->handleError(
1107 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1108 return false;
1109 }
1110 break;
1111
1112 case GL_BUFFER_MAPPED:
1113 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1114 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1115 !extensions.mapBufferRange)
1116 {
1117 context->handleError(Error(
1118 GL_INVALID_ENUM,
1119 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1120 return false;
1121 }
1122 break;
1123
1124 case GL_BUFFER_MAP_POINTER:
1125 if (!pointerVersion)
1126 {
1127 context->handleError(
1128 Error(GL_INVALID_ENUM,
1129 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1130 return false;
1131 }
1132 break;
1133
1134 case GL_BUFFER_ACCESS_FLAGS:
1135 case GL_BUFFER_MAP_OFFSET:
1136 case GL_BUFFER_MAP_LENGTH:
1137 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1138 {
1139 context->handleError(Error(
1140 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1141 return false;
1142 }
1143 break;
1144
1145 default:
1146 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1147 return false;
1148 }
1149
1150 // All buffer parameter queries return one value.
1151 if (numParams)
1152 {
1153 *numParams = 1;
1154 }
1155
1156 return true;
1157}
1158
Geoff Lang0a9661f2016-10-20 10:59:20 -07001159bool ValidateGetInternalFormativBase(Context *context,
1160 GLenum target,
1161 GLenum internalformat,
1162 GLenum pname,
1163 GLsizei bufSize,
1164 GLsizei *numParams)
1165{
1166 if (numParams)
1167 {
1168 *numParams = 0;
1169 }
1170
1171 if (context->getClientMajorVersion() < 3)
1172 {
1173 context->handleError(
1174 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1175 return false;
1176 }
1177
1178 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1179 if (!formatCaps.renderable)
1180 {
1181 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1182 return false;
1183 }
1184
1185 switch (target)
1186 {
1187 case GL_RENDERBUFFER:
1188 break;
1189
1190 default:
1191 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1192 return false;
1193 }
1194
1195 if (bufSize < 0)
1196 {
1197 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1198 return false;
1199 }
1200
1201 GLsizei maxWriteParams = 0;
1202 switch (pname)
1203 {
1204 case GL_NUM_SAMPLE_COUNTS:
1205 maxWriteParams = 1;
1206 break;
1207
1208 case GL_SAMPLES:
1209 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1210 break;
1211
1212 default:
1213 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1214 return false;
1215 }
1216
1217 if (numParams)
1218 {
1219 // glGetInternalFormativ will not overflow bufSize
1220 *numParams = std::min(bufSize, maxWriteParams);
1221 }
1222
1223 return true;
1224}
1225
Geoff Langf41a7152016-09-19 15:11:17 -04001226} // anonymous namespace
1227
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001228bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001229{
Jamie Madilld7460c72014-01-21 16:38:14 -05001230 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001231 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001232 case GL_TEXTURE_2D:
1233 case GL_TEXTURE_CUBE_MAP:
1234 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001235
Jamie Madilld7460c72014-01-21 16:38:14 -05001236 case GL_TEXTURE_3D:
1237 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001238 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001239
1240 default:
1241 return false;
1242 }
Jamie Madill35d15012013-10-07 10:46:37 -04001243}
1244
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001245bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1246{
1247 switch (target)
1248 {
1249 case GL_TEXTURE_2D:
1250 case GL_TEXTURE_CUBE_MAP:
1251 return true;
1252
1253 default:
1254 return false;
1255 }
1256}
1257
1258bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1259{
1260 switch (target)
1261 {
1262 case GL_TEXTURE_3D:
1263 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001264 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001265
1266 default:
1267 return false;
1268 }
1269}
1270
Ian Ewellbda75592016-04-18 17:25:54 -04001271// Most texture GL calls are not compatible with external textures, so we have a separate validation
1272// function for use in the GL calls that do
1273bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1274{
1275 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1276 (context->getExtensions().eglImageExternal ||
1277 context->getExtensions().eglStreamConsumerExternal);
1278}
1279
Shannon Woods4dfed832014-03-17 20:03:39 -04001280// This function differs from ValidTextureTarget in that the target must be
1281// usable as the destination of a 2D operation-- so a cube face is valid, but
1282// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001283// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001284bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001285{
1286 switch (target)
1287 {
1288 case GL_TEXTURE_2D:
1289 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1290 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1291 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1292 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1293 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1294 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1295 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001296 default:
1297 return false;
1298 }
1299}
1300
1301bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1302{
1303 switch (target)
1304 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001305 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001306 case GL_TEXTURE_2D_ARRAY:
1307 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001308 default:
1309 return false;
1310 }
1311}
1312
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001313bool ValidFramebufferTarget(GLenum target)
1314{
Geoff Langd4475812015-03-18 10:53:05 -04001315 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1316 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001317
1318 switch (target)
1319 {
1320 case GL_FRAMEBUFFER: return true;
1321 case GL_READ_FRAMEBUFFER: return true;
1322 case GL_DRAW_FRAMEBUFFER: return true;
1323 default: return false;
1324 }
1325}
1326
Jamie Madill29639852016-09-02 15:00:09 -04001327bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001328{
1329 switch (target)
1330 {
1331 case GL_ARRAY_BUFFER:
1332 case GL_ELEMENT_ARRAY_BUFFER:
1333 return true;
1334
Jamie Madill8c96d582014-03-05 15:01:23 -05001335 case GL_PIXEL_PACK_BUFFER:
1336 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001337 return (context->getExtensions().pixelBufferObject ||
1338 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001339
Shannon Woodsb3801742014-03-27 14:59:19 -04001340 case GL_COPY_READ_BUFFER:
1341 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001342 case GL_TRANSFORM_FEEDBACK_BUFFER:
1343 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001344 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001345
1346 default:
1347 return false;
1348 }
1349}
1350
Jamie Madillc29968b2016-01-20 11:17:23 -05001351bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001352{
Jamie Madillc29968b2016-01-20 11:17:23 -05001353 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001354 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001355 switch (target)
1356 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001357 case GL_TEXTURE_2D:
1358 maxDimension = caps.max2DTextureSize;
1359 break;
Geoff Langce635692013-09-24 13:56:32 -04001360 case GL_TEXTURE_CUBE_MAP:
1361 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1362 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1363 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1364 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1365 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001366 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1367 maxDimension = caps.maxCubeMapTextureSize;
1368 break;
1369 case GL_TEXTURE_3D:
1370 maxDimension = caps.max3DTextureSize;
1371 break;
1372 case GL_TEXTURE_2D_ARRAY:
1373 maxDimension = caps.max2DTextureSize;
1374 break;
Geoff Langce635692013-09-24 13:56:32 -04001375 default: UNREACHABLE();
1376 }
1377
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001378 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001379}
1380
Austin Kinross08528e12015-10-07 16:24:40 -07001381bool ValidImageSizeParameters(const Context *context,
1382 GLenum target,
1383 GLint level,
1384 GLsizei width,
1385 GLsizei height,
1386 GLsizei depth,
1387 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001388{
1389 if (level < 0 || width < 0 || height < 0 || depth < 0)
1390 {
1391 return false;
1392 }
1393
Austin Kinross08528e12015-10-07 16:24:40 -07001394 // TexSubImage parameters can be NPOT without textureNPOT extension,
1395 // as long as the destination texture is POT.
1396 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001397 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001398 {
1399 return false;
1400 }
1401
1402 if (!ValidMipLevel(context, target, level))
1403 {
1404 return false;
1405 }
1406
1407 return true;
1408}
1409
Geoff Lang0d8b7242015-09-09 14:56:53 -04001410bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1411{
1412 // List of compressed format that require that the texture size is smaller than or a multiple of
1413 // the compressed block size.
1414 switch (internalFormat)
1415 {
1416 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1417 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1418 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1419 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001420 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001421 return true;
1422
1423 default:
1424 return false;
1425 }
1426}
1427
Jamie Madillc29968b2016-01-20 11:17:23 -05001428bool ValidCompressedImageSize(const ValidationContext *context,
1429 GLenum internalFormat,
1430 GLsizei width,
1431 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001432{
Geoff Lang5d601382014-07-22 15:14:06 -04001433 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1434 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001435 {
1436 return false;
1437 }
1438
Geoff Lang0d8b7242015-09-09 14:56:53 -04001439 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001440 {
1441 return false;
1442 }
1443
Geoff Lang0d8b7242015-09-09 14:56:53 -04001444 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1445 {
1446 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1447 width % formatInfo.compressedBlockWidth != 0) ||
1448 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1449 height % formatInfo.compressedBlockHeight != 0))
1450 {
1451 return false;
1452 }
1453 }
1454
Geoff Langd4f180b2013-09-24 13:57:44 -04001455 return true;
1456}
1457
Geoff Langff5b2d52016-09-07 11:32:23 -04001458bool ValidImageDataSize(ValidationContext *context,
1459 GLenum textureTarget,
1460 GLsizei width,
1461 GLsizei height,
1462 GLsizei depth,
1463 GLenum internalFormat,
1464 GLenum type,
1465 const GLvoid *pixels,
1466 GLsizei imageSize)
1467{
1468 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1469 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1470 {
1471 // Checks are not required
1472 return true;
1473 }
1474
1475 // ...the data would be unpacked from the buffer object such that the memory reads required
1476 // would exceed the data store size.
1477 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1478 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1479 const gl::Extents size(width, height, depth);
1480 const auto &unpack = context->getGLState().getUnpackState();
1481
1482 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1483 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1484 if (endByteOrErr.isError())
1485 {
1486 context->handleError(endByteOrErr.getError());
1487 return false;
1488 }
1489
1490 GLuint endByte = endByteOrErr.getResult();
1491
1492 if (pixelUnpackBuffer)
1493 {
1494 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1495 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1496 checkedEndByte += checkedOffset;
1497
1498 if (!checkedEndByte.IsValid() ||
1499 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1500 {
1501 // Overflow past the end of the buffer
1502 context->handleError(Error(GL_INVALID_OPERATION));
1503 return false;
1504 }
1505 }
1506 else
1507 {
1508 ASSERT(imageSize >= 0);
1509 if (pixels == nullptr && imageSize != 0)
1510 {
1511 context->handleError(
1512 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1513 }
1514
1515 if (endByte > static_cast<GLuint>(imageSize))
1516 {
1517 context->handleError(
1518 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1519 return false;
1520 }
1521 }
1522
1523 return true;
1524}
1525
Geoff Lang37dde692014-01-31 16:34:54 -05001526bool ValidQueryType(const Context *context, GLenum queryType)
1527{
Geoff Langd4475812015-03-18 10:53:05 -04001528 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1529 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 -05001530
1531 switch (queryType)
1532 {
1533 case GL_ANY_SAMPLES_PASSED:
1534 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1535 return true;
1536 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001537 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001538 case GL_TIME_ELAPSED_EXT:
1539 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001540 case GL_COMMANDS_COMPLETED_CHROMIUM:
1541 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001542 default:
1543 return false;
1544 }
1545}
1546
Jamie Madillef300b12016-10-07 15:12:09 -04001547Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001548{
1549 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1550 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1551 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1552
Dian Xiang769769a2015-09-09 15:20:08 -07001553 Program *validProgram = context->getProgram(id);
1554
1555 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001556 {
Dian Xiang769769a2015-09-09 15:20:08 -07001557 if (context->getShader(id))
1558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001560 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1561 }
1562 else
1563 {
Jamie Madill437fa652016-05-03 15:13:24 -04001564 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001565 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001566 }
Dian Xiang769769a2015-09-09 15:20:08 -07001567
1568 return validProgram;
1569}
1570
Jamie Madillef300b12016-10-07 15:12:09 -04001571Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001572{
1573 // See ValidProgram for spec details.
1574
1575 Shader *validShader = context->getShader(id);
1576
1577 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001578 {
Dian Xiang769769a2015-09-09 15:20:08 -07001579 if (context->getProgram(id))
1580 {
Jamie Madill437fa652016-05-03 15:13:24 -04001581 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001582 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1583 }
1584 else
1585 {
Jamie Madill437fa652016-05-03 15:13:24 -04001586 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001587 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001588 }
Dian Xiang769769a2015-09-09 15:20:08 -07001589
1590 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001591}
1592
Geoff Langb1196682014-07-23 13:47:29 -04001593bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001594{
1595 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1596 {
1597 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1598
Geoff Langaae65a42014-05-26 12:43:44 -04001599 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001602 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001603 }
1604 }
1605 else
1606 {
1607 switch (attachment)
1608 {
1609 case GL_DEPTH_ATTACHMENT:
1610 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001611 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001612
1613 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001614 if (!context->getExtensions().webglCompatibility &&
1615 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001616 {
1617 context->handleError(Error(GL_INVALID_ENUM));
1618 return false;
1619 }
1620 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001621
1622 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001623 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001624 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001625 }
1626 }
1627
1628 return true;
1629}
1630
Corentin Walleze0902642014-11-04 12:32:15 -08001631bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1632 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001633{
1634 switch (target)
1635 {
1636 case GL_RENDERBUFFER:
1637 break;
1638 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001641 }
1642
1643 if (width < 0 || height < 0 || samples < 0)
1644 {
Jamie Madill437fa652016-05-03 15:13:24 -04001645 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001646 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001647 }
1648
Geoff Langd87878e2014-09-19 15:42:59 -04001649 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1650 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651 {
Jamie Madill437fa652016-05-03 15:13:24 -04001652 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001653 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001654 }
1655
1656 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1657 // 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 -08001658 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001659 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001660 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 {
Jamie Madill437fa652016-05-03 15:13:24 -04001662 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001663 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001664 }
1665
Geoff Langaae65a42014-05-26 12:43:44 -04001666 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001667 {
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001669 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001670 }
1671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001672 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673 if (handle == 0)
1674 {
Jamie Madill437fa652016-05-03 15:13:24 -04001675 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001676 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001677 }
1678
1679 return true;
1680}
1681
Corentin Walleze0902642014-11-04 12:32:15 -08001682bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1683 GLenum internalformat, GLsizei width, GLsizei height)
1684{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001685 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001686
1687 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001688 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001689 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001690 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001693 return false;
1694 }
1695
1696 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1697 // the specified storage. This is different than ES 3.0 in which a sample number higher
1698 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001699 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001700 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001701 {
Geoff Langa4903b72015-03-02 16:02:48 -08001702 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1703 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1704 {
Jamie Madill437fa652016-05-03 15:13:24 -04001705 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001706 return false;
1707 }
Corentin Walleze0902642014-11-04 12:32:15 -08001708 }
1709
1710 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1711}
1712
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001713bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1714 GLenum renderbuffertarget, GLuint renderbuffer)
1715{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001716 if (!ValidFramebufferTarget(target))
1717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001719 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001720 }
1721
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001722 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001723
Jamie Madill84115c92015-04-23 15:00:07 -04001724 ASSERT(framebuffer);
1725 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(
1728 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001729 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001730 }
1731
Jamie Madillb4472272014-07-03 10:38:55 -04001732 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001733 {
Jamie Madillb4472272014-07-03 10:38:55 -04001734 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001735 }
1736
Jamie Madillab9d82c2014-01-21 16:38:14 -05001737 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1738 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1739 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1740 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1741 if (renderbuffer != 0)
1742 {
1743 if (!context->getRenderbuffer(renderbuffer))
1744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001746 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001747 }
1748 }
1749
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001750 return true;
1751}
1752
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001753bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001754 GLint srcX0,
1755 GLint srcY0,
1756 GLint srcX1,
1757 GLint srcY1,
1758 GLint dstX0,
1759 GLint dstY0,
1760 GLint dstX1,
1761 GLint dstY1,
1762 GLbitfield mask,
1763 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001764{
1765 switch (filter)
1766 {
1767 case GL_NEAREST:
1768 break;
1769 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001770 break;
1771 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001772 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001773 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001774 }
1775
1776 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001779 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001780 }
1781
1782 if (mask == 0)
1783 {
1784 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1785 // buffers are copied.
1786 return false;
1787 }
1788
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1790 // color buffer, leaving only nearest being unfiltered from above
1791 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1792 {
Jamie Madill437fa652016-05-03 15:13:24 -04001793 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 }
1796
Jamie Madill51f40ec2016-06-15 14:06:00 -04001797 const auto &glState = context->getGLState();
1798 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1799 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001800
1801 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001802 {
Jamie Madill437fa652016-05-03 15:13:24 -04001803 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001804 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001805 }
1806
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001807 if (readFramebuffer->id() == drawFramebuffer->id())
1808 {
1809 context->handleError(Error(GL_INVALID_OPERATION));
1810 return false;
1811 }
1812
Jamie Madill51f40ec2016-06-15 14:06:00 -04001813 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001814 {
Jamie Madill437fa652016-05-03 15:13:24 -04001815 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001816 return false;
1817 }
1818
Jamie Madill51f40ec2016-06-15 14:06:00 -04001819 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001820 {
Jamie Madill437fa652016-05-03 15:13:24 -04001821 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001822 return false;
1823 }
1824
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001825 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001826 {
Jamie Madill437fa652016-05-03 15:13:24 -04001827 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001828 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001829 }
1830
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001831 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1832
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001833 if (mask & GL_COLOR_BUFFER_BIT)
1834 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001835 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1836 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001837 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001838
1839 if (readColorBuffer && drawColorBuffer)
1840 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001841 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001842
Geoff Langa15472a2015-08-11 11:48:03 -04001843 for (size_t drawbufferIdx = 0;
1844 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001845 {
Geoff Langa15472a2015-08-11 11:48:03 -04001846 const FramebufferAttachment *attachment =
1847 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1848 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001849 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001850 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001851
Geoff Langb2f3d052013-08-13 12:49:27 -04001852 // The GL ES 3.0.2 spec (pg 193) states that:
1853 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1854 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1855 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001856 // Changes with EXT_color_buffer_float:
1857 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001858 GLenum readComponentType = readFormat.info->componentType;
1859 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001860 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1861 readComponentType == GL_SIGNED_NORMALIZED);
1862 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1863 drawComponentType == GL_SIGNED_NORMALIZED);
1864
1865 if (extensions.colorBufferFloat)
1866 {
1867 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1868 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1869
1870 if (readFixedOrFloat != drawFixedOrFloat)
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001873 "If the read buffer contains fixed-point or "
1874 "floating-point values, the draw buffer "
1875 "must as well."));
1876 return false;
1877 }
1878 }
1879 else if (readFixedPoint != drawFixedPoint)
1880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001882 "If the read buffer contains fixed-point "
1883 "values, the draw buffer must as well."));
1884 return false;
1885 }
1886
1887 if (readComponentType == GL_UNSIGNED_INT &&
1888 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001889 {
Jamie Madill437fa652016-05-03 15:13:24 -04001890 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001891 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001892 }
1893
Jamie Madill6163c752015-12-07 16:32:59 -05001894 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001897 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001898 }
1899
Jamie Madilla3944d42016-07-22 22:13:26 -04001900 if (readColorBuffer->getSamples() > 0 &&
1901 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001904 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001905 }
1906 }
1907 }
1908
Jamie Madilla3944d42016-07-22 22:13:26 -04001909 if ((readFormat.info->componentType == GL_INT ||
1910 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1911 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001912 {
Jamie Madill437fa652016-05-03 15:13:24 -04001913 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001914 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001915 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001916 }
1917 }
1918
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001919 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1920 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1921 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001922 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001923 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001924 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001925 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1926 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001927
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001928 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001929 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001930 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001931 {
Jamie Madill437fa652016-05-03 15:13:24 -04001932 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001933 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001934 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001935
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001936 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001937 {
Jamie Madill437fa652016-05-03 15:13:24 -04001938 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001939 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001940 }
1941 }
1942 }
1943 }
1944
1945 return true;
1946}
1947
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001948bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001949 GLint x,
1950 GLint y,
1951 GLsizei width,
1952 GLsizei height,
1953 GLenum format,
1954 GLenum type,
1955 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001956{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001957 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1958}
1959
1960bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1961 GLint x,
1962 GLint y,
1963 GLsizei width,
1964 GLsizei height,
1965 GLenum format,
1966 GLenum type,
1967 GLsizei bufSize,
1968 GLsizei *length,
1969 GLvoid *pixels)
1970{
1971 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001972 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001973 return false;
1974 }
1975
Geoff Lang62fce5b2016-09-30 10:46:35 -04001976 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1977 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001978 {
Geoff Langb1196682014-07-23 13:47:29 -04001979 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001980 }
1981
Geoff Lang62fce5b2016-09-30 10:46:35 -04001982 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001983 {
Geoff Langb1196682014-07-23 13:47:29 -04001984 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001985 }
1986
Jamie Madillc29968b2016-01-20 11:17:23 -05001987 return true;
1988}
1989
1990bool ValidateReadnPixelsEXT(Context *context,
1991 GLint x,
1992 GLint y,
1993 GLsizei width,
1994 GLsizei height,
1995 GLenum format,
1996 GLenum type,
1997 GLsizei bufSize,
1998 GLvoid *pixels)
1999{
2000 if (bufSize < 0)
2001 {
Jamie Madill437fa652016-05-03 15:13:24 -04002002 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002003 return false;
2004 }
2005
Geoff Lang62fce5b2016-09-30 10:46:35 -04002006 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2007 pixels);
2008}
Jamie Madill26e91952014-03-05 15:01:27 -05002009
Geoff Lang62fce5b2016-09-30 10:46:35 -04002010bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2011 GLint x,
2012 GLint y,
2013 GLsizei width,
2014 GLsizei height,
2015 GLenum format,
2016 GLenum type,
2017 GLsizei bufSize,
2018 GLsizei *length,
2019 GLvoid *data)
2020{
2021 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002022 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002023 return false;
2024 }
2025
Geoff Lang62fce5b2016-09-30 10:46:35 -04002026 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002027 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002028 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002029 }
2030
Geoff Lang62fce5b2016-09-30 10:46:35 -04002031 if (!ValidateRobustBufferSize(context, bufSize, *length))
2032 {
2033 return false;
2034 }
2035
2036 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002037}
2038
Olli Etuaho41997e72016-03-10 13:38:39 +02002039bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002040{
2041 if (!context->getExtensions().occlusionQueryBoolean &&
2042 !context->getExtensions().disjointTimerQuery)
2043 {
Jamie Madill437fa652016-05-03 15:13:24 -04002044 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045 return false;
2046 }
2047
Olli Etuaho41997e72016-03-10 13:38:39 +02002048 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002049}
2050
Olli Etuaho41997e72016-03-10 13:38:39 +02002051bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052{
2053 if (!context->getExtensions().occlusionQueryBoolean &&
2054 !context->getExtensions().disjointTimerQuery)
2055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
2059
Olli Etuaho41997e72016-03-10 13:38:39 +02002060 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002061}
2062
2063bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002064{
2065 if (!ValidQueryType(context, target))
2066 {
Jamie Madill437fa652016-05-03 15:13:24 -04002067 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002068 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002069 }
2070
2071 if (id == 0)
2072 {
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002074 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002075 }
2076
2077 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2078 // of zero, if the active query object name for <target> is non-zero (for the
2079 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2080 // the active query for either target is non-zero), if <id> is the name of an
2081 // existing query object whose type does not match <target>, or if <id> is the
2082 // active query object name for any query type, the error INVALID_OPERATION is
2083 // generated.
2084
2085 // Ensure no other queries are active
2086 // NOTE: If other queries than occlusion are supported, we will need to check
2087 // separately that:
2088 // a) The query ID passed is not the current active query for any target/type
2089 // b) There are no active queries for the requested target (and in the case
2090 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2091 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002092
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002093 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002096 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002097 }
2098
2099 Query *queryObject = context->getQuery(id, true, target);
2100
2101 // check that name was obtained with glGenQueries
2102 if (!queryObject)
2103 {
Jamie Madill437fa652016-05-03 15:13:24 -04002104 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002105 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002106 }
2107
2108 // check for type mismatch
2109 if (queryObject->getType() != target)
2110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002112 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002113 }
2114
2115 return true;
2116}
2117
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002118bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2119{
2120 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002121 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002122 {
Jamie Madill437fa652016-05-03 15:13:24 -04002123 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002124 return false;
2125 }
2126
2127 return ValidateBeginQueryBase(context, target, id);
2128}
2129
2130bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002131{
2132 if (!ValidQueryType(context, target))
2133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002135 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002136 }
2137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002138 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002139
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002140 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002141 {
Jamie Madill437fa652016-05-03 15:13:24 -04002142 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002143 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002144 }
2145
Jamie Madill45c785d2014-05-13 14:09:34 -04002146 return true;
2147}
2148
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002149bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2150{
2151 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002152 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002153 {
Jamie Madill437fa652016-05-03 15:13:24 -04002154 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002155 return false;
2156 }
2157
2158 return ValidateEndQueryBase(context, target);
2159}
2160
2161bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2162{
2163 if (!context->getExtensions().disjointTimerQuery)
2164 {
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002166 return false;
2167 }
2168
2169 if (target != GL_TIMESTAMP_EXT)
2170 {
Jamie Madill437fa652016-05-03 15:13:24 -04002171 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002172 return false;
2173 }
2174
2175 Query *queryObject = context->getQuery(id, true, target);
2176 if (queryObject == nullptr)
2177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002179 return false;
2180 }
2181
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002182 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002183 {
Jamie Madill437fa652016-05-03 15:13:24 -04002184 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002185 return false;
2186 }
2187
2188 return true;
2189}
2190
Geoff Lang2186c382016-10-14 10:54:54 -04002191bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002192{
Geoff Lang2186c382016-10-14 10:54:54 -04002193 if (numParams)
2194 {
2195 *numParams = 0;
2196 }
2197
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002198 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002201 return false;
2202 }
2203
2204 switch (pname)
2205 {
2206 case GL_CURRENT_QUERY_EXT:
2207 if (target == GL_TIMESTAMP_EXT)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002210 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2211 return false;
2212 }
2213 break;
2214 case GL_QUERY_COUNTER_BITS_EXT:
2215 if (!context->getExtensions().disjointTimerQuery ||
2216 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2217 {
Jamie Madill437fa652016-05-03 15:13:24 -04002218 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002219 return false;
2220 }
2221 break;
2222 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002223 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002224 return false;
2225 }
2226
Geoff Lang2186c382016-10-14 10:54:54 -04002227 if (numParams)
2228 {
2229 // All queries return only one value
2230 *numParams = 1;
2231 }
2232
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002233 return true;
2234}
2235
2236bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2237{
2238 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002239 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002240 {
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002242 return false;
2243 }
2244
Geoff Lang2186c382016-10-14 10:54:54 -04002245 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002246}
2247
Geoff Lang2186c382016-10-14 10:54:54 -04002248bool ValidateGetQueryivRobustANGLE(Context *context,
2249 GLenum target,
2250 GLenum pname,
2251 GLsizei bufSize,
2252 GLsizei *length,
2253 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002254{
Geoff Lang2186c382016-10-14 10:54:54 -04002255 if (!ValidateRobustEntryPoint(context, bufSize))
2256 {
2257 return false;
2258 }
2259
2260 if (!ValidateGetQueryivBase(context, target, pname, length))
2261 {
2262 return false;
2263 }
2264
2265 if (!ValidateRobustBufferSize(context, bufSize, *length))
2266 {
2267 return false;
2268 }
2269
2270 return true;
2271}
2272
2273bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2274{
2275 if (numParams)
2276 {
2277 *numParams = 0;
2278 }
2279
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280 Query *queryObject = context->getQuery(id, false, GL_NONE);
2281
2282 if (!queryObject)
2283 {
Jamie Madill437fa652016-05-03 15:13:24 -04002284 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002285 return false;
2286 }
2287
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002288 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002289 {
Jamie Madill437fa652016-05-03 15:13:24 -04002290 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 return false;
2292 }
2293
2294 switch (pname)
2295 {
2296 case GL_QUERY_RESULT_EXT:
2297 case GL_QUERY_RESULT_AVAILABLE_EXT:
2298 break;
2299
2300 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002301 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002302 return false;
2303 }
2304
Geoff Lang2186c382016-10-14 10:54:54 -04002305 if (numParams)
2306 {
2307 *numParams = 1;
2308 }
2309
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002310 return true;
2311}
2312
2313bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2314{
2315 if (!context->getExtensions().disjointTimerQuery)
2316 {
Jamie Madill437fa652016-05-03 15:13:24 -04002317 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002318 return false;
2319 }
Geoff Lang2186c382016-10-14 10:54:54 -04002320 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2321}
2322
2323bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2324 GLuint id,
2325 GLenum pname,
2326 GLsizei bufSize,
2327 GLsizei *length,
2328 GLint *params)
2329{
2330 if (!context->getExtensions().disjointTimerQuery)
2331 {
2332 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2333 return false;
2334 }
2335
2336 if (!ValidateRobustEntryPoint(context, bufSize))
2337 {
2338 return false;
2339 }
2340
2341 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2342 {
2343 return false;
2344 }
2345
2346 if (!ValidateRobustBufferSize(context, bufSize, *length))
2347 {
2348 return false;
2349 }
2350
2351 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002352}
2353
2354bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2355{
2356 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002357 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002358 {
Jamie Madill437fa652016-05-03 15:13:24 -04002359 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002360 return false;
2361 }
Geoff Lang2186c382016-10-14 10:54:54 -04002362 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2363}
2364
2365bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2366 GLuint id,
2367 GLenum pname,
2368 GLsizei bufSize,
2369 GLsizei *length,
2370 GLuint *params)
2371{
2372 if (!context->getExtensions().disjointTimerQuery &&
2373 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2374 {
2375 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2376 return false;
2377 }
2378
2379 if (!ValidateRobustEntryPoint(context, bufSize))
2380 {
2381 return false;
2382 }
2383
2384 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2385 {
2386 return false;
2387 }
2388
2389 if (!ValidateRobustBufferSize(context, bufSize, *length))
2390 {
2391 return false;
2392 }
2393
2394 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002395}
2396
2397bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2398{
2399 if (!context->getExtensions().disjointTimerQuery)
2400 {
Jamie Madill437fa652016-05-03 15:13:24 -04002401 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002402 return false;
2403 }
Geoff Lang2186c382016-10-14 10:54:54 -04002404 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2405}
2406
2407bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2408 GLuint id,
2409 GLenum pname,
2410 GLsizei bufSize,
2411 GLsizei *length,
2412 GLint64 *params)
2413{
2414 if (!context->getExtensions().disjointTimerQuery)
2415 {
2416 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2417 return false;
2418 }
2419
2420 if (!ValidateRobustEntryPoint(context, bufSize))
2421 {
2422 return false;
2423 }
2424
2425 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2426 {
2427 return false;
2428 }
2429
2430 if (!ValidateRobustBufferSize(context, bufSize, *length))
2431 {
2432 return false;
2433 }
2434
2435 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002436}
2437
2438bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2439{
2440 if (!context->getExtensions().disjointTimerQuery)
2441 {
Jamie Madill437fa652016-05-03 15:13:24 -04002442 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002443 return false;
2444 }
Geoff Lang2186c382016-10-14 10:54:54 -04002445 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2446}
2447
2448bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2449 GLuint id,
2450 GLenum pname,
2451 GLsizei bufSize,
2452 GLsizei *length,
2453 GLuint64 *params)
2454{
2455 if (!context->getExtensions().disjointTimerQuery)
2456 {
2457 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2458 return false;
2459 }
2460
2461 if (!ValidateRobustEntryPoint(context, bufSize))
2462 {
2463 return false;
2464 }
2465
2466 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2467 {
2468 return false;
2469 }
2470
2471 if (!ValidateRobustBufferSize(context, bufSize, *length))
2472 {
2473 return false;
2474 }
2475
2476 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002477}
2478
Jamie Madill62d31cb2015-09-11 13:25:51 -04002479static bool ValidateUniformCommonBase(gl::Context *context,
2480 GLenum targetUniformType,
2481 GLint location,
2482 GLsizei count,
2483 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002484{
2485 if (count < 0)
2486 {
Jamie Madill437fa652016-05-03 15:13:24 -04002487 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002488 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002489 }
2490
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002491 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002492 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002493 {
Jamie Madill437fa652016-05-03 15:13:24 -04002494 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002495 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002496 }
2497
Geoff Langd8605522016-04-13 10:19:12 -04002498 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002499 {
2500 // Silently ignore the uniform command
2501 return false;
2502 }
2503
Geoff Lang7dd2e102014-11-10 15:19:26 -05002504 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002505 {
Jamie Madill437fa652016-05-03 15:13:24 -04002506 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002508 }
2509
Jamie Madill62d31cb2015-09-11 13:25:51 -04002510 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002511
2512 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002513 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002514 {
Jamie Madill437fa652016-05-03 15:13:24 -04002515 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002516 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002517 }
2518
Jamie Madill62d31cb2015-09-11 13:25:51 -04002519 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002520 return true;
2521}
2522
Jamie Madillaa981bd2014-05-20 10:55:55 -04002523bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2524{
2525 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002526 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2527 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002528 {
Jamie Madill437fa652016-05-03 15:13:24 -04002529 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002530 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002531 }
2532
Jamie Madill62d31cb2015-09-11 13:25:51 -04002533 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002534 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2535 {
2536 return false;
2537 }
2538
Jamie Madillf2575982014-06-25 16:04:54 -04002539 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002540 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002541 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002544 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002545 }
2546
2547 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002548}
2549
2550bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2551 GLboolean transpose)
2552{
2553 // Check for ES3 uniform entry points
2554 int rows = VariableRowCount(matrixType);
2555 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002556 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002557 {
Jamie Madill437fa652016-05-03 15:13:24 -04002558 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002559 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002560 }
2561
Martin Radev1be913c2016-07-11 17:59:16 +03002562 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002563 {
Jamie Madill437fa652016-05-03 15:13:24 -04002564 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002565 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002566 }
2567
Jamie Madill62d31cb2015-09-11 13:25:51 -04002568 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002569 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2570 {
2571 return false;
2572 }
2573
2574 if (uniform->type != matrixType)
2575 {
Jamie Madill437fa652016-05-03 15:13:24 -04002576 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002577 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002578 }
2579
2580 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002581}
2582
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002583bool ValidateStateQuery(ValidationContext *context,
2584 GLenum pname,
2585 GLenum *nativeType,
2586 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002587{
2588 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2589 {
Jamie Madill437fa652016-05-03 15:13:24 -04002590 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002591 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002592 }
2593
Jamie Madill0af26e12015-03-05 19:54:33 -05002594 const Caps &caps = context->getCaps();
2595
Jamie Madill893ab082014-05-16 16:56:10 -04002596 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2597 {
2598 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2599
Jamie Madill0af26e12015-03-05 19:54:33 -05002600 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002601 {
Jamie Madill437fa652016-05-03 15:13:24 -04002602 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002603 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002604 }
2605 }
2606
2607 switch (pname)
2608 {
2609 case GL_TEXTURE_BINDING_2D:
2610 case GL_TEXTURE_BINDING_CUBE_MAP:
2611 case GL_TEXTURE_BINDING_3D:
2612 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002613 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002614 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002615 if (!context->getExtensions().eglStreamConsumerExternal &&
2616 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002617 {
John Bauman18319182016-09-28 14:22:27 -07002618 context->handleError(Error(GL_INVALID_ENUM,
2619 "Neither NV_EGL_stream_consumer_external nor "
2620 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002621 return false;
2622 }
2623 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002624
2625 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2626 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2627 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002628 if (context->getGLState().getReadFramebuffer()->checkStatus(
2629 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002630 {
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 Madill893ab082014-05-16 16:56:10 -04002633 }
2634
Jamie Madill51f40ec2016-06-15 14:06:00 -04002635 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2636 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002637
2638 if (framebuffer->getReadBufferState() == GL_NONE)
2639 {
2640 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2641 return false;
2642 }
2643
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002644 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002645 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002646 {
Jamie Madill437fa652016-05-03 15:13:24 -04002647 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002648 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002649 }
2650 }
2651 break;
2652
2653 default:
2654 break;
2655 }
2656
2657 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002658 if (*numParams == 0)
2659 {
2660 return false;
2661 }
2662
2663 return true;
2664}
2665
2666bool ValidateRobustStateQuery(ValidationContext *context,
2667 GLenum pname,
2668 GLsizei bufSize,
2669 GLenum *nativeType,
2670 unsigned int *numParams)
2671{
2672 if (!ValidateRobustEntryPoint(context, bufSize))
2673 {
2674 return false;
2675 }
2676
2677 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2678 {
2679 return false;
2680 }
2681
2682 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002683 {
2684 return false;
2685 }
2686
2687 return true;
2688}
2689
Jamie Madillc29968b2016-01-20 11:17:23 -05002690bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2691 GLenum target,
2692 GLint level,
2693 GLenum internalformat,
2694 bool isSubImage,
2695 GLint xoffset,
2696 GLint yoffset,
2697 GLint zoffset,
2698 GLint x,
2699 GLint y,
2700 GLsizei width,
2701 GLsizei height,
2702 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002703 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002704{
Jamie Madill560a8d82014-05-21 13:06:20 -04002705 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2706 {
Jamie Madill437fa652016-05-03 15:13:24 -04002707 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002708 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002709 }
2710
2711 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2712 {
Jamie Madill437fa652016-05-03 15:13:24 -04002713 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002714 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002715 }
2716
2717 if (border != 0)
2718 {
Jamie Madill437fa652016-05-03 15:13:24 -04002719 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002720 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002721 }
2722
2723 if (!ValidMipLevel(context, target, level))
2724 {
Jamie Madill437fa652016-05-03 15:13:24 -04002725 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002726 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002727 }
2728
Jamie Madill51f40ec2016-06-15 14:06:00 -04002729 const auto &state = context->getGLState();
2730 auto readFramebuffer = state.getReadFramebuffer();
2731 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002732 {
Jamie Madill437fa652016-05-03 15:13:24 -04002733 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002735 }
2736
Jamie Madill51f40ec2016-06-15 14:06:00 -04002737 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002738 {
Jamie Madill437fa652016-05-03 15:13:24 -04002739 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002740 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002741 }
2742
Martin Radev138064f2016-07-15 12:03:41 +03002743 if (readFramebuffer->getReadBufferState() == GL_NONE)
2744 {
2745 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2746 return false;
2747 }
2748
Geoff Langaae65a42014-05-26 12:43:44 -04002749 const gl::Caps &caps = context->getCaps();
2750
Geoff Langaae65a42014-05-26 12:43:44 -04002751 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002752 switch (target)
2753 {
2754 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002755 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002756 break;
2757
2758 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2759 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2760 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2761 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2762 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2763 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002764 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002765 break;
2766
2767 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002768 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002769 break;
2770
2771 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002772 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002773 break;
2774
2775 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002776 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002777 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002778 }
2779
Jamie Madillc29968b2016-01-20 11:17:23 -05002780 gl::Texture *texture =
2781 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002782 if (!texture)
2783 {
Jamie Madill437fa652016-05-03 15:13:24 -04002784 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002785 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002786 }
2787
Geoff Lang69cce582015-09-17 13:20:36 -04002788 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002789 {
Jamie Madill437fa652016-05-03 15:13:24 -04002790 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002791 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002792 }
2793
Geoff Lang5d601382014-07-22 15:14:06 -04002794 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2795
2796 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002797 {
Jamie Madill437fa652016-05-03 15:13:24 -04002798 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002799 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002800 }
2801
Geoff Langa9be0dc2014-12-17 12:34:40 -05002802 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002803 {
Jamie Madill437fa652016-05-03 15:13:24 -04002804 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002805 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002806 }
2807
2808 if (isSubImage)
2809 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002810 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2811 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2812 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002813 {
Jamie Madill437fa652016-05-03 15:13:24 -04002814 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002815 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002816 }
2817 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002818 else
2819 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002820 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002821 {
Jamie Madill437fa652016-05-03 15:13:24 -04002822 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002823 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002824 }
2825
Martin Radev1be913c2016-07-11 17:59:16 +03002826 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002827 {
Jamie Madill437fa652016-05-03 15:13:24 -04002828 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002829 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002830 }
2831
2832 int maxLevelDimension = (maxDimension >> level);
2833 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2834 {
Jamie Madill437fa652016-05-03 15:13:24 -04002835 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002836 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002837 }
2838 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002839
Jamie Madill0c8abca2016-07-22 20:21:26 -04002840 if (textureFormatOut)
2841 {
2842 *textureFormatOut = texture->getFormat(target, level);
2843 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002844 return true;
2845}
2846
Jamie Madillf25855c2015-11-03 11:06:18 -05002847static bool ValidateDrawBase(ValidationContext *context,
2848 GLenum mode,
2849 GLsizei count,
2850 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002851{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002852 switch (mode)
2853 {
2854 case GL_POINTS:
2855 case GL_LINES:
2856 case GL_LINE_LOOP:
2857 case GL_LINE_STRIP:
2858 case GL_TRIANGLES:
2859 case GL_TRIANGLE_STRIP:
2860 case GL_TRIANGLE_FAN:
2861 break;
2862 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002863 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002864 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002865 }
2866
Jamie Madill250d33f2014-06-06 17:09:03 -04002867 if (count < 0)
2868 {
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 Madill250d33f2014-06-06 17:09:03 -04002871 }
2872
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002873 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002874
Jamie Madill250d33f2014-06-06 17:09:03 -04002875 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002876 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002877 {
Jamie Madill437fa652016-05-03 15:13:24 -04002878 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002879 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002880 }
2881
Jamie Madill51f40ec2016-06-15 14:06:00 -04002882 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002883 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002884 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002885 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2886 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2887 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2888 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2889 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2890 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002891 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002892 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2893 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002894 {
2895 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2896 // Section 6.10 of the WebGL 1.0 spec
2897 ERR(
2898 "This ANGLE implementation does not support separate front/back stencil "
2899 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002900 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002901 return false;
2902 }
Jamie Madillac528012014-06-20 13:21:23 -04002903 }
2904
Jamie Madill51f40ec2016-06-15 14:06:00 -04002905 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002906 {
Jamie Madill437fa652016-05-03 15:13:24 -04002907 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002908 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002909 }
2910
Geoff Lang7dd2e102014-11-10 15:19:26 -05002911 gl::Program *program = state.getProgram();
2912 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002913 {
Jamie Madill437fa652016-05-03 15:13:24 -04002914 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002915 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002916 }
2917
Geoff Lang7dd2e102014-11-10 15:19:26 -05002918 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002919 {
Jamie Madill437fa652016-05-03 15:13:24 -04002920 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002921 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002922 }
2923
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002924 // Uniform buffer validation
2925 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2926 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002927 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002928 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002929 const OffsetBindingPointer<Buffer> &uniformBuffer =
2930 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002931
Geoff Lang5d124a62015-09-15 13:03:27 -04002932 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002933 {
2934 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002935 context->handleError(
2936 Error(GL_INVALID_OPERATION,
2937 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002938 return false;
2939 }
2940
Geoff Lang5d124a62015-09-15 13:03:27 -04002941 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002942 if (uniformBufferSize == 0)
2943 {
2944 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002945 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002946 }
2947
Jamie Madill62d31cb2015-09-11 13:25:51 -04002948 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002949 {
2950 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002951 context->handleError(
2952 Error(GL_INVALID_OPERATION,
2953 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002954 return false;
2955 }
2956 }
2957
Jamie Madill250d33f2014-06-06 17:09:03 -04002958 // No-op if zero count
2959 return (count > 0);
2960}
2961
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002962bool ValidateDrawArrays(ValidationContext *context,
2963 GLenum mode,
2964 GLint first,
2965 GLsizei count,
2966 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002967{
Jamie Madillfd716582014-06-06 17:09:04 -04002968 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 {
Jamie Madill437fa652016-05-03 15:13:24 -04002970 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002971 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002972 }
2973
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002974 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002975 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002976 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2977 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002978 {
2979 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2980 // that does not match the current transform feedback object's draw mode (if transform feedback
2981 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002982 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002984 }
2985
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002986 if (!ValidateDrawBase(context, mode, count, primcount))
2987 {
2988 return false;
2989 }
2990
2991 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002992 {
2993 return false;
2994 }
2995
2996 return true;
2997}
2998
Geoff Langb1196682014-07-23 13:47:29 -04002999bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003000{
3001 if (primcount < 0)
3002 {
Jamie Madill437fa652016-05-03 15:13:24 -04003003 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003004 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003005 }
3006
Jamie Madill2b976812014-08-25 15:47:49 -04003007 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003008 {
3009 return false;
3010 }
3011
3012 // No-op if zero primitive count
3013 return (primcount > 0);
3014}
3015
Geoff Lang87a93302014-09-16 13:29:43 -04003016static bool ValidateDrawInstancedANGLE(Context *context)
3017{
3018 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003019 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003020
Geoff Lang7dd2e102014-11-10 15:19:26 -05003021 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003022
3023 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003024 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003025 {
3026 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003027 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003028 {
3029 return true;
3030 }
3031 }
3032
Jamie Madill437fa652016-05-03 15:13:24 -04003033 context->handleError(Error(GL_INVALID_OPERATION,
3034 "ANGLE_instanced_arrays requires that at least one active attribute"
3035 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003036 return false;
3037}
3038
3039bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
3040{
3041 if (!ValidateDrawInstancedANGLE(context))
3042 {
3043 return false;
3044 }
3045
3046 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3047}
3048
Jamie Madillf25855c2015-11-03 11:06:18 -05003049bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003050 GLenum mode,
3051 GLsizei count,
3052 GLenum type,
3053 const GLvoid *indices,
3054 GLsizei primcount,
3055 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003056{
Jamie Madill250d33f2014-06-06 17:09:03 -04003057 switch (type)
3058 {
3059 case GL_UNSIGNED_BYTE:
3060 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03003061 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003062 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03003063 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3064 {
3065 context->handleError(Error(GL_INVALID_ENUM));
3066 return false;
3067 }
3068 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003069 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003070 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003071 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003072 }
3073
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003074 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003075
3076 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003077 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003078 {
3079 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3080 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003082 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003083 }
3084
3085 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003086 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003087 {
Jamie Madill437fa652016-05-03 15:13:24 -04003088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003089 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003090 }
3091
Jamie Madill2b976812014-08-25 15:47:49 -04003092 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003093 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003094 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003098 }
3099
Jamie Madillae3000b2014-08-25 15:47:51 -04003100 if (elementArrayBuffer)
3101 {
3102 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3103
3104 GLint64 offset = reinterpret_cast<GLint64>(indices);
3105 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3106
3107 // check for integer overflows
3108 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3109 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3110 {
Jamie Madill437fa652016-05-03 15:13:24 -04003111 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003113 }
3114
3115 // Check for reading past the end of the bound buffer object
3116 if (byteCount > elementArrayBuffer->getSize())
3117 {
Jamie Madill437fa652016-05-03 15:13:24 -04003118 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003119 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003120 }
3121 }
3122 else if (!indices)
3123 {
3124 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003127 }
3128
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003129 if (!ValidateDrawBase(context, mode, count, primcount))
3130 {
3131 return false;
3132 }
3133
Jamie Madill2b976812014-08-25 15:47:49 -04003134 // Use max index to validate if our vertex buffers are large enough for the pull.
3135 // TODO: offer fast path, with disabled index validation.
3136 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3137 if (elementArrayBuffer)
3138 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003139 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003140 Error error =
3141 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3142 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003143 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003144 {
Jamie Madill437fa652016-05-03 15:13:24 -04003145 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003146 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003147 }
3148 }
3149 else
3150 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003151 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003152 }
3153
Jamie Madille79b1e12015-11-04 16:36:37 -05003154 // If we use an index greater than our maximum supported index range, return an error.
3155 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3156 // return an error if possible here.
3157 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3158 {
Jamie Madill437fa652016-05-03 15:13:24 -04003159 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003160 return false;
3161 }
3162
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003163 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003164 {
3165 return false;
3166 }
3167
Geoff Lang3edfe032015-09-04 16:38:24 -04003168 // No op if there are no real indices in the index data (all are primitive restart).
3169 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003170}
3171
Geoff Langb1196682014-07-23 13:47:29 -04003172bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003173 GLenum mode,
3174 GLsizei count,
3175 GLenum type,
3176 const GLvoid *indices,
3177 GLsizei primcount,
3178 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003179{
3180 if (primcount < 0)
3181 {
Jamie Madill437fa652016-05-03 15:13:24 -04003182 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003183 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003184 }
3185
Jamie Madill2b976812014-08-25 15:47:49 -04003186 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003187 {
3188 return false;
3189 }
3190
3191 // No-op zero primitive count
3192 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003193}
3194
Geoff Lang3edfe032015-09-04 16:38:24 -04003195bool ValidateDrawElementsInstancedANGLE(Context *context,
3196 GLenum mode,
3197 GLsizei count,
3198 GLenum type,
3199 const GLvoid *indices,
3200 GLsizei primcount,
3201 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003202{
3203 if (!ValidateDrawInstancedANGLE(context))
3204 {
3205 return false;
3206 }
3207
3208 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3209}
3210
Geoff Langb1196682014-07-23 13:47:29 -04003211bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003212 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003213{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003214 if (!ValidFramebufferTarget(target))
3215 {
Jamie Madill437fa652016-05-03 15:13:24 -04003216 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003218 }
3219
3220 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003221 {
3222 return false;
3223 }
3224
Jamie Madill55ec3b12014-07-03 10:38:57 -04003225 if (texture != 0)
3226 {
3227 gl::Texture *tex = context->getTexture(texture);
3228
3229 if (tex == NULL)
3230 {
Jamie Madill437fa652016-05-03 15:13:24 -04003231 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003232 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003233 }
3234
3235 if (level < 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 Madill55ec3b12014-07-03 10:38:57 -04003239 }
3240 }
3241
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003242 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003243 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003244
Jamie Madill84115c92015-04-23 15:00:07 -04003245 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003246 {
Jamie Madill437fa652016-05-03 15:13:24 -04003247 context->handleError(
3248 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003249 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003250 }
3251
3252 return true;
3253}
3254
Geoff Langb1196682014-07-23 13:47:29 -04003255bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003256 GLenum textarget, GLuint texture, GLint level)
3257{
Geoff Lang95663912015-04-02 15:54:45 -04003258 // 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 +03003259 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3260 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003261 {
Jamie Madill437fa652016-05-03 15:13:24 -04003262 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003263 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003264 }
3265
3266 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003267 {
3268 return false;
3269 }
3270
Jamie Madill55ec3b12014-07-03 10:38:57 -04003271 if (texture != 0)
3272 {
3273 gl::Texture *tex = context->getTexture(texture);
3274 ASSERT(tex);
3275
Jamie Madill2a6564e2014-07-11 09:53:19 -04003276 const gl::Caps &caps = context->getCaps();
3277
Jamie Madill55ec3b12014-07-03 10:38:57 -04003278 switch (textarget)
3279 {
3280 case GL_TEXTURE_2D:
3281 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003282 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003283 {
Jamie Madill437fa652016-05-03 15:13:24 -04003284 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003285 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003286 }
3287 if (tex->getTarget() != GL_TEXTURE_2D)
3288 {
Jamie Madill437fa652016-05-03 15:13:24 -04003289 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003290 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003291 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003292 }
3293 break;
3294
3295 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3296 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3297 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3298 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3299 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3300 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3301 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003302 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003303 {
Jamie Madill437fa652016-05-03 15:13:24 -04003304 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003305 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003306 }
3307 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3308 {
Jamie Madill437fa652016-05-03 15:13:24 -04003309 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003310 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003311 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003312 }
3313 break;
3314
3315 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003316 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003317 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003318 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003319
Jamie Madilla3944d42016-07-22 22:13:26 -04003320 const Format &format = tex->getFormat(textarget, level);
3321 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003322 {
Jamie Madill437fa652016-05-03 15:13:24 -04003323 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003324 return false;
3325 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003326 }
3327
Jamie Madill570f7c82014-07-03 10:38:54 -04003328 return true;
3329}
3330
Geoff Langb1196682014-07-23 13:47:29 -04003331bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003332{
3333 if (program == 0)
3334 {
Jamie Madill437fa652016-05-03 15:13:24 -04003335 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003336 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003337 }
3338
Dian Xiang769769a2015-09-09 15:20:08 -07003339 gl::Program *programObject = GetValidProgram(context, program);
3340 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003341 {
3342 return false;
3343 }
3344
Jamie Madill0063c512014-08-25 15:47:53 -04003345 if (!programObject || !programObject->isLinked())
3346 {
Jamie Madill437fa652016-05-03 15:13:24 -04003347 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003348 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003349 }
3350
Geoff Lang7dd2e102014-11-10 15:19:26 -05003351 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003352 {
Jamie Madill437fa652016-05-03 15:13:24 -04003353 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003354 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003355 }
3356
Jamie Madill0063c512014-08-25 15:47:53 -04003357 return true;
3358}
3359
Geoff Langb1196682014-07-23 13:47:29 -04003360bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003361{
3362 return ValidateGetUniformBase(context, program, location);
3363}
3364
Geoff Langb1196682014-07-23 13:47:29 -04003365bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003366{
Jamie Madill78f41802014-08-25 15:47:55 -04003367 return ValidateGetUniformBase(context, program, location);
3368}
3369
Geoff Langf41d0ee2016-10-07 13:04:23 -04003370static bool ValidateSizedGetUniform(Context *context,
3371 GLuint program,
3372 GLint location,
3373 GLsizei bufSize,
3374 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003375{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003376 if (length)
3377 {
3378 *length = 0;
3379 }
3380
Jamie Madill78f41802014-08-25 15:47:55 -04003381 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003382 {
Jamie Madill78f41802014-08-25 15:47:55 -04003383 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003384 }
3385
Geoff Langf41d0ee2016-10-07 13:04:23 -04003386 if (bufSize < 0)
3387 {
3388 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3389 return false;
3390 }
3391
Jamie Madilla502c742014-08-28 17:19:13 -04003392 gl::Program *programObject = context->getProgram(program);
3393 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003394
Jamie Madill78f41802014-08-25 15:47:55 -04003395 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003396 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3397 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003398 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003399 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003400 context->handleError(
3401 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003402 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003403 }
3404
Geoff Langf41d0ee2016-10-07 13:04:23 -04003405 if (length)
3406 {
3407 // Cast is safe because of comparison to bufSize.
3408 *length = static_cast<GLsizei>(requiredBytes);
3409 }
3410
Jamie Madill0063c512014-08-25 15:47:53 -04003411 return true;
3412}
3413
Geoff Langb1196682014-07-23 13:47:29 -04003414bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003415{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003416 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003417}
3418
Geoff Langb1196682014-07-23 13:47:29 -04003419bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003420{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003421 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3422}
3423
3424bool ValidateGetUniformfvRobustANGLE(Context *context,
3425 GLuint program,
3426 GLint location,
3427 GLsizei bufSize,
3428 GLsizei *length,
3429 GLfloat *params)
3430{
3431 if (!ValidateRobustEntryPoint(context, bufSize))
3432 {
3433 return false;
3434 }
3435
3436 // bufSize is validated in ValidateSizedGetUniform
3437 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3438}
3439
3440bool ValidateGetUniformivRobustANGLE(Context *context,
3441 GLuint program,
3442 GLint location,
3443 GLsizei bufSize,
3444 GLsizei *length,
3445 GLint *params)
3446{
3447 if (!ValidateRobustEntryPoint(context, bufSize))
3448 {
3449 return false;
3450 }
3451
3452 // bufSize is validated in ValidateSizedGetUniform
3453 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3454}
3455
3456bool ValidateGetUniformuivRobustANGLE(Context *context,
3457 GLuint program,
3458 GLint location,
3459 GLsizei bufSize,
3460 GLsizei *length,
3461 GLuint *params)
3462{
3463 if (!ValidateRobustEntryPoint(context, bufSize))
3464 {
3465 return false;
3466 }
3467
3468 if (context->getClientMajorVersion() < 3)
3469 {
3470 context->handleError(
3471 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3472 return false;
3473 }
3474
3475 // bufSize is validated in ValidateSizedGetUniform
3476 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003477}
3478
Austin Kinross08332632015-05-05 13:35:47 -07003479bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3480 const GLenum *attachments, bool defaultFramebuffer)
3481{
3482 if (numAttachments < 0)
3483 {
Jamie Madill437fa652016-05-03 15:13:24 -04003484 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003485 return false;
3486 }
3487
3488 for (GLsizei i = 0; i < numAttachments; ++i)
3489 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003490 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003491 {
3492 if (defaultFramebuffer)
3493 {
Jamie Madill437fa652016-05-03 15:13:24 -04003494 context->handleError(Error(
3495 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003496 return false;
3497 }
3498
3499 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3500 {
Jamie Madill437fa652016-05-03 15:13:24 -04003501 context->handleError(Error(GL_INVALID_OPERATION,
3502 "Requested color attachment is greater than the maximum "
3503 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003504 return false;
3505 }
3506 }
3507 else
3508 {
3509 switch (attachments[i])
3510 {
3511 case GL_DEPTH_ATTACHMENT:
3512 case GL_STENCIL_ATTACHMENT:
3513 case GL_DEPTH_STENCIL_ATTACHMENT:
3514 if (defaultFramebuffer)
3515 {
Jamie Madill437fa652016-05-03 15:13:24 -04003516 context->handleError(
3517 Error(GL_INVALID_ENUM,
3518 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003519 return false;
3520 }
3521 break;
3522 case GL_COLOR:
3523 case GL_DEPTH:
3524 case GL_STENCIL:
3525 if (!defaultFramebuffer)
3526 {
Jamie Madill437fa652016-05-03 15:13:24 -04003527 context->handleError(
3528 Error(GL_INVALID_ENUM,
3529 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003530 return false;
3531 }
3532 break;
3533 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003534 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003535 return false;
3536 }
3537 }
3538 }
3539
3540 return true;
3541}
3542
Austin Kinross6ee1e782015-05-29 17:05:37 -07003543bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3544{
3545 // Note that debug marker calls must not set error state
3546
3547 if (length < 0)
3548 {
3549 return false;
3550 }
3551
3552 if (marker == nullptr)
3553 {
3554 return false;
3555 }
3556
3557 return true;
3558}
3559
3560bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3561{
3562 // Note that debug marker calls must not set error state
3563
3564 if (length < 0)
3565 {
3566 return false;
3567 }
3568
3569 if (length > 0 && marker == nullptr)
3570 {
3571 return false;
3572 }
3573
3574 return true;
3575}
3576
Geoff Langdcab33b2015-07-21 13:03:16 -04003577bool ValidateEGLImageTargetTexture2DOES(Context *context,
3578 egl::Display *display,
3579 GLenum target,
3580 egl::Image *image)
3581{
Geoff Langa8406172015-07-21 16:53:39 -04003582 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3583 {
Jamie Madill437fa652016-05-03 15:13:24 -04003584 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003585 return false;
3586 }
3587
3588 switch (target)
3589 {
3590 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003591 if (!context->getExtensions().eglImage)
3592 {
3593 context->handleError(Error(
3594 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3595 }
3596 break;
3597
3598 case GL_TEXTURE_EXTERNAL_OES:
3599 if (!context->getExtensions().eglImageExternal)
3600 {
3601 context->handleError(Error(
3602 GL_INVALID_ENUM,
3603 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3604 }
Geoff Langa8406172015-07-21 16:53:39 -04003605 break;
3606
3607 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003608 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003609 return false;
3610 }
3611
3612 if (!display->isValidImage(image))
3613 {
Jamie Madill437fa652016-05-03 15:13:24 -04003614 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003615 return false;
3616 }
3617
3618 if (image->getSamples() > 0)
3619 {
Jamie Madill437fa652016-05-03 15:13:24 -04003620 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003621 "cannot create a 2D texture from a multisampled EGL image."));
3622 return false;
3623 }
3624
Jamie Madilla3944d42016-07-22 22:13:26 -04003625 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003626 if (!textureCaps.texturable)
3627 {
Jamie Madill437fa652016-05-03 15:13:24 -04003628 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003629 "EGL image internal format is not supported as a texture."));
3630 return false;
3631 }
3632
Geoff Langdcab33b2015-07-21 13:03:16 -04003633 return true;
3634}
3635
3636bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3637 egl::Display *display,
3638 GLenum target,
3639 egl::Image *image)
3640{
Geoff Langa8406172015-07-21 16:53:39 -04003641 if (!context->getExtensions().eglImage)
3642 {
Jamie Madill437fa652016-05-03 15:13:24 -04003643 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003644 return false;
3645 }
3646
3647 switch (target)
3648 {
3649 case GL_RENDERBUFFER:
3650 break;
3651
3652 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003653 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003654 return false;
3655 }
3656
3657 if (!display->isValidImage(image))
3658 {
Jamie Madill437fa652016-05-03 15:13:24 -04003659 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003660 return false;
3661 }
3662
Jamie Madilla3944d42016-07-22 22:13:26 -04003663 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003664 if (!textureCaps.renderable)
3665 {
Jamie Madill437fa652016-05-03 15:13:24 -04003666 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003667 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3668 return false;
3669 }
3670
Geoff Langdcab33b2015-07-21 13:03:16 -04003671 return true;
3672}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003673
3674bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3675{
Geoff Lang36167ab2015-12-07 10:27:14 -05003676 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003677 {
3678 // The default VAO should always exist
3679 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003680 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003681 return false;
3682 }
3683
3684 return true;
3685}
3686
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003687bool ValidateLinkProgram(Context *context, GLuint program)
3688{
3689 if (context->hasActiveTransformFeedback(program))
3690 {
3691 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003692 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003693 "Cannot link program while program is associated with an active "
3694 "transform feedback object."));
3695 return false;
3696 }
3697 return true;
3698}
3699
Geoff Langc5629752015-12-07 16:29:04 -05003700bool ValidateProgramBinaryBase(Context *context,
3701 GLuint program,
3702 GLenum binaryFormat,
3703 const void *binary,
3704 GLint length)
3705{
3706 Program *programObject = GetValidProgram(context, program);
3707 if (programObject == nullptr)
3708 {
3709 return false;
3710 }
3711
3712 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3713 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3714 programBinaryFormats.end())
3715 {
Jamie Madill437fa652016-05-03 15:13:24 -04003716 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003717 return false;
3718 }
3719
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003720 if (context->hasActiveTransformFeedback(program))
3721 {
3722 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003723 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003724 "Cannot change program binary while program is associated with "
3725 "an active transform feedback object."));
3726 return false;
3727 }
3728
Geoff Langc5629752015-12-07 16:29:04 -05003729 return true;
3730}
3731
3732bool ValidateGetProgramBinaryBase(Context *context,
3733 GLuint program,
3734 GLsizei bufSize,
3735 GLsizei *length,
3736 GLenum *binaryFormat,
3737 void *binary)
3738{
3739 Program *programObject = GetValidProgram(context, program);
3740 if (programObject == nullptr)
3741 {
3742 return false;
3743 }
3744
3745 if (!programObject->isLinked())
3746 {
Jamie Madill437fa652016-05-03 15:13:24 -04003747 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003748 return false;
3749 }
3750
3751 return true;
3752}
Jamie Madillc29968b2016-01-20 11:17:23 -05003753
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003754bool ValidateUseProgram(Context *context, GLuint program)
3755{
3756 if (program != 0)
3757 {
3758 Program *programObject = context->getProgram(program);
3759 if (!programObject)
3760 {
3761 // ES 3.1.0 section 7.3 page 72
3762 if (context->getShader(program))
3763 {
Jamie Madill437fa652016-05-03 15:13:24 -04003764 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003765 Error(GL_INVALID_OPERATION,
3766 "Attempted to use a single shader instead of a shader program."));
3767 return false;
3768 }
3769 else
3770 {
Jamie Madill437fa652016-05-03 15:13:24 -04003771 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003772 return false;
3773 }
3774 }
3775 if (!programObject->isLinked())
3776 {
Jamie Madill437fa652016-05-03 15:13:24 -04003777 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003778 return false;
3779 }
3780 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003781 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003782 {
3783 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003784 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003785 Error(GL_INVALID_OPERATION,
3786 "Cannot change active program while transform feedback is unpaused."));
3787 return false;
3788 }
3789
3790 return true;
3791}
3792
Jamie Madillc29968b2016-01-20 11:17:23 -05003793bool ValidateCopyTexImage2D(ValidationContext *context,
3794 GLenum target,
3795 GLint level,
3796 GLenum internalformat,
3797 GLint x,
3798 GLint y,
3799 GLsizei width,
3800 GLsizei height,
3801 GLint border)
3802{
Martin Radev1be913c2016-07-11 17:59:16 +03003803 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003804 {
3805 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3806 0, x, y, width, height, border);
3807 }
3808
Martin Radev1be913c2016-07-11 17:59:16 +03003809 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003810 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3811 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003812}
Jamie Madillc29968b2016-01-20 11:17:23 -05003813
3814bool ValidateFramebufferRenderbuffer(Context *context,
3815 GLenum target,
3816 GLenum attachment,
3817 GLenum renderbuffertarget,
3818 GLuint renderbuffer)
3819{
3820 if (!ValidFramebufferTarget(target) ||
3821 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3822 {
Jamie Madill437fa652016-05-03 15:13:24 -04003823 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003824 return false;
3825 }
3826
3827 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3828 renderbuffertarget, renderbuffer);
3829}
3830
3831bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3832{
3833 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3834 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3835 {
Jamie Madill437fa652016-05-03 15:13:24 -04003836 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003837 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3838 return false;
3839 }
3840
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003841 ASSERT(context->getGLState().getDrawFramebuffer());
3842 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003843 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3844
3845 // This should come first before the check for the default frame buffer
3846 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3847 // rather than INVALID_OPERATION
3848 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3849 {
3850 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3851
3852 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003853 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3854 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003855 {
3856 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003857 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3858 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3859 // 3.1 is still a bit ambiguous about the error, but future specs are
3860 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003861 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003862 return false;
3863 }
3864 else if (bufs[colorAttachment] >= maxColorAttachment)
3865 {
Jamie Madill437fa652016-05-03 15:13:24 -04003866 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003867 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003868 return false;
3869 }
3870 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3871 frameBufferId != 0)
3872 {
3873 // INVALID_OPERATION-GL is bound to buffer and ith argument
3874 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003875 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003876 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3877 return false;
3878 }
3879 }
3880
3881 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3882 // and n is not 1 or bufs is bound to value other than BACK and NONE
3883 if (frameBufferId == 0)
3884 {
3885 if (n != 1)
3886 {
Jamie Madill437fa652016-05-03 15:13:24 -04003887 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003888 "n must be 1 when GL is bound to the default framebuffer"));
3889 return false;
3890 }
3891
3892 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3893 {
Jamie Madill437fa652016-05-03 15:13:24 -04003894 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003895 GL_INVALID_OPERATION,
3896 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3897 return false;
3898 }
3899 }
3900
3901 return true;
3902}
3903
3904bool ValidateCopyTexSubImage2D(Context *context,
3905 GLenum target,
3906 GLint level,
3907 GLint xoffset,
3908 GLint yoffset,
3909 GLint x,
3910 GLint y,
3911 GLsizei width,
3912 GLsizei height)
3913{
Martin Radev1be913c2016-07-11 17:59:16 +03003914 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003915 {
3916 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3917 yoffset, x, y, width, height, 0);
3918 }
3919
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003920 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3921 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003922}
3923
Geoff Lang496c02d2016-10-20 11:38:11 -07003924bool ValidateGetBufferPointervBase(Context *context,
3925 GLenum target,
3926 GLenum pname,
3927 GLsizei *length,
3928 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003929{
Geoff Lang496c02d2016-10-20 11:38:11 -07003930 if (length)
3931 {
3932 *length = 0;
3933 }
3934
3935 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3936 {
3937 context->handleError(
3938 Error(GL_INVALID_OPERATION,
3939 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
3940 return false;
3941 }
3942
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 if (!ValidBufferTarget(context, target))
3944 {
Jamie Madill437fa652016-05-03 15:13:24 -04003945 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003946 return false;
3947 }
3948
Geoff Lang496c02d2016-10-20 11:38:11 -07003949 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003951 case GL_BUFFER_MAP_POINTER:
3952 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003953
Geoff Lang496c02d2016-10-20 11:38:11 -07003954 default:
3955 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
3956 return false;
3957 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003958
3959 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3960 // target bound to zero generate an INVALID_OPERATION error."
3961 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003962 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003963 {
Jamie Madill437fa652016-05-03 15:13:24 -04003964 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003965 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3966 return false;
3967 }
3968
Geoff Lang496c02d2016-10-20 11:38:11 -07003969 if (length)
3970 {
3971 *length = 1;
3972 }
3973
Olli Etuaho4f667482016-03-30 15:56:35 +03003974 return true;
3975}
3976
3977bool ValidateUnmapBufferBase(Context *context, GLenum target)
3978{
3979 if (!ValidBufferTarget(context, target))
3980 {
Jamie Madill437fa652016-05-03 15:13:24 -04003981 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003982 return false;
3983 }
3984
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003985 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003986
3987 if (buffer == nullptr || !buffer->isMapped())
3988 {
Jamie Madill437fa652016-05-03 15:13:24 -04003989 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003990 return false;
3991 }
3992
3993 return true;
3994}
3995
3996bool ValidateMapBufferRangeBase(Context *context,
3997 GLenum target,
3998 GLintptr offset,
3999 GLsizeiptr length,
4000 GLbitfield access)
4001{
4002 if (!ValidBufferTarget(context, target))
4003 {
Jamie Madill437fa652016-05-03 15:13:24 -04004004 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004005 return false;
4006 }
4007
4008 if (offset < 0 || length < 0)
4009 {
Jamie Madill437fa652016-05-03 15:13:24 -04004010 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004011 return false;
4012 }
4013
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004014 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004015
4016 if (!buffer)
4017 {
Jamie Madill437fa652016-05-03 15:13:24 -04004018 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004019 return false;
4020 }
4021
4022 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004023 CheckedNumeric<size_t> checkedOffset(offset);
4024 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004025
Jamie Madille2e406c2016-06-02 13:04:10 -04004026 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004027 {
Jamie Madill437fa652016-05-03 15:13:24 -04004028 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004029 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4030 return false;
4031 }
4032
4033 // Check for invalid bits in the mask
4034 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4035 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4036 GL_MAP_UNSYNCHRONIZED_BIT;
4037
4038 if (access & ~(allAccessBits))
4039 {
Jamie Madill437fa652016-05-03 15:13:24 -04004040 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004041 return false;
4042 }
4043
4044 if (length == 0)
4045 {
Jamie Madill437fa652016-05-03 15:13:24 -04004046 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004047 return false;
4048 }
4049
4050 if (buffer->isMapped())
4051 {
Jamie Madill437fa652016-05-03 15:13:24 -04004052 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004053 return false;
4054 }
4055
4056 // Check for invalid bit combinations
4057 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4058 {
Jamie Madill437fa652016-05-03 15:13:24 -04004059 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004060 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4061 return false;
4062 }
4063
4064 GLbitfield writeOnlyBits =
4065 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4066
4067 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4068 {
Jamie Madill437fa652016-05-03 15:13:24 -04004069 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004070 "Invalid access bits when mapping buffer for reading: 0x%X.",
4071 access));
4072 return false;
4073 }
4074
4075 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4076 {
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004078 GL_INVALID_OPERATION,
4079 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4080 return false;
4081 }
4082 return true;
4083}
4084
4085bool ValidateFlushMappedBufferRangeBase(Context *context,
4086 GLenum target,
4087 GLintptr offset,
4088 GLsizeiptr length)
4089{
4090 if (offset < 0 || length < 0)
4091 {
Jamie Madill437fa652016-05-03 15:13:24 -04004092 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004093 return false;
4094 }
4095
4096 if (!ValidBufferTarget(context, target))
4097 {
Jamie Madill437fa652016-05-03 15:13:24 -04004098 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004099 return false;
4100 }
4101
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004102 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004103
4104 if (buffer == nullptr)
4105 {
Jamie Madill437fa652016-05-03 15:13:24 -04004106 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004107 return false;
4108 }
4109
4110 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4111 {
Jamie Madill437fa652016-05-03 15:13:24 -04004112 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004113 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4114 return false;
4115 }
4116
4117 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004118 CheckedNumeric<size_t> checkedOffset(offset);
4119 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004120
Jamie Madille2e406c2016-06-02 13:04:10 -04004121 if (!checkedSize.IsValid() ||
4122 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004123 {
Jamie Madill437fa652016-05-03 15:13:24 -04004124 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004125 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4126 return false;
4127 }
4128
4129 return true;
4130}
4131
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004132bool ValidateGenerateMipmap(Context *context, GLenum target)
4133{
4134 if (!ValidTextureTarget(context, target))
4135 {
4136 context->handleError(Error(GL_INVALID_ENUM));
4137 return false;
4138 }
4139
4140 Texture *texture = context->getTargetTexture(target);
4141
4142 if (texture == nullptr)
4143 {
4144 context->handleError(Error(GL_INVALID_OPERATION));
4145 return false;
4146 }
4147
4148 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4149
4150 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4151 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4152 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4153 {
4154 context->handleError(Error(GL_INVALID_OPERATION));
4155 return false;
4156 }
4157
Jamie Madilla3944d42016-07-22 22:13:26 -04004158 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4159 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4160 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004161
4162 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4163 // unsized formats or that are color renderable and filterable. Since we do not track if
4164 // the texture was created with sized or unsized format (only sized formats are stored),
4165 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4166 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4167 // textures since they're the only texture format that can be created with unsized formats
4168 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4169 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004170 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4171 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004172 {
4173 context->handleError(Error(GL_INVALID_OPERATION));
4174 return false;
4175 }
4176
4177 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004178 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004179 {
4180 context->handleError(Error(GL_INVALID_OPERATION));
4181 return false;
4182 }
4183
4184 // Non-power of 2 ES2 check
4185 if (!context->getExtensions().textureNPOT &&
4186 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4187 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4188 {
Martin Radev1be913c2016-07-11 17:59:16 +03004189 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004190 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
4191 context->handleError(Error(GL_INVALID_OPERATION));
4192 return false;
4193 }
4194
4195 // Cube completeness check
4196 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4197 {
4198 context->handleError(Error(GL_INVALID_OPERATION));
4199 return false;
4200 }
4201
4202 return true;
4203}
4204
Olli Etuaho41997e72016-03-10 13:38:39 +02004205bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4206{
4207 return ValidateGenOrDelete(context, n);
4208}
4209
4210bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4211{
4212 return ValidateGenOrDelete(context, n);
4213}
4214
4215bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4216{
4217 return ValidateGenOrDelete(context, n);
4218}
4219
4220bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4221{
4222 return ValidateGenOrDelete(context, n);
4223}
4224
4225bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4226{
4227 return ValidateGenOrDelete(context, n);
4228}
4229
4230bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4231{
4232 return ValidateGenOrDelete(context, n);
4233}
4234
4235bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4236{
4237 return ValidateGenOrDelete(context, n);
4238}
4239
4240bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4241{
4242 return ValidateGenOrDelete(context, n);
4243}
4244
4245bool ValidateGenOrDelete(Context *context, GLint n)
4246{
4247 if (n < 0)
4248 {
Jamie Madill437fa652016-05-03 15:13:24 -04004249 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004250 return false;
4251 }
4252 return true;
4253}
4254
Geoff Langf41a7152016-09-19 15:11:17 -04004255bool ValidateEnable(Context *context, GLenum cap)
4256{
4257 if (!ValidCap(context, cap, false))
4258 {
4259 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4260 return false;
4261 }
4262
4263 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4264 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4265 {
4266 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4267 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4268
4269 // We also output an error message to the debugger window if tracing is active, so that
4270 // developers can see the error message.
4271 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004272 return false;
4273 }
4274
4275 return true;
4276}
4277
4278bool ValidateDisable(Context *context, GLenum cap)
4279{
4280 if (!ValidCap(context, cap, false))
4281 {
4282 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4283 return false;
4284 }
4285
4286 return true;
4287}
4288
4289bool ValidateIsEnabled(Context *context, GLenum cap)
4290{
4291 if (!ValidCap(context, cap, true))
4292 {
4293 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4294 return false;
4295 }
4296
4297 return true;
4298}
4299
Geoff Langff5b2d52016-09-07 11:32:23 -04004300bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4301{
4302 if (!context->getExtensions().robustClientMemory)
4303 {
4304 context->handleError(
4305 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4306 return false;
4307 }
4308
4309 if (bufSize < 0)
4310 {
4311 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4312 return false;
4313 }
4314
4315 return true;
4316}
4317
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004318bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4319{
4320 if (bufSize < numParams)
4321 {
4322 context->handleError(Error(GL_INVALID_OPERATION,
4323 "%u parameters are required but %i were provided.", numParams,
4324 bufSize));
4325 return false;
4326 }
4327
4328 return true;
4329}
4330
Geoff Langff5b2d52016-09-07 11:32:23 -04004331bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4332 GLenum target,
4333 GLenum attachment,
4334 GLenum pname,
4335 GLsizei *numParams)
4336{
4337 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4338 *numParams = 1;
4339
4340 if (!ValidFramebufferTarget(target))
4341 {
4342 context->handleError(Error(GL_INVALID_ENUM));
4343 return false;
4344 }
4345
4346 int clientVersion = context->getClientMajorVersion();
4347
4348 switch (pname)
4349 {
4350 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4351 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4352 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4353 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4354 break;
4355
4356 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4357 if (clientVersion < 3 && !context->getExtensions().sRGB)
4358 {
4359 context->handleError(Error(GL_INVALID_ENUM));
4360 return false;
4361 }
4362 break;
4363
4364 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4365 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4366 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4367 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4368 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4369 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4370 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4371 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4372 if (clientVersion < 3)
4373 {
4374 context->handleError(Error(GL_INVALID_ENUM));
4375 return false;
4376 }
4377 break;
4378
4379 default:
4380 context->handleError(Error(GL_INVALID_ENUM));
4381 return false;
4382 }
4383
4384 // Determine if the attachment is a valid enum
4385 switch (attachment)
4386 {
4387 case GL_BACK:
4388 case GL_FRONT:
4389 case GL_DEPTH:
4390 case GL_STENCIL:
4391 case GL_DEPTH_STENCIL_ATTACHMENT:
4392 if (clientVersion < 3)
4393 {
4394 context->handleError(Error(GL_INVALID_ENUM));
4395 return false;
4396 }
4397 break;
4398
4399 case GL_DEPTH_ATTACHMENT:
4400 case GL_STENCIL_ATTACHMENT:
4401 break;
4402
4403 default:
4404 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4405 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4406 {
4407 context->handleError(Error(GL_INVALID_ENUM));
4408 return false;
4409 }
4410 break;
4411 }
4412
4413 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4414 ASSERT(framebuffer);
4415
4416 if (framebuffer->id() == 0)
4417 {
4418 if (clientVersion < 3)
4419 {
4420 context->handleError(Error(GL_INVALID_OPERATION));
4421 return false;
4422 }
4423
4424 switch (attachment)
4425 {
4426 case GL_BACK:
4427 case GL_DEPTH:
4428 case GL_STENCIL:
4429 break;
4430
4431 default:
4432 context->handleError(Error(GL_INVALID_OPERATION));
4433 return false;
4434 }
4435 }
4436 else
4437 {
4438 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4439 {
4440 // Valid attachment query
4441 }
4442 else
4443 {
4444 switch (attachment)
4445 {
4446 case GL_DEPTH_ATTACHMENT:
4447 case GL_STENCIL_ATTACHMENT:
4448 break;
4449
4450 case GL_DEPTH_STENCIL_ATTACHMENT:
4451 if (!framebuffer->hasValidDepthStencil())
4452 {
4453 context->handleError(Error(GL_INVALID_OPERATION));
4454 return false;
4455 }
4456 break;
4457
4458 default:
4459 context->handleError(Error(GL_INVALID_OPERATION));
4460 return false;
4461 }
4462 }
4463 }
4464
4465 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4466 if (attachmentObject)
4467 {
4468 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4469 attachmentObject->type() == GL_TEXTURE ||
4470 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4471
4472 switch (pname)
4473 {
4474 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4475 if (attachmentObject->type() != GL_RENDERBUFFER &&
4476 attachmentObject->type() != GL_TEXTURE)
4477 {
4478 context->handleError(Error(GL_INVALID_ENUM));
4479 return false;
4480 }
4481 break;
4482
4483 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4484 if (attachmentObject->type() != GL_TEXTURE)
4485 {
4486 context->handleError(Error(GL_INVALID_ENUM));
4487 return false;
4488 }
4489 break;
4490
4491 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4492 if (attachmentObject->type() != GL_TEXTURE)
4493 {
4494 context->handleError(Error(GL_INVALID_ENUM));
4495 return false;
4496 }
4497 break;
4498
4499 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4500 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4501 {
4502 context->handleError(Error(GL_INVALID_OPERATION));
4503 return false;
4504 }
4505 break;
4506
4507 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4508 if (attachmentObject->type() != GL_TEXTURE)
4509 {
4510 context->handleError(Error(GL_INVALID_ENUM));
4511 return false;
4512 }
4513 break;
4514
4515 default:
4516 break;
4517 }
4518 }
4519 else
4520 {
4521 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4522 // is NONE, then querying any other pname will generate INVALID_ENUM.
4523
4524 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4525 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4526 // INVALID_OPERATION for all other pnames
4527
4528 switch (pname)
4529 {
4530 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4531 break;
4532
4533 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4534 if (clientVersion < 3)
4535 {
4536 context->handleError(Error(GL_INVALID_ENUM));
4537 return false;
4538 }
4539 break;
4540
4541 default:
4542 if (clientVersion < 3)
4543 {
4544 context->handleError(Error(GL_INVALID_ENUM));
4545 return false;
4546 }
4547 else
4548 {
4549 context->handleError(Error(GL_INVALID_OPERATION));
4550 return false;
4551 }
4552 }
4553 }
4554
4555 return true;
4556}
4557
4558bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4559 GLenum target,
4560 GLenum attachment,
4561 GLenum pname,
4562 GLsizei bufSize,
4563 GLsizei *numParams)
4564{
4565 if (!ValidateRobustEntryPoint(context, bufSize))
4566 {
4567 return false;
4568 }
4569
4570 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4571 {
4572 return false;
4573 }
4574
4575 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4576 {
4577 return false;
4578 }
4579
4580 return true;
4581}
4582
4583bool ValidateGetBufferParameteriv(ValidationContext *context,
4584 GLenum target,
4585 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004586 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004587{
Geoff Langebebe1c2016-10-14 12:01:31 -04004588 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004589}
4590
4591bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4592 GLenum target,
4593 GLenum pname,
4594 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004595 GLsizei *length,
4596 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004597{
4598 if (!ValidateRobustEntryPoint(context, bufSize))
4599 {
4600 return false;
4601 }
4602
Geoff Langebebe1c2016-10-14 12:01:31 -04004603 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004604 {
4605 return false;
4606 }
4607
Geoff Langebebe1c2016-10-14 12:01:31 -04004608 if (!ValidateRobustBufferSize(context, bufSize, *length))
4609 {
4610 return false;
4611 }
4612
4613 return true;
4614}
4615
4616bool ValidateGetBufferParameteri64v(ValidationContext *context,
4617 GLenum target,
4618 GLenum pname,
4619 GLint64 *params)
4620{
4621 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4622}
4623
4624bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4625 GLenum target,
4626 GLenum pname,
4627 GLsizei bufSize,
4628 GLsizei *length,
4629 GLint64 *params)
4630{
4631 if (!ValidateRobustEntryPoint(context, bufSize))
4632 {
4633 return false;
4634 }
4635
4636 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4637 {
4638 return false;
4639 }
4640
4641 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004642 {
4643 return false;
4644 }
4645
4646 return true;
4647}
4648
4649bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4650{
4651 // Currently, all GetProgramiv queries return 1 parameter
4652 *numParams = 1;
4653
4654 Program *programObject = GetValidProgram(context, program);
4655 if (!programObject)
4656 {
4657 return false;
4658 }
4659
4660 switch (pname)
4661 {
4662 case GL_DELETE_STATUS:
4663 case GL_LINK_STATUS:
4664 case GL_VALIDATE_STATUS:
4665 case GL_INFO_LOG_LENGTH:
4666 case GL_ATTACHED_SHADERS:
4667 case GL_ACTIVE_ATTRIBUTES:
4668 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4669 case GL_ACTIVE_UNIFORMS:
4670 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4671 break;
4672
4673 case GL_PROGRAM_BINARY_LENGTH:
4674 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4675 {
4676 context->handleError(Error(GL_INVALID_ENUM,
4677 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4678 "GL_OES_get_program_binary or ES 3.0."));
4679 return false;
4680 }
4681 break;
4682
4683 case GL_ACTIVE_UNIFORM_BLOCKS:
4684 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4685 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4686 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4687 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4688 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4689 if (context->getClientMajorVersion() < 3)
4690 {
4691 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4692 return false;
4693 }
4694 break;
4695
4696 default:
4697 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4698 return false;
4699 }
4700
4701 return true;
4702}
4703
4704bool ValidateGetProgramivRobustANGLE(Context *context,
4705 GLuint program,
4706 GLenum pname,
4707 GLsizei bufSize,
4708 GLsizei *numParams)
4709{
4710 if (!ValidateRobustEntryPoint(context, bufSize))
4711 {
4712 return false;
4713 }
4714
4715 if (!ValidateGetProgramiv(context, program, pname, numParams))
4716 {
4717 return false;
4718 }
4719
4720 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4721 {
4722 return false;
4723 }
4724
4725 return true;
4726}
4727
Geoff Lang740d9022016-10-07 11:20:52 -04004728bool ValidateGetRenderbufferParameteriv(Context *context,
4729 GLenum target,
4730 GLenum pname,
4731 GLint *params)
4732{
4733 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4734}
4735
4736bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4737 GLenum target,
4738 GLenum pname,
4739 GLsizei bufSize,
4740 GLsizei *length,
4741 GLint *params)
4742{
4743 if (!ValidateRobustEntryPoint(context, bufSize))
4744 {
4745 return false;
4746 }
4747
4748 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4749 {
4750 return false;
4751 }
4752
4753 if (!ValidateRobustBufferSize(context, bufSize, *length))
4754 {
4755 return false;
4756 }
4757
4758 return true;
4759}
4760
Geoff Langd7d0ed32016-10-07 11:33:51 -04004761bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4762{
4763 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4764}
4765
4766bool ValidateGetShaderivRobustANGLE(Context *context,
4767 GLuint shader,
4768 GLenum pname,
4769 GLsizei bufSize,
4770 GLsizei *length,
4771 GLint *params)
4772{
4773 if (!ValidateRobustEntryPoint(context, bufSize))
4774 {
4775 return false;
4776 }
4777
4778 if (!ValidateGetShaderivBase(context, shader, pname, length))
4779 {
4780 return false;
4781 }
4782
4783 if (!ValidateRobustBufferSize(context, bufSize, *length))
4784 {
4785 return false;
4786 }
4787
4788 return true;
4789}
4790
Geoff Langc1984ed2016-10-07 12:41:00 -04004791bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4792{
4793 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4794}
4795
4796bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4797 GLenum target,
4798 GLenum pname,
4799 GLsizei bufSize,
4800 GLsizei *length,
4801 GLfloat *params)
4802{
4803 if (!ValidateRobustEntryPoint(context, bufSize))
4804 {
4805 return false;
4806 }
4807
4808 if (!ValidateGetTexParameterBase(context, target, pname, length))
4809 {
4810 return false;
4811 }
4812
4813 if (!ValidateRobustBufferSize(context, bufSize, *length))
4814 {
4815 return false;
4816 }
4817
4818 return true;
4819}
4820
4821bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4822{
4823 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4824}
4825
4826bool ValidateGetTexParameterivRobustANGLE(Context *context,
4827 GLenum target,
4828 GLenum pname,
4829 GLsizei bufSize,
4830 GLsizei *length,
4831 GLint *params)
4832{
4833 if (!ValidateRobustEntryPoint(context, bufSize))
4834 {
4835 return false;
4836 }
4837
4838 if (!ValidateGetTexParameterBase(context, target, pname, length))
4839 {
4840 return false;
4841 }
4842
4843 if (!ValidateRobustBufferSize(context, bufSize, *length))
4844 {
4845 return false;
4846 }
4847
4848 return true;
4849}
4850
4851bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4852{
4853 return ValidateTexParameterBase(context, target, pname, -1, &param);
4854}
4855
4856bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4857{
4858 return ValidateTexParameterBase(context, target, pname, -1, params);
4859}
4860
4861bool ValidateTexParameterfvRobustANGLE(Context *context,
4862 GLenum target,
4863 GLenum pname,
4864 GLsizei bufSize,
4865 const GLfloat *params)
4866{
4867 if (!ValidateRobustEntryPoint(context, bufSize))
4868 {
4869 return false;
4870 }
4871
4872 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4873}
4874
4875bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4876{
4877 return ValidateTexParameterBase(context, target, pname, -1, &param);
4878}
4879
4880bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4881{
4882 return ValidateTexParameterBase(context, target, pname, -1, params);
4883}
4884
4885bool ValidateTexParameterivRobustANGLE(Context *context,
4886 GLenum target,
4887 GLenum pname,
4888 GLsizei bufSize,
4889 const GLint *params)
4890{
4891 if (!ValidateRobustEntryPoint(context, bufSize))
4892 {
4893 return false;
4894 }
4895
4896 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4897}
4898
4899bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4900{
4901 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4902}
4903
4904bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4905 GLuint sampler,
4906 GLenum pname,
4907 GLuint bufSize,
4908 GLsizei *length,
4909 GLfloat *params)
4910{
4911 if (!ValidateRobustEntryPoint(context, bufSize))
4912 {
4913 return false;
4914 }
4915
4916 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4917 {
4918 return false;
4919 }
4920
4921 if (!ValidateRobustBufferSize(context, bufSize, *length))
4922 {
4923 return false;
4924 }
4925
4926 return true;
4927}
4928
4929bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4930{
4931 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4932}
4933
4934bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4935 GLuint sampler,
4936 GLenum pname,
4937 GLuint bufSize,
4938 GLsizei *length,
4939 GLint *params)
4940{
4941 if (!ValidateRobustEntryPoint(context, bufSize))
4942 {
4943 return false;
4944 }
4945
4946 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4947 {
4948 return false;
4949 }
4950
4951 if (!ValidateRobustBufferSize(context, bufSize, *length))
4952 {
4953 return false;
4954 }
4955
4956 return true;
4957}
4958
4959bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4960{
4961 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4962}
4963
4964bool ValidateSamplerParameterfv(Context *context,
4965 GLuint sampler,
4966 GLenum pname,
4967 const GLfloat *params)
4968{
4969 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4970}
4971
4972bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4973 GLuint sampler,
4974 GLenum pname,
4975 GLsizei bufSize,
4976 const GLfloat *params)
4977{
4978 if (!ValidateRobustEntryPoint(context, bufSize))
4979 {
4980 return false;
4981 }
4982
4983 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4984}
4985
4986bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4987{
4988 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4989}
4990
4991bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4992{
4993 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4994}
4995
4996bool ValidateSamplerParameterivRobustANGLE(Context *context,
4997 GLuint sampler,
4998 GLenum pname,
4999 GLsizei bufSize,
5000 const GLint *params)
5001{
5002 if (!ValidateRobustEntryPoint(context, bufSize))
5003 {
5004 return false;
5005 }
5006
5007 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5008}
5009
Geoff Lang0b031062016-10-13 14:30:04 -04005010bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5011{
5012 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5013}
5014
5015bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5016 GLuint index,
5017 GLenum pname,
5018 GLsizei bufSize,
5019 GLsizei *length,
5020 GLfloat *params)
5021{
5022 if (!ValidateRobustEntryPoint(context, bufSize))
5023 {
5024 return false;
5025 }
5026
5027 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5028 {
5029 return false;
5030 }
5031
5032 if (!ValidateRobustBufferSize(context, bufSize, *length))
5033 {
5034 return false;
5035 }
5036
5037 return true;
5038}
5039
5040bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5041{
5042 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5043}
5044
5045bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5046 GLuint index,
5047 GLenum pname,
5048 GLsizei bufSize,
5049 GLsizei *length,
5050 GLint *params)
5051{
5052 if (!ValidateRobustEntryPoint(context, bufSize))
5053 {
5054 return false;
5055 }
5056
5057 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5058 {
5059 return false;
5060 }
5061
5062 if (!ValidateRobustBufferSize(context, bufSize, *length))
5063 {
5064 return false;
5065 }
5066
5067 return true;
5068}
5069
5070bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5071{
5072 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5073}
5074
5075bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5076 GLuint index,
5077 GLenum pname,
5078 GLsizei bufSize,
5079 GLsizei *length,
5080 void **pointer)
5081{
5082 if (!ValidateRobustEntryPoint(context, bufSize))
5083 {
5084 return false;
5085 }
5086
5087 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5088 {
5089 return false;
5090 }
5091
5092 if (!ValidateRobustBufferSize(context, bufSize, *length))
5093 {
5094 return false;
5095 }
5096
5097 return true;
5098}
5099
5100bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5101{
5102 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5103}
5104
5105bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5106 GLuint index,
5107 GLenum pname,
5108 GLsizei bufSize,
5109 GLsizei *length,
5110 GLint *params)
5111{
5112 if (!ValidateRobustEntryPoint(context, bufSize))
5113 {
5114 return false;
5115 }
5116
5117 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5118 {
5119 return false;
5120 }
5121
5122 if (!ValidateRobustBufferSize(context, bufSize, *length))
5123 {
5124 return false;
5125 }
5126
5127 return true;
5128}
5129
5130bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5131{
5132 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5133}
5134
5135bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5136 GLuint index,
5137 GLenum pname,
5138 GLsizei bufSize,
5139 GLsizei *length,
5140 GLuint *params)
5141{
5142 if (!ValidateRobustEntryPoint(context, bufSize))
5143 {
5144 return false;
5145 }
5146
5147 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5148 {
5149 return false;
5150 }
5151
5152 if (!ValidateRobustBufferSize(context, bufSize, *length))
5153 {
5154 return false;
5155 }
5156
5157 return true;
5158}
5159
Geoff Lang6899b872016-10-14 11:30:13 -04005160bool ValidateGetActiveUniformBlockiv(Context *context,
5161 GLuint program,
5162 GLuint uniformBlockIndex,
5163 GLenum pname,
5164 GLint *params)
5165{
5166 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5167}
5168
5169bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5170 GLuint program,
5171 GLuint uniformBlockIndex,
5172 GLenum pname,
5173 GLsizei bufSize,
5174 GLsizei *length,
5175 GLint *params)
5176{
5177 if (!ValidateRobustEntryPoint(context, bufSize))
5178 {
5179 return false;
5180 }
5181
5182 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5183 {
5184 return false;
5185 }
5186
5187 if (!ValidateRobustBufferSize(context, bufSize, *length))
5188 {
5189 return false;
5190 }
5191
5192 return true;
5193}
5194
Geoff Lang0a9661f2016-10-20 10:59:20 -07005195bool ValidateGetInternalFormativ(Context *context,
5196 GLenum target,
5197 GLenum internalformat,
5198 GLenum pname,
5199 GLsizei bufSize,
5200 GLint *params)
5201{
5202 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5203 nullptr);
5204}
5205
5206bool ValidateGetInternalFormativRobustANGLE(Context *context,
5207 GLenum target,
5208 GLenum internalformat,
5209 GLenum pname,
5210 GLsizei bufSize,
5211 GLsizei *length,
5212 GLint *params)
5213{
5214 if (!ValidateRobustEntryPoint(context, bufSize))
5215 {
5216 return false;
5217 }
5218
5219 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5220 {
5221 return false;
5222 }
5223
5224 if (!ValidateRobustBufferSize(context, bufSize, *length))
5225 {
5226 return false;
5227 }
5228
5229 return true;
5230}
5231
Jamie Madillc29968b2016-01-20 11:17:23 -05005232} // namespace gl