blob: 4af40ca6abae36d84cadd538c64625640990fb45 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
165 default:
166 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500167 }
168}
169
Geoff Lang62fce5b2016-09-30 10:46:35 -0400170bool ValidateReadPixelsBase(ValidationContext *context,
171 GLint x,
172 GLint y,
173 GLsizei width,
174 GLsizei height,
175 GLenum format,
176 GLenum type,
177 GLsizei bufSize,
178 GLsizei *length,
179 GLvoid *pixels)
180{
181 if (length != nullptr)
182 {
183 *length = 0;
184 }
185
186 if (width < 0 || height < 0)
187 {
188 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
189 return false;
190 }
191
192 auto readFramebuffer = context->getGLState().getReadFramebuffer();
193
194 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
195 {
196 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
197 return false;
198 }
199
200 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
201 {
202 context->handleError(Error(GL_INVALID_OPERATION));
203 return false;
204 }
205
206 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
207 ASSERT(framebuffer);
208
209 if (framebuffer->getReadBufferState() == GL_NONE)
210 {
211 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
212 return false;
213 }
214
215 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
216 if (!readBuffer)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION));
219 return false;
220 }
221
222 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
223 GLenum currentType = framebuffer->getImplementationColorReadType();
224 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
225
226 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
227 bool validFormatTypeCombination =
228 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
229
230 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
231 {
232 context->handleError(Error(GL_INVALID_OPERATION));
233 return false;
234 }
235
236 // Check for pixel pack buffer related API errors
237 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
238 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
239 {
240 // ...the buffer object's data store is currently mapped.
241 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
242 return false;
243 }
244
245 // .. the data would be packed to the buffer object such that the memory writes required
246 // would exceed the data store size.
247 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
248 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
249 const gl::Extents size(width, height, 1);
250 const auto &pack = context->getGLState().getPackState();
251
252 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
253 if (endByteOrErr.isError())
254 {
255 context->handleError(endByteOrErr.getError());
256 return false;
257 }
258
259 size_t endByte = endByteOrErr.getResult();
260 if (bufSize >= 0)
261 {
262
263 if (static_cast<size_t>(bufSize) < endByte)
264 {
265 context->handleError(
266 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
267 return false;
268 }
269 }
270
271 if (pixelPackBuffer != nullptr)
272 {
273 CheckedNumeric<size_t> checkedEndByte(endByte);
274 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
275 checkedEndByte += checkedOffset;
276
277 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
278 {
279 // Overflow past the end of the buffer
280 context->handleError(
281 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
282 return false;
283 }
284 }
285
286 if (length != nullptr)
287 {
288 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
289 {
290 context->handleError(
291 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
292 return false;
293 }
294
295 *length = static_cast<GLsizei>(endByte);
296 }
297
298 return true;
299}
300
Geoff Lang740d9022016-10-07 11:20:52 -0400301bool ValidateGetRenderbufferParameterivBase(Context *context,
302 GLenum target,
303 GLenum pname,
304 GLsizei *length)
305{
306 if (length)
307 {
308 *length = 0;
309 }
310
311 if (target != GL_RENDERBUFFER)
312 {
313 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
314 return false;
315 }
316
317 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
318 if (renderbuffer == nullptr)
319 {
320 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
321 return false;
322 }
323
324 switch (pname)
325 {
326 case GL_RENDERBUFFER_WIDTH:
327 case GL_RENDERBUFFER_HEIGHT:
328 case GL_RENDERBUFFER_INTERNAL_FORMAT:
329 case GL_RENDERBUFFER_RED_SIZE:
330 case GL_RENDERBUFFER_GREEN_SIZE:
331 case GL_RENDERBUFFER_BLUE_SIZE:
332 case GL_RENDERBUFFER_ALPHA_SIZE:
333 case GL_RENDERBUFFER_DEPTH_SIZE:
334 case GL_RENDERBUFFER_STENCIL_SIZE:
335 break;
336
337 case GL_RENDERBUFFER_SAMPLES_ANGLE:
338 if (!context->getExtensions().framebufferMultisample)
339 {
340 context->handleError(
341 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
342 return false;
343 }
344 break;
345
346 default:
347 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
348 return false;
349 }
350
351 if (length)
352 {
353 *length = 1;
354 }
355 return true;
356}
357
Geoff Langd7d0ed32016-10-07 11:33:51 -0400358bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
359{
360 if (length)
361 {
362 *length = 0;
363 }
364
365 if (GetValidShader(context, shader) == nullptr)
366 {
367 return false;
368 }
369
370 switch (pname)
371 {
372 case GL_SHADER_TYPE:
373 case GL_DELETE_STATUS:
374 case GL_COMPILE_STATUS:
375 case GL_INFO_LOG_LENGTH:
376 case GL_SHADER_SOURCE_LENGTH:
377 break;
378
379 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
380 if (!context->getExtensions().translatedShaderSource)
381 {
382 context->handleError(
383 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
384 return false;
385 }
386 break;
387
388 default:
389 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
390 return false;
391 }
392
393 if (length)
394 {
395 *length = 1;
396 }
397 return true;
398}
399
Geoff Langc1984ed2016-10-07 12:41:00 -0400400bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
401{
402 if (length)
403 {
404 *length = 0;
405 }
406
407 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
408 {
409 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
410 return false;
411 }
412
413 if (context->getTargetTexture(target) == nullptr)
414 {
415 // Should only be possible for external textures
416 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
417 return false;
418 }
419
420 switch (pname)
421 {
422 case GL_TEXTURE_MAG_FILTER:
423 case GL_TEXTURE_MIN_FILTER:
424 case GL_TEXTURE_WRAP_S:
425 case GL_TEXTURE_WRAP_T:
426 break;
427
428 case GL_TEXTURE_USAGE_ANGLE:
429 if (!context->getExtensions().textureUsage)
430 {
431 context->handleError(
432 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
438 if (!context->getExtensions().textureFilterAnisotropic)
439 {
440 context->handleError(
441 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
442 return false;
443 }
444 break;
445
446 case GL_TEXTURE_IMMUTABLE_FORMAT:
447 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
448 {
449 context->handleError(
450 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
451 return false;
452 }
453 break;
454
455 case GL_TEXTURE_WRAP_R:
456 case GL_TEXTURE_IMMUTABLE_LEVELS:
457 case GL_TEXTURE_SWIZZLE_R:
458 case GL_TEXTURE_SWIZZLE_G:
459 case GL_TEXTURE_SWIZZLE_B:
460 case GL_TEXTURE_SWIZZLE_A:
461 case GL_TEXTURE_BASE_LEVEL:
462 case GL_TEXTURE_MAX_LEVEL:
463 case GL_TEXTURE_MIN_LOD:
464 case GL_TEXTURE_MAX_LOD:
465 case GL_TEXTURE_COMPARE_MODE:
466 case GL_TEXTURE_COMPARE_FUNC:
467 if (context->getClientMajorVersion() < 3)
468 {
469 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
470 return false;
471 }
472 break;
473
Geoff Lang81c6b572016-10-19 14:07:52 -0700474 case GL_TEXTURE_SRGB_DECODE_EXT:
475 if (!context->getExtensions().textureSRGBDecode)
476 {
477 context->handleError(
478 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
479 return false;
480 }
481 break;
482
Geoff Langc1984ed2016-10-07 12:41:00 -0400483 default:
484 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
485 return false;
486 }
487
488 if (length)
489 {
490 *length = 1;
491 }
492 return true;
493}
494
495template <typename ParamType>
496bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
497{
498 switch (ConvertToGLenum(params[0]))
499 {
500 case GL_CLAMP_TO_EDGE:
501 break;
502
503 case GL_REPEAT:
504 case GL_MIRRORED_REPEAT:
505 if (isExternalTextureTarget)
506 {
507 // OES_EGL_image_external specifies this error.
508 context->handleError(Error(
509 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
510 return false;
511 }
512 break;
513
514 default:
515 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
516 return false;
517 }
518
519 return true;
520}
521
522template <typename ParamType>
523bool ValidateTextureMinFilterValue(Context *context,
524 ParamType *params,
525 bool isExternalTextureTarget)
526{
527 switch (ConvertToGLenum(params[0]))
528 {
529 case GL_NEAREST:
530 case GL_LINEAR:
531 break;
532
533 case GL_NEAREST_MIPMAP_NEAREST:
534 case GL_LINEAR_MIPMAP_NEAREST:
535 case GL_NEAREST_MIPMAP_LINEAR:
536 case GL_LINEAR_MIPMAP_LINEAR:
537 if (isExternalTextureTarget)
538 {
539 // OES_EGL_image_external specifies this error.
540 context->handleError(
541 Error(GL_INVALID_ENUM,
542 "external textures only support NEAREST and LINEAR filtering"));
543 return false;
544 }
545 break;
546
547 default:
548 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
549 return false;
550 }
551
552 return true;
553}
554
555template <typename ParamType>
556bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
557{
558 switch (ConvertToGLenum(params[0]))
559 {
560 case GL_NEAREST:
561 case GL_LINEAR:
562 break;
563
564 default:
565 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
566 return false;
567 }
568
569 return true;
570}
571
572template <typename ParamType>
573bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
574{
575 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
576 switch (ConvertToGLenum(params[0]))
577 {
578 case GL_NONE:
579 case GL_COMPARE_REF_TO_TEXTURE:
580 break;
581
582 default:
583 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
584 return false;
585 }
586
587 return true;
588}
589
590template <typename ParamType>
591bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
592{
593 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
594 switch (ConvertToGLenum(params[0]))
595 {
596 case GL_LEQUAL:
597 case GL_GEQUAL:
598 case GL_LESS:
599 case GL_GREATER:
600 case GL_EQUAL:
601 case GL_NOTEQUAL:
602 case GL_ALWAYS:
603 case GL_NEVER:
604 break;
605
606 default:
607 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
608 return false;
609 }
610
611 return true;
612}
613
614template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700615bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
616{
617 if (!context->getExtensions().textureSRGBDecode)
618 {
619 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
620 return false;
621 }
622
623 switch (ConvertToGLenum(params[0]))
624 {
625 case GL_DECODE_EXT:
626 case GL_SKIP_DECODE_EXT:
627 break;
628
629 default:
630 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
631 return false;
632 }
633
634 return true;
635}
636
637template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400638bool ValidateTexParameterBase(Context *context,
639 GLenum target,
640 GLenum pname,
641 GLsizei bufSize,
642 ParamType *params)
643{
644 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
645 {
646 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
647 return false;
648 }
649
650 if (context->getTargetTexture(target) == nullptr)
651 {
652 // Should only be possible for external textures
653 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
654 return false;
655 }
656
657 const GLsizei minBufSize = 1;
658 if (bufSize >= 0 && bufSize < minBufSize)
659 {
660 context->handleError(
661 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
662 return false;
663 }
664
665 switch (pname)
666 {
667 case GL_TEXTURE_WRAP_R:
668 case GL_TEXTURE_SWIZZLE_R:
669 case GL_TEXTURE_SWIZZLE_G:
670 case GL_TEXTURE_SWIZZLE_B:
671 case GL_TEXTURE_SWIZZLE_A:
672 case GL_TEXTURE_BASE_LEVEL:
673 case GL_TEXTURE_MAX_LEVEL:
674 case GL_TEXTURE_COMPARE_MODE:
675 case GL_TEXTURE_COMPARE_FUNC:
676 case GL_TEXTURE_MIN_LOD:
677 case GL_TEXTURE_MAX_LOD:
678 if (context->getClientMajorVersion() < 3)
679 {
680 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
681 return false;
682 }
683 if (target == GL_TEXTURE_EXTERNAL_OES &&
684 !context->getExtensions().eglImageExternalEssl3)
685 {
686 context->handleError(Error(GL_INVALID_ENUM,
687 "ES3 texture parameters are not available without "
688 "GL_OES_EGL_image_external_essl3."));
689 return false;
690 }
691 break;
692
693 default:
694 break;
695 }
696
697 switch (pname)
698 {
699 case GL_TEXTURE_WRAP_S:
700 case GL_TEXTURE_WRAP_T:
701 case GL_TEXTURE_WRAP_R:
702 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
703 {
704 return false;
705 }
706 break;
707
708 case GL_TEXTURE_MIN_FILTER:
709 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
710 {
711 return false;
712 }
713 break;
714
715 case GL_TEXTURE_MAG_FILTER:
716 if (!ValidateTextureMagFilterValue(context, params))
717 {
718 return false;
719 }
720 break;
721
722 case GL_TEXTURE_USAGE_ANGLE:
723 switch (ConvertToGLenum(params[0]))
724 {
725 case GL_NONE:
726 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
727 break;
728
729 default:
730 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
731 return false;
732 }
733 break;
734
735 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
736 if (!context->getExtensions().textureFilterAnisotropic)
737 {
738 context->handleError(
739 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
740 return false;
741 }
742
743 // we assume the parameter passed to this validation method is truncated, not rounded
744 if (params[0] < 1)
745 {
746 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
747 return false;
748 }
749 break;
750
751 case GL_TEXTURE_MIN_LOD:
752 case GL_TEXTURE_MAX_LOD:
753 // any value is permissible
754 break;
755
756 case GL_TEXTURE_COMPARE_MODE:
757 if (!ValidateTextureCompareModeValue(context, params))
758 {
759 return false;
760 }
761 break;
762
763 case GL_TEXTURE_COMPARE_FUNC:
764 if (!ValidateTextureCompareFuncValue(context, params))
765 {
766 return false;
767 }
768 break;
769
770 case GL_TEXTURE_SWIZZLE_R:
771 case GL_TEXTURE_SWIZZLE_G:
772 case GL_TEXTURE_SWIZZLE_B:
773 case GL_TEXTURE_SWIZZLE_A:
774 switch (ConvertToGLenum(params[0]))
775 {
776 case GL_RED:
777 case GL_GREEN:
778 case GL_BLUE:
779 case GL_ALPHA:
780 case GL_ZERO:
781 case GL_ONE:
782 break;
783
784 default:
785 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
786 return false;
787 }
788 break;
789
790 case GL_TEXTURE_BASE_LEVEL:
791 if (params[0] < 0)
792 {
793 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
794 return false;
795 }
796 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
797 {
798 context->handleError(
799 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
800 return false;
801 }
802 break;
803
804 case GL_TEXTURE_MAX_LEVEL:
805 if (params[0] < 0)
806 {
807 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
808 return false;
809 }
810 break;
811
Geoff Lang81c6b572016-10-19 14:07:52 -0700812 case GL_TEXTURE_SRGB_DECODE_EXT:
813 if (!ValidateTextureSRGBDecodeValue(context, params))
814 {
815 return false;
816 }
817 break;
818
Geoff Langc1984ed2016-10-07 12:41:00 -0400819 default:
820 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
821 return false;
822 }
823
824 return true;
825}
826
827template <typename ParamType>
828bool ValidateSamplerParameterBase(Context *context,
829 GLuint sampler,
830 GLenum pname,
831 GLsizei bufSize,
832 ParamType *params)
833{
834 if (context->getClientMajorVersion() < 3)
835 {
836 context->handleError(
837 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
838 return false;
839 }
840
841 if (!context->isSampler(sampler))
842 {
843 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
844 return false;
845 }
846
847 const GLsizei minBufSize = 1;
848 if (bufSize >= 0 && bufSize < minBufSize)
849 {
850 context->handleError(
851 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
852 return false;
853 }
854
855 switch (pname)
856 {
857 case GL_TEXTURE_WRAP_S:
858 case GL_TEXTURE_WRAP_T:
859 case GL_TEXTURE_WRAP_R:
860 if (!ValidateTextureWrapModeValue(context, params, false))
861 {
862 return false;
863 }
864 break;
865
866 case GL_TEXTURE_MIN_FILTER:
867 if (!ValidateTextureMinFilterValue(context, params, false))
868 {
869 return false;
870 }
871 break;
872
873 case GL_TEXTURE_MAG_FILTER:
874 if (!ValidateTextureMagFilterValue(context, params))
875 {
876 return false;
877 }
878 break;
879
880 case GL_TEXTURE_MIN_LOD:
881 case GL_TEXTURE_MAX_LOD:
882 // any value is permissible
883 break;
884
885 case GL_TEXTURE_COMPARE_MODE:
886 if (!ValidateTextureCompareModeValue(context, params))
887 {
888 return false;
889 }
890 break;
891
892 case GL_TEXTURE_COMPARE_FUNC:
893 if (!ValidateTextureCompareFuncValue(context, params))
894 {
895 return false;
896 }
897 break;
898
Geoff Lang81c6b572016-10-19 14:07:52 -0700899 case GL_TEXTURE_SRGB_DECODE_EXT:
900 if (!ValidateTextureSRGBDecodeValue(context, params))
901 {
902 return false;
903 }
904 break;
905
Geoff Langc1984ed2016-10-07 12:41:00 -0400906 default:
907 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
908 return false;
909 }
910
911 return true;
912}
913
914bool ValidateGetSamplerParameterBase(Context *context,
915 GLuint sampler,
916 GLenum pname,
917 GLsizei *length)
918{
919 if (length)
920 {
921 *length = 0;
922 }
923
924 if (context->getClientMajorVersion() < 3)
925 {
926 context->handleError(
927 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
928 return false;
929 }
930
931 if (!context->isSampler(sampler))
932 {
933 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
934 return false;
935 }
936
937 switch (pname)
938 {
939 case GL_TEXTURE_WRAP_S:
940 case GL_TEXTURE_WRAP_T:
941 case GL_TEXTURE_WRAP_R:
942 case GL_TEXTURE_MIN_FILTER:
943 case GL_TEXTURE_MAG_FILTER:
944 case GL_TEXTURE_MIN_LOD:
945 case GL_TEXTURE_MAX_LOD:
946 case GL_TEXTURE_COMPARE_MODE:
947 case GL_TEXTURE_COMPARE_FUNC:
948 break;
949
Geoff Lang81c6b572016-10-19 14:07:52 -0700950 case GL_TEXTURE_SRGB_DECODE_EXT:
951 if (!context->getExtensions().textureSRGBDecode)
952 {
953 context->handleError(
954 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
955 return false;
956 }
957 break;
958
Geoff Langc1984ed2016-10-07 12:41:00 -0400959 default:
960 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
961 return false;
962 }
963
964 if (length)
965 {
966 *length = 1;
967 }
968 return true;
969}
970
Geoff Lang0b031062016-10-13 14:30:04 -0400971bool ValidateGetVertexAttribBase(Context *context,
972 GLuint index,
973 GLenum pname,
974 GLsizei *length,
975 bool pointer,
976 bool pureIntegerEntryPoint)
977{
978 if (length)
979 {
980 *length = 0;
981 }
982
983 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
984 {
985 context->handleError(
986 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
987 return false;
988 }
989
990 if (index >= context->getCaps().maxVertexAttributes)
991 {
992 context->handleError(Error(
993 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
994 return false;
995 }
996
997 if (pointer)
998 {
999 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1000 {
1001 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1002 return false;
1003 }
1004 }
1005 else
1006 {
1007 switch (pname)
1008 {
1009 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1010 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1011 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1012 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1013 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1014 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1015 case GL_CURRENT_VERTEX_ATTRIB:
1016 break;
1017
1018 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1019 static_assert(
1020 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1021 "ANGLE extension enums not equal to GL enums.");
1022 if (context->getClientMajorVersion() < 3 &&
1023 !context->getExtensions().instancedArrays)
1024 {
1025 context->handleError(Error(GL_INVALID_ENUM,
1026 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1027 "3.0 or GL_ANGLE_instanced_arrays."));
1028 return false;
1029 }
1030 break;
1031
1032 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1033 if (context->getClientMajorVersion() < 3)
1034 {
1035 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1036 return false;
1037 }
1038 break;
1039
1040 default:
1041 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1042 return false;
1043 }
1044 }
1045
1046 if (length)
1047 {
1048 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1049 {
1050 *length = 4;
1051 }
1052 else
1053 {
1054 *length = 1;
1055 }
1056 }
1057
1058 return true;
1059}
1060
Geoff Lang6899b872016-10-14 11:30:13 -04001061bool ValidateGetActiveUniformBlockivBase(Context *context,
1062 GLuint program,
1063 GLuint uniformBlockIndex,
1064 GLenum pname,
1065 GLsizei *length)
1066{
1067 if (length)
1068 {
1069 *length = 0;
1070 }
1071
1072 if (context->getClientMajorVersion() < 3)
1073 {
1074 context->handleError(
1075 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1076 return false;
1077 }
1078
1079 Program *programObject = GetValidProgram(context, program);
1080 if (!programObject)
1081 {
1082 return false;
1083 }
1084
1085 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1086 {
1087 context->handleError(
1088 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1089 return false;
1090 }
1091
1092 switch (pname)
1093 {
1094 case GL_UNIFORM_BLOCK_BINDING:
1095 case GL_UNIFORM_BLOCK_DATA_SIZE:
1096 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1097 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1098 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1099 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1100 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1101 break;
1102
1103 default:
1104 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1105 return false;
1106 }
1107
1108 if (length)
1109 {
1110 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1111 {
1112 const UniformBlock &uniformBlock =
1113 programObject->getUniformBlockByIndex(uniformBlockIndex);
1114 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1115 }
1116 else
1117 {
1118 *length = 1;
1119 }
1120 }
1121
1122 return true;
1123}
1124
Geoff Langebebe1c2016-10-14 12:01:31 -04001125bool ValidateGetBufferParameterBase(ValidationContext *context,
1126 GLenum target,
1127 GLenum pname,
1128 bool pointerVersion,
1129 GLsizei *numParams)
1130{
1131 if (numParams)
1132 {
1133 *numParams = 0;
1134 }
1135
1136 if (!ValidBufferTarget(context, target))
1137 {
1138 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1139 return false;
1140 }
1141
1142 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1143 if (!buffer)
1144 {
1145 // A null buffer means that "0" is bound to the requested buffer target
1146 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1147 return false;
1148 }
1149
1150 const Extensions &extensions = context->getExtensions();
1151
1152 switch (pname)
1153 {
1154 case GL_BUFFER_USAGE:
1155 case GL_BUFFER_SIZE:
1156 break;
1157
1158 case GL_BUFFER_ACCESS_OES:
1159 if (!extensions.mapBuffer)
1160 {
1161 context->handleError(
1162 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1163 return false;
1164 }
1165 break;
1166
1167 case GL_BUFFER_MAPPED:
1168 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1169 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1170 !extensions.mapBufferRange)
1171 {
1172 context->handleError(Error(
1173 GL_INVALID_ENUM,
1174 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1175 return false;
1176 }
1177 break;
1178
1179 case GL_BUFFER_MAP_POINTER:
1180 if (!pointerVersion)
1181 {
1182 context->handleError(
1183 Error(GL_INVALID_ENUM,
1184 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1185 return false;
1186 }
1187 break;
1188
1189 case GL_BUFFER_ACCESS_FLAGS:
1190 case GL_BUFFER_MAP_OFFSET:
1191 case GL_BUFFER_MAP_LENGTH:
1192 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1193 {
1194 context->handleError(Error(
1195 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1196 return false;
1197 }
1198 break;
1199
1200 default:
1201 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1202 return false;
1203 }
1204
1205 // All buffer parameter queries return one value.
1206 if (numParams)
1207 {
1208 *numParams = 1;
1209 }
1210
1211 return true;
1212}
1213
Geoff Lang0a9661f2016-10-20 10:59:20 -07001214bool ValidateGetInternalFormativBase(Context *context,
1215 GLenum target,
1216 GLenum internalformat,
1217 GLenum pname,
1218 GLsizei bufSize,
1219 GLsizei *numParams)
1220{
1221 if (numParams)
1222 {
1223 *numParams = 0;
1224 }
1225
1226 if (context->getClientMajorVersion() < 3)
1227 {
1228 context->handleError(
1229 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1230 return false;
1231 }
1232
1233 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1234 if (!formatCaps.renderable)
1235 {
1236 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1237 return false;
1238 }
1239
1240 switch (target)
1241 {
1242 case GL_RENDERBUFFER:
1243 break;
1244
1245 default:
1246 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1247 return false;
1248 }
1249
1250 if (bufSize < 0)
1251 {
1252 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1253 return false;
1254 }
1255
1256 GLsizei maxWriteParams = 0;
1257 switch (pname)
1258 {
1259 case GL_NUM_SAMPLE_COUNTS:
1260 maxWriteParams = 1;
1261 break;
1262
1263 case GL_SAMPLES:
1264 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1265 break;
1266
1267 default:
1268 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1269 return false;
1270 }
1271
1272 if (numParams)
1273 {
1274 // glGetInternalFormativ will not overflow bufSize
1275 *numParams = std::min(bufSize, maxWriteParams);
1276 }
1277
1278 return true;
1279}
1280
Geoff Langf41a7152016-09-19 15:11:17 -04001281} // anonymous namespace
1282
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001283bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001284{
Jamie Madilld7460c72014-01-21 16:38:14 -05001285 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001286 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001287 case GL_TEXTURE_2D:
1288 case GL_TEXTURE_CUBE_MAP:
1289 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001290
Jamie Madilld7460c72014-01-21 16:38:14 -05001291 case GL_TEXTURE_3D:
1292 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001293 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001294
1295 default:
1296 return false;
1297 }
Jamie Madill35d15012013-10-07 10:46:37 -04001298}
1299
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001300bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1301{
1302 switch (target)
1303 {
1304 case GL_TEXTURE_2D:
1305 case GL_TEXTURE_CUBE_MAP:
1306 return true;
1307
1308 default:
1309 return false;
1310 }
1311}
1312
1313bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1314{
1315 switch (target)
1316 {
1317 case GL_TEXTURE_3D:
1318 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001319 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001320
1321 default:
1322 return false;
1323 }
1324}
1325
Ian Ewellbda75592016-04-18 17:25:54 -04001326// Most texture GL calls are not compatible with external textures, so we have a separate validation
1327// function for use in the GL calls that do
1328bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1329{
1330 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1331 (context->getExtensions().eglImageExternal ||
1332 context->getExtensions().eglStreamConsumerExternal);
1333}
1334
Shannon Woods4dfed832014-03-17 20:03:39 -04001335// This function differs from ValidTextureTarget in that the target must be
1336// usable as the destination of a 2D operation-- so a cube face is valid, but
1337// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001338// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001339bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001340{
1341 switch (target)
1342 {
1343 case GL_TEXTURE_2D:
1344 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1345 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1346 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1347 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1348 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1349 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1350 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001351 default:
1352 return false;
1353 }
1354}
1355
1356bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1357{
1358 switch (target)
1359 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001360 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001361 case GL_TEXTURE_2D_ARRAY:
1362 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001363 default:
1364 return false;
1365 }
1366}
1367
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001368bool ValidFramebufferTarget(GLenum target)
1369{
Geoff Langd4475812015-03-18 10:53:05 -04001370 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1371 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001372
1373 switch (target)
1374 {
1375 case GL_FRAMEBUFFER: return true;
1376 case GL_READ_FRAMEBUFFER: return true;
1377 case GL_DRAW_FRAMEBUFFER: return true;
1378 default: return false;
1379 }
1380}
1381
Jamie Madill29639852016-09-02 15:00:09 -04001382bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001383{
1384 switch (target)
1385 {
1386 case GL_ARRAY_BUFFER:
1387 case GL_ELEMENT_ARRAY_BUFFER:
1388 return true;
1389
Jamie Madill8c96d582014-03-05 15:01:23 -05001390 case GL_PIXEL_PACK_BUFFER:
1391 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001392 return (context->getExtensions().pixelBufferObject ||
1393 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001394
Shannon Woodsb3801742014-03-27 14:59:19 -04001395 case GL_COPY_READ_BUFFER:
1396 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001397 case GL_TRANSFORM_FEEDBACK_BUFFER:
1398 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001399 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001400
1401 default:
1402 return false;
1403 }
1404}
1405
Jamie Madillc29968b2016-01-20 11:17:23 -05001406bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001407{
Jamie Madillc29968b2016-01-20 11:17:23 -05001408 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001409 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001410 switch (target)
1411 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001412 case GL_TEXTURE_2D:
1413 maxDimension = caps.max2DTextureSize;
1414 break;
Geoff Langce635692013-09-24 13:56:32 -04001415 case GL_TEXTURE_CUBE_MAP:
1416 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1417 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1418 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1419 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1420 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001421 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1422 maxDimension = caps.maxCubeMapTextureSize;
1423 break;
1424 case GL_TEXTURE_3D:
1425 maxDimension = caps.max3DTextureSize;
1426 break;
1427 case GL_TEXTURE_2D_ARRAY:
1428 maxDimension = caps.max2DTextureSize;
1429 break;
Geoff Langce635692013-09-24 13:56:32 -04001430 default: UNREACHABLE();
1431 }
1432
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001433 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001434}
1435
Austin Kinross08528e12015-10-07 16:24:40 -07001436bool ValidImageSizeParameters(const Context *context,
1437 GLenum target,
1438 GLint level,
1439 GLsizei width,
1440 GLsizei height,
1441 GLsizei depth,
1442 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001443{
1444 if (level < 0 || width < 0 || height < 0 || depth < 0)
1445 {
1446 return false;
1447 }
1448
Austin Kinross08528e12015-10-07 16:24:40 -07001449 // TexSubImage parameters can be NPOT without textureNPOT extension,
1450 // as long as the destination texture is POT.
1451 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001452 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001453 {
1454 return false;
1455 }
1456
1457 if (!ValidMipLevel(context, target, level))
1458 {
1459 return false;
1460 }
1461
1462 return true;
1463}
1464
Geoff Lang0d8b7242015-09-09 14:56:53 -04001465bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1466{
1467 // List of compressed format that require that the texture size is smaller than or a multiple of
1468 // the compressed block size.
1469 switch (internalFormat)
1470 {
1471 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1472 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1473 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1474 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001475 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001476 return true;
1477
1478 default:
1479 return false;
1480 }
1481}
1482
Jamie Madillc29968b2016-01-20 11:17:23 -05001483bool ValidCompressedImageSize(const ValidationContext *context,
1484 GLenum internalFormat,
1485 GLsizei width,
1486 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001487{
Geoff Lang5d601382014-07-22 15:14:06 -04001488 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1489 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001490 {
1491 return false;
1492 }
1493
Geoff Lang0d8b7242015-09-09 14:56:53 -04001494 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001495 {
1496 return false;
1497 }
1498
Geoff Lang0d8b7242015-09-09 14:56:53 -04001499 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1500 {
1501 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1502 width % formatInfo.compressedBlockWidth != 0) ||
1503 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1504 height % formatInfo.compressedBlockHeight != 0))
1505 {
1506 return false;
1507 }
1508 }
1509
Geoff Langd4f180b2013-09-24 13:57:44 -04001510 return true;
1511}
1512
Geoff Langff5b2d52016-09-07 11:32:23 -04001513bool ValidImageDataSize(ValidationContext *context,
1514 GLenum textureTarget,
1515 GLsizei width,
1516 GLsizei height,
1517 GLsizei depth,
1518 GLenum internalFormat,
1519 GLenum type,
1520 const GLvoid *pixels,
1521 GLsizei imageSize)
1522{
1523 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1524 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1525 {
1526 // Checks are not required
1527 return true;
1528 }
1529
1530 // ...the data would be unpacked from the buffer object such that the memory reads required
1531 // would exceed the data store size.
1532 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1533 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1534 const gl::Extents size(width, height, depth);
1535 const auto &unpack = context->getGLState().getUnpackState();
1536
1537 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1538 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1539 if (endByteOrErr.isError())
1540 {
1541 context->handleError(endByteOrErr.getError());
1542 return false;
1543 }
1544
1545 GLuint endByte = endByteOrErr.getResult();
1546
1547 if (pixelUnpackBuffer)
1548 {
1549 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1550 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1551 checkedEndByte += checkedOffset;
1552
1553 if (!checkedEndByte.IsValid() ||
1554 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1555 {
1556 // Overflow past the end of the buffer
1557 context->handleError(Error(GL_INVALID_OPERATION));
1558 return false;
1559 }
1560 }
1561 else
1562 {
1563 ASSERT(imageSize >= 0);
1564 if (pixels == nullptr && imageSize != 0)
1565 {
1566 context->handleError(
1567 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001568 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001569 }
1570
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001571 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001572 {
1573 context->handleError(
1574 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1575 return false;
1576 }
1577 }
1578
1579 return true;
1580}
1581
Geoff Lang37dde692014-01-31 16:34:54 -05001582bool ValidQueryType(const Context *context, GLenum queryType)
1583{
Geoff Langd4475812015-03-18 10:53:05 -04001584 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1585 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 -05001586
1587 switch (queryType)
1588 {
1589 case GL_ANY_SAMPLES_PASSED:
1590 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1591 return true;
1592 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001593 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001594 case GL_TIME_ELAPSED_EXT:
1595 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001596 case GL_COMMANDS_COMPLETED_CHROMIUM:
1597 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001598 default:
1599 return false;
1600 }
1601}
1602
Jamie Madillef300b12016-10-07 15:12:09 -04001603Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001604{
1605 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1606 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1607 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1608
Dian Xiang769769a2015-09-09 15:20:08 -07001609 Program *validProgram = context->getProgram(id);
1610
1611 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001612 {
Dian Xiang769769a2015-09-09 15:20:08 -07001613 if (context->getShader(id))
1614 {
Jamie Madill437fa652016-05-03 15:13:24 -04001615 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001616 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1617 }
1618 else
1619 {
Jamie Madill437fa652016-05-03 15:13:24 -04001620 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001621 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001622 }
Dian Xiang769769a2015-09-09 15:20:08 -07001623
1624 return validProgram;
1625}
1626
Jamie Madillef300b12016-10-07 15:12:09 -04001627Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001628{
1629 // See ValidProgram for spec details.
1630
1631 Shader *validShader = context->getShader(id);
1632
1633 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001634 {
Dian Xiang769769a2015-09-09 15:20:08 -07001635 if (context->getProgram(id))
1636 {
Jamie Madill437fa652016-05-03 15:13:24 -04001637 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001638 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1639 }
1640 else
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001643 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001644 }
Dian Xiang769769a2015-09-09 15:20:08 -07001645
1646 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001647}
1648
Geoff Langb1196682014-07-23 13:47:29 -04001649bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001650{
1651 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1652 {
1653 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1654
Geoff Langaae65a42014-05-26 12:43:44 -04001655 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001656 {
Jamie Madill437fa652016-05-03 15:13:24 -04001657 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001658 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001659 }
1660 }
1661 else
1662 {
1663 switch (attachment)
1664 {
1665 case GL_DEPTH_ATTACHMENT:
1666 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001667 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001668
1669 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001670 if (!context->getExtensions().webglCompatibility &&
1671 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001672 {
1673 context->handleError(Error(GL_INVALID_ENUM));
1674 return false;
1675 }
1676 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001677
1678 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001679 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001680 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001681 }
1682 }
1683
1684 return true;
1685}
1686
Corentin Walleze0902642014-11-04 12:32:15 -08001687bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1688 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001689{
1690 switch (target)
1691 {
1692 case GL_RENDERBUFFER:
1693 break;
1694 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001696 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001697 }
1698
1699 if (width < 0 || height < 0 || samples < 0)
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001702 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001703 }
1704
Geoff Langd87878e2014-09-19 15:42:59 -04001705 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1706 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001709 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001710 }
1711
1712 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1713 // 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 -08001714 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001715 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001716 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001719 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001720 }
1721
Geoff Langaae65a42014-05-26 12:43:44 -04001722 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001723 {
Jamie Madill437fa652016-05-03 15:13:24 -04001724 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001725 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001726 }
1727
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001728 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729 if (handle == 0)
1730 {
Jamie Madill437fa652016-05-03 15:13:24 -04001731 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001732 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001733 }
1734
1735 return true;
1736}
1737
Corentin Walleze0902642014-11-04 12:32:15 -08001738bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1739 GLenum internalformat, GLsizei width, GLsizei height)
1740{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001741 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001742
1743 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001744 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001745 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001746 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001747 {
Jamie Madill437fa652016-05-03 15:13:24 -04001748 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001749 return false;
1750 }
1751
1752 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1753 // the specified storage. This is different than ES 3.0 in which a sample number higher
1754 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001755 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001756 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001757 {
Geoff Langa4903b72015-03-02 16:02:48 -08001758 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1759 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1760 {
Jamie Madill437fa652016-05-03 15:13:24 -04001761 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001762 return false;
1763 }
Corentin Walleze0902642014-11-04 12:32:15 -08001764 }
1765
1766 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1767}
1768
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001769bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1770 GLenum renderbuffertarget, GLuint renderbuffer)
1771{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001772 if (!ValidFramebufferTarget(target))
1773 {
Jamie Madill437fa652016-05-03 15:13:24 -04001774 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001775 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001776 }
1777
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001778 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001779
Jamie Madill84115c92015-04-23 15:00:07 -04001780 ASSERT(framebuffer);
1781 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001782 {
Jamie Madill437fa652016-05-03 15:13:24 -04001783 context->handleError(
1784 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001785 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001786 }
1787
Jamie Madillb4472272014-07-03 10:38:55 -04001788 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001789 {
Jamie Madillb4472272014-07-03 10:38:55 -04001790 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001791 }
1792
Jamie Madillab9d82c2014-01-21 16:38:14 -05001793 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1794 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1795 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1796 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1797 if (renderbuffer != 0)
1798 {
1799 if (!context->getRenderbuffer(renderbuffer))
1800 {
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001802 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001803 }
1804 }
1805
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001806 return true;
1807}
1808
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001809bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001810 GLint srcX0,
1811 GLint srcY0,
1812 GLint srcX1,
1813 GLint srcY1,
1814 GLint dstX0,
1815 GLint dstY0,
1816 GLint dstX1,
1817 GLint dstY1,
1818 GLbitfield mask,
1819 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001820{
1821 switch (filter)
1822 {
1823 case GL_NEAREST:
1824 break;
1825 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001826 break;
1827 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001830 }
1831
1832 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1833 {
Jamie Madill437fa652016-05-03 15:13:24 -04001834 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001835 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001836 }
1837
1838 if (mask == 0)
1839 {
1840 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1841 // buffers are copied.
1842 return false;
1843 }
1844
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001845 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1846 // color buffer, leaving only nearest being unfiltered from above
1847 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1848 {
Jamie Madill437fa652016-05-03 15:13:24 -04001849 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001850 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001851 }
1852
Jamie Madill51f40ec2016-06-15 14:06:00 -04001853 const auto &glState = context->getGLState();
1854 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1855 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001856
1857 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001858 {
Jamie Madill437fa652016-05-03 15:13:24 -04001859 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001860 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001861 }
1862
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001863 if (readFramebuffer->id() == drawFramebuffer->id())
1864 {
1865 context->handleError(Error(GL_INVALID_OPERATION));
1866 return false;
1867 }
1868
Jamie Madill51f40ec2016-06-15 14:06:00 -04001869 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001870 {
Jamie Madill437fa652016-05-03 15:13:24 -04001871 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001872 return false;
1873 }
1874
Jamie Madill51f40ec2016-06-15 14:06:00 -04001875 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001876 {
Jamie Madill437fa652016-05-03 15:13:24 -04001877 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001878 return false;
1879 }
1880
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001881 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001882 {
Jamie Madill437fa652016-05-03 15:13:24 -04001883 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001884 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001885 }
1886
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001887 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1888
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001889 if (mask & GL_COLOR_BUFFER_BIT)
1890 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001891 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1892 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001893 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001894
1895 if (readColorBuffer && drawColorBuffer)
1896 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001897 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001898
Geoff Langa15472a2015-08-11 11:48:03 -04001899 for (size_t drawbufferIdx = 0;
1900 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001901 {
Geoff Langa15472a2015-08-11 11:48:03 -04001902 const FramebufferAttachment *attachment =
1903 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1904 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001905 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001906 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001907
Geoff Langb2f3d052013-08-13 12:49:27 -04001908 // The GL ES 3.0.2 spec (pg 193) states that:
1909 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1910 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1911 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001912 // Changes with EXT_color_buffer_float:
1913 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001914 GLenum readComponentType = readFormat.info->componentType;
1915 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001916 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1917 readComponentType == GL_SIGNED_NORMALIZED);
1918 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1919 drawComponentType == GL_SIGNED_NORMALIZED);
1920
1921 if (extensions.colorBufferFloat)
1922 {
1923 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1924 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1925
1926 if (readFixedOrFloat != drawFixedOrFloat)
1927 {
Jamie Madill437fa652016-05-03 15:13:24 -04001928 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001929 "If the read buffer contains fixed-point or "
1930 "floating-point values, the draw buffer "
1931 "must as well."));
1932 return false;
1933 }
1934 }
1935 else if (readFixedPoint != drawFixedPoint)
1936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001938 "If the read buffer contains fixed-point "
1939 "values, the draw buffer must as well."));
1940 return false;
1941 }
1942
1943 if (readComponentType == GL_UNSIGNED_INT &&
1944 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001945 {
Jamie Madill437fa652016-05-03 15:13:24 -04001946 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001947 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001948 }
1949
Jamie Madill6163c752015-12-07 16:32:59 -05001950 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001951 {
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001953 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001954 }
1955
Jamie Madilla3944d42016-07-22 22:13:26 -04001956 if (readColorBuffer->getSamples() > 0 &&
1957 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001958 {
Jamie Madill437fa652016-05-03 15:13:24 -04001959 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001960 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961 }
1962 }
1963 }
1964
Jamie Madilla3944d42016-07-22 22:13:26 -04001965 if ((readFormat.info->componentType == GL_INT ||
1966 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1967 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001968 {
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001970 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972 }
1973 }
1974
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001975 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1976 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1977 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001978 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001979 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001980 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001981 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1982 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001984 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001986 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001987 {
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001990 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001991
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001992 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001996 }
1997 }
1998 }
1999 }
2000
2001 return true;
2002}
2003
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002004bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002005 GLint x,
2006 GLint y,
2007 GLsizei width,
2008 GLsizei height,
2009 GLenum format,
2010 GLenum type,
2011 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002012{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002013 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2014}
2015
2016bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2017 GLint x,
2018 GLint y,
2019 GLsizei width,
2020 GLsizei height,
2021 GLenum format,
2022 GLenum type,
2023 GLsizei bufSize,
2024 GLsizei *length,
2025 GLvoid *pixels)
2026{
2027 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002028 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002029 return false;
2030 }
2031
Geoff Lang62fce5b2016-09-30 10:46:35 -04002032 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2033 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002034 {
Geoff Langb1196682014-07-23 13:47:29 -04002035 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002036 }
2037
Geoff Lang62fce5b2016-09-30 10:46:35 -04002038 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002039 {
Geoff Langb1196682014-07-23 13:47:29 -04002040 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002041 }
2042
Jamie Madillc29968b2016-01-20 11:17:23 -05002043 return true;
2044}
2045
2046bool ValidateReadnPixelsEXT(Context *context,
2047 GLint x,
2048 GLint y,
2049 GLsizei width,
2050 GLsizei height,
2051 GLenum format,
2052 GLenum type,
2053 GLsizei bufSize,
2054 GLvoid *pixels)
2055{
2056 if (bufSize < 0)
2057 {
Jamie Madill437fa652016-05-03 15:13:24 -04002058 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002059 return false;
2060 }
2061
Geoff Lang62fce5b2016-09-30 10:46:35 -04002062 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2063 pixels);
2064}
Jamie Madill26e91952014-03-05 15:01:27 -05002065
Geoff Lang62fce5b2016-09-30 10:46:35 -04002066bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2067 GLint x,
2068 GLint y,
2069 GLsizei width,
2070 GLsizei height,
2071 GLenum format,
2072 GLenum type,
2073 GLsizei bufSize,
2074 GLsizei *length,
2075 GLvoid *data)
2076{
2077 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002078 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002079 return false;
2080 }
2081
Geoff Lang62fce5b2016-09-30 10:46:35 -04002082 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002083 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002084 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002085 }
2086
Geoff Lang62fce5b2016-09-30 10:46:35 -04002087 if (!ValidateRobustBufferSize(context, bufSize, *length))
2088 {
2089 return false;
2090 }
2091
2092 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002093}
2094
Olli Etuaho41997e72016-03-10 13:38:39 +02002095bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002096{
2097 if (!context->getExtensions().occlusionQueryBoolean &&
2098 !context->getExtensions().disjointTimerQuery)
2099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002101 return false;
2102 }
2103
Olli Etuaho41997e72016-03-10 13:38:39 +02002104 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002105}
2106
Olli Etuaho41997e72016-03-10 13:38:39 +02002107bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002108{
2109 if (!context->getExtensions().occlusionQueryBoolean &&
2110 !context->getExtensions().disjointTimerQuery)
2111 {
Jamie Madill437fa652016-05-03 15:13:24 -04002112 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002113 return false;
2114 }
2115
Olli Etuaho41997e72016-03-10 13:38:39 +02002116 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002117}
2118
2119bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002120{
2121 if (!ValidQueryType(context, target))
2122 {
Jamie Madill437fa652016-05-03 15:13:24 -04002123 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002124 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002125 }
2126
2127 if (id == 0)
2128 {
Jamie Madill437fa652016-05-03 15:13:24 -04002129 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002130 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002131 }
2132
2133 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2134 // of zero, if the active query object name for <target> is non-zero (for the
2135 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2136 // the active query for either target is non-zero), if <id> is the name of an
2137 // existing query object whose type does not match <target>, or if <id> is the
2138 // active query object name for any query type, the error INVALID_OPERATION is
2139 // generated.
2140
2141 // Ensure no other queries are active
2142 // NOTE: If other queries than occlusion are supported, we will need to check
2143 // separately that:
2144 // a) The query ID passed is not the current active query for any target/type
2145 // b) There are no active queries for the requested target (and in the case
2146 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2147 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002148
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002149 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002150 {
Jamie Madill437fa652016-05-03 15:13:24 -04002151 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002152 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002153 }
2154
2155 Query *queryObject = context->getQuery(id, true, target);
2156
2157 // check that name was obtained with glGenQueries
2158 if (!queryObject)
2159 {
Jamie Madill437fa652016-05-03 15:13:24 -04002160 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002161 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002162 }
2163
2164 // check for type mismatch
2165 if (queryObject->getType() != target)
2166 {
Jamie Madill437fa652016-05-03 15:13:24 -04002167 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002168 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002169 }
2170
2171 return true;
2172}
2173
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002174bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2175{
2176 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002177 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002178 {
Jamie Madill437fa652016-05-03 15:13:24 -04002179 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002180 return false;
2181 }
2182
2183 return ValidateBeginQueryBase(context, target, id);
2184}
2185
2186bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002187{
2188 if (!ValidQueryType(context, target))
2189 {
Jamie Madill437fa652016-05-03 15:13:24 -04002190 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002191 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002192 }
2193
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002194 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002195
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002196 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002199 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002200 }
2201
Jamie Madill45c785d2014-05-13 14:09:34 -04002202 return true;
2203}
2204
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002205bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2206{
2207 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002208 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002209 {
Jamie Madill437fa652016-05-03 15:13:24 -04002210 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002211 return false;
2212 }
2213
2214 return ValidateEndQueryBase(context, target);
2215}
2216
2217bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2218{
2219 if (!context->getExtensions().disjointTimerQuery)
2220 {
Jamie Madill437fa652016-05-03 15:13:24 -04002221 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002222 return false;
2223 }
2224
2225 if (target != GL_TIMESTAMP_EXT)
2226 {
Jamie Madill437fa652016-05-03 15:13:24 -04002227 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002228 return false;
2229 }
2230
2231 Query *queryObject = context->getQuery(id, true, target);
2232 if (queryObject == nullptr)
2233 {
Jamie Madill437fa652016-05-03 15:13:24 -04002234 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002235 return false;
2236 }
2237
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002238 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002239 {
Jamie Madill437fa652016-05-03 15:13:24 -04002240 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002241 return false;
2242 }
2243
2244 return true;
2245}
2246
Geoff Lang2186c382016-10-14 10:54:54 -04002247bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002248{
Geoff Lang2186c382016-10-14 10:54:54 -04002249 if (numParams)
2250 {
2251 *numParams = 0;
2252 }
2253
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002254 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2255 {
Jamie Madill437fa652016-05-03 15:13:24 -04002256 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002257 return false;
2258 }
2259
2260 switch (pname)
2261 {
2262 case GL_CURRENT_QUERY_EXT:
2263 if (target == GL_TIMESTAMP_EXT)
2264 {
Jamie Madill437fa652016-05-03 15:13:24 -04002265 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002266 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2267 return false;
2268 }
2269 break;
2270 case GL_QUERY_COUNTER_BITS_EXT:
2271 if (!context->getExtensions().disjointTimerQuery ||
2272 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2273 {
Jamie Madill437fa652016-05-03 15:13:24 -04002274 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002275 return false;
2276 }
2277 break;
2278 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002279 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280 return false;
2281 }
2282
Geoff Lang2186c382016-10-14 10:54:54 -04002283 if (numParams)
2284 {
2285 // All queries return only one value
2286 *numParams = 1;
2287 }
2288
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002289 return true;
2290}
2291
2292bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2293{
2294 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002295 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002296 {
Jamie Madill437fa652016-05-03 15:13:24 -04002297 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002298 return false;
2299 }
2300
Geoff Lang2186c382016-10-14 10:54:54 -04002301 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002302}
2303
Geoff Lang2186c382016-10-14 10:54:54 -04002304bool ValidateGetQueryivRobustANGLE(Context *context,
2305 GLenum target,
2306 GLenum pname,
2307 GLsizei bufSize,
2308 GLsizei *length,
2309 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002310{
Geoff Lang2186c382016-10-14 10:54:54 -04002311 if (!ValidateRobustEntryPoint(context, bufSize))
2312 {
2313 return false;
2314 }
2315
2316 if (!ValidateGetQueryivBase(context, target, pname, length))
2317 {
2318 return false;
2319 }
2320
2321 if (!ValidateRobustBufferSize(context, bufSize, *length))
2322 {
2323 return false;
2324 }
2325
2326 return true;
2327}
2328
2329bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2330{
2331 if (numParams)
2332 {
2333 *numParams = 0;
2334 }
2335
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002336 Query *queryObject = context->getQuery(id, false, GL_NONE);
2337
2338 if (!queryObject)
2339 {
Jamie Madill437fa652016-05-03 15:13:24 -04002340 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002341 return false;
2342 }
2343
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002344 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002345 {
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002347 return false;
2348 }
2349
2350 switch (pname)
2351 {
2352 case GL_QUERY_RESULT_EXT:
2353 case GL_QUERY_RESULT_AVAILABLE_EXT:
2354 break;
2355
2356 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002357 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002358 return false;
2359 }
2360
Geoff Lang2186c382016-10-14 10:54:54 -04002361 if (numParams)
2362 {
2363 *numParams = 1;
2364 }
2365
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366 return true;
2367}
2368
2369bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2370{
2371 if (!context->getExtensions().disjointTimerQuery)
2372 {
Jamie Madill437fa652016-05-03 15:13:24 -04002373 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002374 return false;
2375 }
Geoff Lang2186c382016-10-14 10:54:54 -04002376 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2377}
2378
2379bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2380 GLuint id,
2381 GLenum pname,
2382 GLsizei bufSize,
2383 GLsizei *length,
2384 GLint *params)
2385{
2386 if (!context->getExtensions().disjointTimerQuery)
2387 {
2388 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2389 return false;
2390 }
2391
2392 if (!ValidateRobustEntryPoint(context, bufSize))
2393 {
2394 return false;
2395 }
2396
2397 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2398 {
2399 return false;
2400 }
2401
2402 if (!ValidateRobustBufferSize(context, bufSize, *length))
2403 {
2404 return false;
2405 }
2406
2407 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002408}
2409
2410bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2411{
2412 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002413 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002414 {
Jamie Madill437fa652016-05-03 15:13:24 -04002415 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002416 return false;
2417 }
Geoff Lang2186c382016-10-14 10:54:54 -04002418 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2419}
2420
2421bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2422 GLuint id,
2423 GLenum pname,
2424 GLsizei bufSize,
2425 GLsizei *length,
2426 GLuint *params)
2427{
2428 if (!context->getExtensions().disjointTimerQuery &&
2429 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2430 {
2431 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2432 return false;
2433 }
2434
2435 if (!ValidateRobustEntryPoint(context, bufSize))
2436 {
2437 return false;
2438 }
2439
2440 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2441 {
2442 return false;
2443 }
2444
2445 if (!ValidateRobustBufferSize(context, bufSize, *length))
2446 {
2447 return false;
2448 }
2449
2450 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002451}
2452
2453bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2454{
2455 if (!context->getExtensions().disjointTimerQuery)
2456 {
Jamie Madill437fa652016-05-03 15:13:24 -04002457 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002458 return false;
2459 }
Geoff Lang2186c382016-10-14 10:54:54 -04002460 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2461}
2462
2463bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2464 GLuint id,
2465 GLenum pname,
2466 GLsizei bufSize,
2467 GLsizei *length,
2468 GLint64 *params)
2469{
2470 if (!context->getExtensions().disjointTimerQuery)
2471 {
2472 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2473 return false;
2474 }
2475
2476 if (!ValidateRobustEntryPoint(context, bufSize))
2477 {
2478 return false;
2479 }
2480
2481 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2482 {
2483 return false;
2484 }
2485
2486 if (!ValidateRobustBufferSize(context, bufSize, *length))
2487 {
2488 return false;
2489 }
2490
2491 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002492}
2493
2494bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2495{
2496 if (!context->getExtensions().disjointTimerQuery)
2497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002499 return false;
2500 }
Geoff Lang2186c382016-10-14 10:54:54 -04002501 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2502}
2503
2504bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2505 GLuint id,
2506 GLenum pname,
2507 GLsizei bufSize,
2508 GLsizei *length,
2509 GLuint64 *params)
2510{
2511 if (!context->getExtensions().disjointTimerQuery)
2512 {
2513 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2514 return false;
2515 }
2516
2517 if (!ValidateRobustEntryPoint(context, bufSize))
2518 {
2519 return false;
2520 }
2521
2522 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2523 {
2524 return false;
2525 }
2526
2527 if (!ValidateRobustBufferSize(context, bufSize, *length))
2528 {
2529 return false;
2530 }
2531
2532 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002533}
2534
Jamie Madill62d31cb2015-09-11 13:25:51 -04002535static bool ValidateUniformCommonBase(gl::Context *context,
2536 GLenum targetUniformType,
2537 GLint location,
2538 GLsizei count,
2539 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002540{
2541 if (count < 0)
2542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002544 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002545 }
2546
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002547 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002548 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002549 {
Jamie Madill437fa652016-05-03 15:13:24 -04002550 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002551 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002552 }
2553
Geoff Langd8605522016-04-13 10:19:12 -04002554 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002555 {
2556 // Silently ignore the uniform command
2557 return false;
2558 }
2559
Geoff Lang7dd2e102014-11-10 15:19:26 -05002560 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002561 {
Jamie Madill437fa652016-05-03 15:13:24 -04002562 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002563 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002564 }
2565
Jamie Madill62d31cb2015-09-11 13:25:51 -04002566 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002567
2568 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002569 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002570 {
Jamie Madill437fa652016-05-03 15:13:24 -04002571 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002572 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002573 }
2574
Jamie Madill62d31cb2015-09-11 13:25:51 -04002575 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002576 return true;
2577}
2578
Jamie Madillaa981bd2014-05-20 10:55:55 -04002579bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2580{
2581 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002582 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2583 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002584 {
Jamie Madill437fa652016-05-03 15:13:24 -04002585 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002586 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002587 }
2588
Jamie Madill62d31cb2015-09-11 13:25:51 -04002589 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002590 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2591 {
2592 return false;
2593 }
2594
Jamie Madillf2575982014-06-25 16:04:54 -04002595 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002596 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002597 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2598 {
Jamie Madill437fa652016-05-03 15:13:24 -04002599 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002600 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002601 }
2602
2603 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002604}
2605
2606bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2607 GLboolean transpose)
2608{
2609 // Check for ES3 uniform entry points
2610 int rows = VariableRowCount(matrixType);
2611 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002612 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002613 {
Jamie Madill437fa652016-05-03 15:13:24 -04002614 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002615 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002616 }
2617
Martin Radev1be913c2016-07-11 17:59:16 +03002618 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002619 {
Jamie Madill437fa652016-05-03 15:13:24 -04002620 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002621 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002622 }
2623
Jamie Madill62d31cb2015-09-11 13:25:51 -04002624 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002625 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2626 {
2627 return false;
2628 }
2629
2630 if (uniform->type != matrixType)
2631 {
Jamie Madill437fa652016-05-03 15:13:24 -04002632 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002633 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002634 }
2635
2636 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002637}
2638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002639bool ValidateStateQuery(ValidationContext *context,
2640 GLenum pname,
2641 GLenum *nativeType,
2642 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002643{
2644 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2645 {
Jamie Madill437fa652016-05-03 15:13:24 -04002646 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002647 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002648 }
2649
Jamie Madill0af26e12015-03-05 19:54:33 -05002650 const Caps &caps = context->getCaps();
2651
Jamie Madill893ab082014-05-16 16:56:10 -04002652 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2653 {
2654 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2655
Jamie Madill0af26e12015-03-05 19:54:33 -05002656 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002657 {
Jamie Madill437fa652016-05-03 15:13:24 -04002658 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002659 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002660 }
2661 }
2662
2663 switch (pname)
2664 {
2665 case GL_TEXTURE_BINDING_2D:
2666 case GL_TEXTURE_BINDING_CUBE_MAP:
2667 case GL_TEXTURE_BINDING_3D:
2668 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002669 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002670 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002671 if (!context->getExtensions().eglStreamConsumerExternal &&
2672 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002673 {
John Bauman18319182016-09-28 14:22:27 -07002674 context->handleError(Error(GL_INVALID_ENUM,
2675 "Neither NV_EGL_stream_consumer_external nor "
2676 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002677 return false;
2678 }
2679 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002680
2681 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2682 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2683 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002684 if (context->getGLState().getReadFramebuffer()->checkStatus(
2685 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002686 {
Jamie Madill437fa652016-05-03 15:13:24 -04002687 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002688 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002689 }
2690
Jamie Madill51f40ec2016-06-15 14:06:00 -04002691 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2692 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002693
2694 if (framebuffer->getReadBufferState() == GL_NONE)
2695 {
2696 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2697 return false;
2698 }
2699
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002700 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002701 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002702 {
Jamie Madill437fa652016-05-03 15:13:24 -04002703 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002704 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002705 }
2706 }
2707 break;
2708
2709 default:
2710 break;
2711 }
2712
2713 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002714 if (*numParams == 0)
2715 {
2716 return false;
2717 }
2718
2719 return true;
2720}
2721
2722bool ValidateRobustStateQuery(ValidationContext *context,
2723 GLenum pname,
2724 GLsizei bufSize,
2725 GLenum *nativeType,
2726 unsigned int *numParams)
2727{
2728 if (!ValidateRobustEntryPoint(context, bufSize))
2729 {
2730 return false;
2731 }
2732
2733 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2734 {
2735 return false;
2736 }
2737
2738 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002739 {
2740 return false;
2741 }
2742
2743 return true;
2744}
2745
Jamie Madillc29968b2016-01-20 11:17:23 -05002746bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2747 GLenum target,
2748 GLint level,
2749 GLenum internalformat,
2750 bool isSubImage,
2751 GLint xoffset,
2752 GLint yoffset,
2753 GLint zoffset,
2754 GLint x,
2755 GLint y,
2756 GLsizei width,
2757 GLsizei height,
2758 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002759 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002760{
Jamie Madill560a8d82014-05-21 13:06:20 -04002761 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2762 {
Jamie Madill437fa652016-05-03 15:13:24 -04002763 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002764 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002765 }
2766
2767 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2768 {
Jamie Madill437fa652016-05-03 15:13:24 -04002769 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002770 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002771 }
2772
2773 if (border != 0)
2774 {
Jamie Madill437fa652016-05-03 15:13:24 -04002775 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002776 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002777 }
2778
2779 if (!ValidMipLevel(context, target, level))
2780 {
Jamie Madill437fa652016-05-03 15:13:24 -04002781 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002782 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002783 }
2784
Jamie Madill51f40ec2016-06-15 14:06:00 -04002785 const auto &state = context->getGLState();
2786 auto readFramebuffer = state.getReadFramebuffer();
2787 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002788 {
Jamie Madill437fa652016-05-03 15:13:24 -04002789 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002790 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002791 }
2792
Jamie Madill51f40ec2016-06-15 14:06:00 -04002793 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002794 {
Jamie Madill437fa652016-05-03 15:13:24 -04002795 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002796 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002797 }
2798
Martin Radev138064f2016-07-15 12:03:41 +03002799 if (readFramebuffer->getReadBufferState() == GL_NONE)
2800 {
2801 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2802 return false;
2803 }
2804
Geoff Langaae65a42014-05-26 12:43:44 -04002805 const gl::Caps &caps = context->getCaps();
2806
Geoff Langaae65a42014-05-26 12:43:44 -04002807 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002808 switch (target)
2809 {
2810 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002811 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002812 break;
2813
2814 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2815 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2816 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2817 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2818 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2819 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002820 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002821 break;
2822
2823 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002824 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002825 break;
2826
2827 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002828 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002829 break;
2830
2831 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002832 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002833 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002834 }
2835
Jamie Madillc29968b2016-01-20 11:17:23 -05002836 gl::Texture *texture =
2837 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002838 if (!texture)
2839 {
Jamie Madill437fa652016-05-03 15:13:24 -04002840 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002841 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002842 }
2843
Geoff Lang69cce582015-09-17 13:20:36 -04002844 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002845 {
Jamie Madill437fa652016-05-03 15:13:24 -04002846 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002847 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002848 }
2849
Geoff Lang5d601382014-07-22 15:14:06 -04002850 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2851
2852 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002853 {
Jamie Madill437fa652016-05-03 15:13:24 -04002854 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002855 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002856 }
2857
Geoff Langa9be0dc2014-12-17 12:34:40 -05002858 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002859 {
Jamie Madill437fa652016-05-03 15:13:24 -04002860 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002861 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002862 }
2863
2864 if (isSubImage)
2865 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002866 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2867 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2868 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002869 {
Jamie Madill437fa652016-05-03 15:13:24 -04002870 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002871 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002872 }
2873 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002874 else
2875 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002876 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002877 {
Jamie Madill437fa652016-05-03 15:13:24 -04002878 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002879 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002880 }
2881
Martin Radev1be913c2016-07-11 17:59:16 +03002882 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002883 {
Jamie Madill437fa652016-05-03 15:13:24 -04002884 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002885 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002886 }
2887
2888 int maxLevelDimension = (maxDimension >> level);
2889 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2890 {
Jamie Madill437fa652016-05-03 15:13:24 -04002891 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002892 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002893 }
2894 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002895
Jamie Madill0c8abca2016-07-22 20:21:26 -04002896 if (textureFormatOut)
2897 {
2898 *textureFormatOut = texture->getFormat(target, level);
2899 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002900 return true;
2901}
2902
Jamie Madillf25855c2015-11-03 11:06:18 -05002903static bool ValidateDrawBase(ValidationContext *context,
2904 GLenum mode,
2905 GLsizei count,
2906 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002907{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002908 switch (mode)
2909 {
2910 case GL_POINTS:
2911 case GL_LINES:
2912 case GL_LINE_LOOP:
2913 case GL_LINE_STRIP:
2914 case GL_TRIANGLES:
2915 case GL_TRIANGLE_STRIP:
2916 case GL_TRIANGLE_FAN:
2917 break;
2918 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002919 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002920 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002921 }
2922
Jamie Madill250d33f2014-06-06 17:09:03 -04002923 if (count < 0)
2924 {
Jamie Madill437fa652016-05-03 15:13:24 -04002925 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002926 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002927 }
2928
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002929 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002930
Jamie Madill250d33f2014-06-06 17:09:03 -04002931 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002932 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002933 {
Jamie Madill437fa652016-05-03 15:13:24 -04002934 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002935 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002936 }
2937
Jamie Madill51f40ec2016-06-15 14:06:00 -04002938 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002939 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002940 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002941 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2942 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2943 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2944 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2945 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2946 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002947 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002948 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2949 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002950 {
2951 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2952 // Section 6.10 of the WebGL 1.0 spec
2953 ERR(
2954 "This ANGLE implementation does not support separate front/back stencil "
2955 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002956 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002957 return false;
2958 }
Jamie Madillac528012014-06-20 13:21:23 -04002959 }
2960
Jamie Madill51f40ec2016-06-15 14:06:00 -04002961 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002962 {
Jamie Madill437fa652016-05-03 15:13:24 -04002963 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002964 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002965 }
2966
Geoff Lang7dd2e102014-11-10 15:19:26 -05002967 gl::Program *program = state.getProgram();
2968 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002969 {
Jamie Madill437fa652016-05-03 15:13:24 -04002970 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002971 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002972 }
2973
Geoff Lang7dd2e102014-11-10 15:19:26 -05002974 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002975 {
Jamie Madill437fa652016-05-03 15:13:24 -04002976 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002977 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002978 }
2979
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002980 // Uniform buffer validation
2981 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2982 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002983 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002984 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002985 const OffsetBindingPointer<Buffer> &uniformBuffer =
2986 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002987
Geoff Lang5d124a62015-09-15 13:03:27 -04002988 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002989 {
2990 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002991 context->handleError(
2992 Error(GL_INVALID_OPERATION,
2993 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002994 return false;
2995 }
2996
Geoff Lang5d124a62015-09-15 13:03:27 -04002997 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002998 if (uniformBufferSize == 0)
2999 {
3000 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003001 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003002 }
3003
Jamie Madill62d31cb2015-09-11 13:25:51 -04003004 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003005 {
3006 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003007 context->handleError(
3008 Error(GL_INVALID_OPERATION,
3009 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003010 return false;
3011 }
3012 }
3013
Jamie Madill250d33f2014-06-06 17:09:03 -04003014 // No-op if zero count
3015 return (count > 0);
3016}
3017
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003018bool ValidateDrawArrays(ValidationContext *context,
3019 GLenum mode,
3020 GLint first,
3021 GLsizei count,
3022 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003023{
Jamie Madillfd716582014-06-06 17:09:04 -04003024 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003028 }
3029
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003030 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003031 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003032 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
3033 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003034 {
3035 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
3036 // that does not match the current transform feedback object's draw mode (if transform feedback
3037 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003038 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003040 }
3041
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003042 if (!ValidateDrawBase(context, mode, count, primcount))
3043 {
3044 return false;
3045 }
3046
3047 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003048 {
3049 return false;
3050 }
3051
3052 return true;
3053}
3054
Geoff Langb1196682014-07-23 13:47:29 -04003055bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003056{
3057 if (primcount < 0)
3058 {
Jamie Madill437fa652016-05-03 15:13:24 -04003059 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003060 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003061 }
3062
Jamie Madill2b976812014-08-25 15:47:49 -04003063 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003064 {
3065 return false;
3066 }
3067
3068 // No-op if zero primitive count
3069 return (primcount > 0);
3070}
3071
Geoff Lang87a93302014-09-16 13:29:43 -04003072static bool ValidateDrawInstancedANGLE(Context *context)
3073{
3074 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003075 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003076
Geoff Lang7dd2e102014-11-10 15:19:26 -05003077 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003078
3079 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003080 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003081 {
3082 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003083 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003084 {
3085 return true;
3086 }
3087 }
3088
Jamie Madill437fa652016-05-03 15:13:24 -04003089 context->handleError(Error(GL_INVALID_OPERATION,
3090 "ANGLE_instanced_arrays requires that at least one active attribute"
3091 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003092 return false;
3093}
3094
3095bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
3096{
3097 if (!ValidateDrawInstancedANGLE(context))
3098 {
3099 return false;
3100 }
3101
3102 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3103}
3104
Jamie Madillf25855c2015-11-03 11:06:18 -05003105bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003106 GLenum mode,
3107 GLsizei count,
3108 GLenum type,
3109 const GLvoid *indices,
3110 GLsizei primcount,
3111 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003112{
Jamie Madill250d33f2014-06-06 17:09:03 -04003113 switch (type)
3114 {
3115 case GL_UNSIGNED_BYTE:
3116 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03003117 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003118 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03003119 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3120 {
3121 context->handleError(Error(GL_INVALID_ENUM));
3122 return false;
3123 }
3124 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003125 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003126 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003127 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003128 }
3129
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003130 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003131
3132 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003133 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003134 {
3135 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3136 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003137 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003138 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003139 }
3140
3141 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003142 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003143 {
Jamie Madill437fa652016-05-03 15:13:24 -04003144 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003145 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003146 }
3147
Jamie Madill2b976812014-08-25 15:47:49 -04003148 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003149 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003150 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003151 {
Jamie Madill437fa652016-05-03 15:13:24 -04003152 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003153 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003154 }
3155
Jamie Madillae3000b2014-08-25 15:47:51 -04003156 if (elementArrayBuffer)
3157 {
3158 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3159
3160 GLint64 offset = reinterpret_cast<GLint64>(indices);
3161 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3162
3163 // check for integer overflows
3164 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3165 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3166 {
Jamie Madill437fa652016-05-03 15:13:24 -04003167 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003168 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003169 }
3170
3171 // Check for reading past the end of the bound buffer object
3172 if (byteCount > elementArrayBuffer->getSize())
3173 {
Jamie Madill437fa652016-05-03 15:13:24 -04003174 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003175 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003176 }
3177 }
3178 else if (!indices)
3179 {
3180 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003181 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003182 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003183 }
3184
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003185 if (!ValidateDrawBase(context, mode, count, primcount))
3186 {
3187 return false;
3188 }
3189
Jamie Madill2b976812014-08-25 15:47:49 -04003190 // Use max index to validate if our vertex buffers are large enough for the pull.
3191 // TODO: offer fast path, with disabled index validation.
3192 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3193 if (elementArrayBuffer)
3194 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003195 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003196 Error error =
3197 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3198 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003199 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003200 {
Jamie Madill437fa652016-05-03 15:13:24 -04003201 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003202 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003203 }
3204 }
3205 else
3206 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003207 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003208 }
3209
Jamie Madille79b1e12015-11-04 16:36:37 -05003210 // If we use an index greater than our maximum supported index range, return an error.
3211 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3212 // return an error if possible here.
3213 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3214 {
Jamie Madill437fa652016-05-03 15:13:24 -04003215 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003216 return false;
3217 }
3218
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003219 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003220 {
3221 return false;
3222 }
3223
Geoff Lang3edfe032015-09-04 16:38:24 -04003224 // No op if there are no real indices in the index data (all are primitive restart).
3225 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003226}
3227
Geoff Langb1196682014-07-23 13:47:29 -04003228bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003229 GLenum mode,
3230 GLsizei count,
3231 GLenum type,
3232 const GLvoid *indices,
3233 GLsizei primcount,
3234 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003235{
3236 if (primcount < 0)
3237 {
Jamie Madill437fa652016-05-03 15:13:24 -04003238 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003239 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003240 }
3241
Jamie Madill2b976812014-08-25 15:47:49 -04003242 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003243 {
3244 return false;
3245 }
3246
3247 // No-op zero primitive count
3248 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003249}
3250
Geoff Lang3edfe032015-09-04 16:38:24 -04003251bool ValidateDrawElementsInstancedANGLE(Context *context,
3252 GLenum mode,
3253 GLsizei count,
3254 GLenum type,
3255 const GLvoid *indices,
3256 GLsizei primcount,
3257 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003258{
3259 if (!ValidateDrawInstancedANGLE(context))
3260 {
3261 return false;
3262 }
3263
3264 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3265}
3266
Geoff Langb1196682014-07-23 13:47:29 -04003267bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003268 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003269{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003270 if (!ValidFramebufferTarget(target))
3271 {
Jamie Madill437fa652016-05-03 15:13:24 -04003272 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003273 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003274 }
3275
3276 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003277 {
3278 return false;
3279 }
3280
Jamie Madill55ec3b12014-07-03 10:38:57 -04003281 if (texture != 0)
3282 {
3283 gl::Texture *tex = context->getTexture(texture);
3284
3285 if (tex == NULL)
3286 {
Jamie Madill437fa652016-05-03 15:13:24 -04003287 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003288 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003289 }
3290
3291 if (level < 0)
3292 {
Jamie Madill437fa652016-05-03 15:13:24 -04003293 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003294 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003295 }
3296 }
3297
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003298 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003299 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003300
Jamie Madill84115c92015-04-23 15:00:07 -04003301 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003302 {
Jamie Madill437fa652016-05-03 15:13:24 -04003303 context->handleError(
3304 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003305 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003306 }
3307
3308 return true;
3309}
3310
Geoff Langb1196682014-07-23 13:47:29 -04003311bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003312 GLenum textarget, GLuint texture, GLint level)
3313{
Geoff Lang95663912015-04-02 15:54:45 -04003314 // 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 +03003315 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3316 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003317 {
Jamie Madill437fa652016-05-03 15:13:24 -04003318 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003319 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003320 }
3321
3322 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003323 {
3324 return false;
3325 }
3326
Jamie Madill55ec3b12014-07-03 10:38:57 -04003327 if (texture != 0)
3328 {
3329 gl::Texture *tex = context->getTexture(texture);
3330 ASSERT(tex);
3331
Jamie Madill2a6564e2014-07-11 09:53:19 -04003332 const gl::Caps &caps = context->getCaps();
3333
Jamie Madill55ec3b12014-07-03 10:38:57 -04003334 switch (textarget)
3335 {
3336 case GL_TEXTURE_2D:
3337 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003338 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003339 {
Jamie Madill437fa652016-05-03 15:13:24 -04003340 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003341 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003342 }
3343 if (tex->getTarget() != GL_TEXTURE_2D)
3344 {
Jamie Madill437fa652016-05-03 15:13:24 -04003345 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003346 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003347 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003348 }
3349 break;
3350
3351 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3352 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3353 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3354 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3355 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3356 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3357 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003358 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003359 {
Jamie Madill437fa652016-05-03 15:13:24 -04003360 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003361 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003362 }
3363 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3364 {
Jamie Madill437fa652016-05-03 15:13:24 -04003365 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003366 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003367 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003368 }
3369 break;
3370
3371 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003372 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003373 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003374 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003375
Jamie Madilla3944d42016-07-22 22:13:26 -04003376 const Format &format = tex->getFormat(textarget, level);
3377 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003378 {
Jamie Madill437fa652016-05-03 15:13:24 -04003379 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003380 return false;
3381 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003382 }
3383
Jamie Madill570f7c82014-07-03 10:38:54 -04003384 return true;
3385}
3386
Geoff Langb1196682014-07-23 13:47:29 -04003387bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003388{
3389 if (program == 0)
3390 {
Jamie Madill437fa652016-05-03 15:13:24 -04003391 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003392 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003393 }
3394
Dian Xiang769769a2015-09-09 15:20:08 -07003395 gl::Program *programObject = GetValidProgram(context, program);
3396 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003397 {
3398 return false;
3399 }
3400
Jamie Madill0063c512014-08-25 15:47:53 -04003401 if (!programObject || !programObject->isLinked())
3402 {
Jamie Madill437fa652016-05-03 15:13:24 -04003403 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003404 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003405 }
3406
Geoff Lang7dd2e102014-11-10 15:19:26 -05003407 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003408 {
Jamie Madill437fa652016-05-03 15:13:24 -04003409 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003410 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003411 }
3412
Jamie Madill0063c512014-08-25 15:47:53 -04003413 return true;
3414}
3415
Geoff Langb1196682014-07-23 13:47:29 -04003416bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003417{
3418 return ValidateGetUniformBase(context, program, location);
3419}
3420
Geoff Langb1196682014-07-23 13:47:29 -04003421bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003422{
Jamie Madill78f41802014-08-25 15:47:55 -04003423 return ValidateGetUniformBase(context, program, location);
3424}
3425
Geoff Langf41d0ee2016-10-07 13:04:23 -04003426static bool ValidateSizedGetUniform(Context *context,
3427 GLuint program,
3428 GLint location,
3429 GLsizei bufSize,
3430 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003431{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003432 if (length)
3433 {
3434 *length = 0;
3435 }
3436
Jamie Madill78f41802014-08-25 15:47:55 -04003437 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003438 {
Jamie Madill78f41802014-08-25 15:47:55 -04003439 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003440 }
3441
Geoff Langf41d0ee2016-10-07 13:04:23 -04003442 if (bufSize < 0)
3443 {
3444 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3445 return false;
3446 }
3447
Jamie Madilla502c742014-08-28 17:19:13 -04003448 gl::Program *programObject = context->getProgram(program);
3449 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003450
Jamie Madill78f41802014-08-25 15:47:55 -04003451 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003452 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3453 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003454 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003455 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003456 context->handleError(
3457 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003458 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003459 }
3460
Geoff Langf41d0ee2016-10-07 13:04:23 -04003461 if (length)
3462 {
3463 // Cast is safe because of comparison to bufSize.
3464 *length = static_cast<GLsizei>(requiredBytes);
3465 }
3466
Jamie Madill0063c512014-08-25 15:47:53 -04003467 return true;
3468}
3469
Geoff Langb1196682014-07-23 13:47:29 -04003470bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003471{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003472 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003473}
3474
Geoff Langb1196682014-07-23 13:47:29 -04003475bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003476{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003477 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3478}
3479
3480bool ValidateGetUniformfvRobustANGLE(Context *context,
3481 GLuint program,
3482 GLint location,
3483 GLsizei bufSize,
3484 GLsizei *length,
3485 GLfloat *params)
3486{
3487 if (!ValidateRobustEntryPoint(context, bufSize))
3488 {
3489 return false;
3490 }
3491
3492 // bufSize is validated in ValidateSizedGetUniform
3493 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3494}
3495
3496bool ValidateGetUniformivRobustANGLE(Context *context,
3497 GLuint program,
3498 GLint location,
3499 GLsizei bufSize,
3500 GLsizei *length,
3501 GLint *params)
3502{
3503 if (!ValidateRobustEntryPoint(context, bufSize))
3504 {
3505 return false;
3506 }
3507
3508 // bufSize is validated in ValidateSizedGetUniform
3509 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3510}
3511
3512bool ValidateGetUniformuivRobustANGLE(Context *context,
3513 GLuint program,
3514 GLint location,
3515 GLsizei bufSize,
3516 GLsizei *length,
3517 GLuint *params)
3518{
3519 if (!ValidateRobustEntryPoint(context, bufSize))
3520 {
3521 return false;
3522 }
3523
3524 if (context->getClientMajorVersion() < 3)
3525 {
3526 context->handleError(
3527 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3528 return false;
3529 }
3530
3531 // bufSize is validated in ValidateSizedGetUniform
3532 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003533}
3534
Austin Kinross08332632015-05-05 13:35:47 -07003535bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3536 const GLenum *attachments, bool defaultFramebuffer)
3537{
3538 if (numAttachments < 0)
3539 {
Jamie Madill437fa652016-05-03 15:13:24 -04003540 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003541 return false;
3542 }
3543
3544 for (GLsizei i = 0; i < numAttachments; ++i)
3545 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003546 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003547 {
3548 if (defaultFramebuffer)
3549 {
Jamie Madill437fa652016-05-03 15:13:24 -04003550 context->handleError(Error(
3551 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003552 return false;
3553 }
3554
3555 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3556 {
Jamie Madill437fa652016-05-03 15:13:24 -04003557 context->handleError(Error(GL_INVALID_OPERATION,
3558 "Requested color attachment is greater than the maximum "
3559 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003560 return false;
3561 }
3562 }
3563 else
3564 {
3565 switch (attachments[i])
3566 {
3567 case GL_DEPTH_ATTACHMENT:
3568 case GL_STENCIL_ATTACHMENT:
3569 case GL_DEPTH_STENCIL_ATTACHMENT:
3570 if (defaultFramebuffer)
3571 {
Jamie Madill437fa652016-05-03 15:13:24 -04003572 context->handleError(
3573 Error(GL_INVALID_ENUM,
3574 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003575 return false;
3576 }
3577 break;
3578 case GL_COLOR:
3579 case GL_DEPTH:
3580 case GL_STENCIL:
3581 if (!defaultFramebuffer)
3582 {
Jamie Madill437fa652016-05-03 15:13:24 -04003583 context->handleError(
3584 Error(GL_INVALID_ENUM,
3585 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003586 return false;
3587 }
3588 break;
3589 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003590 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003591 return false;
3592 }
3593 }
3594 }
3595
3596 return true;
3597}
3598
Austin Kinross6ee1e782015-05-29 17:05:37 -07003599bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3600{
3601 // Note that debug marker calls must not set error state
3602
3603 if (length < 0)
3604 {
3605 return false;
3606 }
3607
3608 if (marker == nullptr)
3609 {
3610 return false;
3611 }
3612
3613 return true;
3614}
3615
3616bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3617{
3618 // Note that debug marker calls must not set error state
3619
3620 if (length < 0)
3621 {
3622 return false;
3623 }
3624
3625 if (length > 0 && marker == nullptr)
3626 {
3627 return false;
3628 }
3629
3630 return true;
3631}
3632
Geoff Langdcab33b2015-07-21 13:03:16 -04003633bool ValidateEGLImageTargetTexture2DOES(Context *context,
3634 egl::Display *display,
3635 GLenum target,
3636 egl::Image *image)
3637{
Geoff Langa8406172015-07-21 16:53:39 -04003638 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3639 {
Jamie Madill437fa652016-05-03 15:13:24 -04003640 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003641 return false;
3642 }
3643
3644 switch (target)
3645 {
3646 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003647 if (!context->getExtensions().eglImage)
3648 {
3649 context->handleError(Error(
3650 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3651 }
3652 break;
3653
3654 case GL_TEXTURE_EXTERNAL_OES:
3655 if (!context->getExtensions().eglImageExternal)
3656 {
3657 context->handleError(Error(
3658 GL_INVALID_ENUM,
3659 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3660 }
Geoff Langa8406172015-07-21 16:53:39 -04003661 break;
3662
3663 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003664 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003665 return false;
3666 }
3667
3668 if (!display->isValidImage(image))
3669 {
Jamie Madill437fa652016-05-03 15:13:24 -04003670 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003671 return false;
3672 }
3673
3674 if (image->getSamples() > 0)
3675 {
Jamie Madill437fa652016-05-03 15:13:24 -04003676 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003677 "cannot create a 2D texture from a multisampled EGL image."));
3678 return false;
3679 }
3680
Jamie Madilla3944d42016-07-22 22:13:26 -04003681 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003682 if (!textureCaps.texturable)
3683 {
Jamie Madill437fa652016-05-03 15:13:24 -04003684 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003685 "EGL image internal format is not supported as a texture."));
3686 return false;
3687 }
3688
Geoff Langdcab33b2015-07-21 13:03:16 -04003689 return true;
3690}
3691
3692bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3693 egl::Display *display,
3694 GLenum target,
3695 egl::Image *image)
3696{
Geoff Langa8406172015-07-21 16:53:39 -04003697 if (!context->getExtensions().eglImage)
3698 {
Jamie Madill437fa652016-05-03 15:13:24 -04003699 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003700 return false;
3701 }
3702
3703 switch (target)
3704 {
3705 case GL_RENDERBUFFER:
3706 break;
3707
3708 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003709 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003710 return false;
3711 }
3712
3713 if (!display->isValidImage(image))
3714 {
Jamie Madill437fa652016-05-03 15:13:24 -04003715 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003716 return false;
3717 }
3718
Jamie Madilla3944d42016-07-22 22:13:26 -04003719 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003720 if (!textureCaps.renderable)
3721 {
Jamie Madill437fa652016-05-03 15:13:24 -04003722 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003723 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3724 return false;
3725 }
3726
Geoff Langdcab33b2015-07-21 13:03:16 -04003727 return true;
3728}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003729
3730bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3731{
Geoff Lang36167ab2015-12-07 10:27:14 -05003732 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003733 {
3734 // The default VAO should always exist
3735 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003736 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003737 return false;
3738 }
3739
3740 return true;
3741}
3742
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003743bool ValidateLinkProgram(Context *context, GLuint program)
3744{
3745 if (context->hasActiveTransformFeedback(program))
3746 {
3747 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003748 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003749 "Cannot link program while program is associated with an active "
3750 "transform feedback object."));
3751 return false;
3752 }
3753 return true;
3754}
3755
Geoff Langc5629752015-12-07 16:29:04 -05003756bool ValidateProgramBinaryBase(Context *context,
3757 GLuint program,
3758 GLenum binaryFormat,
3759 const void *binary,
3760 GLint length)
3761{
3762 Program *programObject = GetValidProgram(context, program);
3763 if (programObject == nullptr)
3764 {
3765 return false;
3766 }
3767
3768 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3769 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3770 programBinaryFormats.end())
3771 {
Jamie Madill437fa652016-05-03 15:13:24 -04003772 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003773 return false;
3774 }
3775
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003776 if (context->hasActiveTransformFeedback(program))
3777 {
3778 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003779 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003780 "Cannot change program binary while program is associated with "
3781 "an active transform feedback object."));
3782 return false;
3783 }
3784
Geoff Langc5629752015-12-07 16:29:04 -05003785 return true;
3786}
3787
3788bool ValidateGetProgramBinaryBase(Context *context,
3789 GLuint program,
3790 GLsizei bufSize,
3791 GLsizei *length,
3792 GLenum *binaryFormat,
3793 void *binary)
3794{
3795 Program *programObject = GetValidProgram(context, program);
3796 if (programObject == nullptr)
3797 {
3798 return false;
3799 }
3800
3801 if (!programObject->isLinked())
3802 {
Jamie Madill437fa652016-05-03 15:13:24 -04003803 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003804 return false;
3805 }
3806
3807 return true;
3808}
Jamie Madillc29968b2016-01-20 11:17:23 -05003809
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003810bool ValidateUseProgram(Context *context, GLuint program)
3811{
3812 if (program != 0)
3813 {
3814 Program *programObject = context->getProgram(program);
3815 if (!programObject)
3816 {
3817 // ES 3.1.0 section 7.3 page 72
3818 if (context->getShader(program))
3819 {
Jamie Madill437fa652016-05-03 15:13:24 -04003820 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003821 Error(GL_INVALID_OPERATION,
3822 "Attempted to use a single shader instead of a shader program."));
3823 return false;
3824 }
3825 else
3826 {
Jamie Madill437fa652016-05-03 15:13:24 -04003827 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003828 return false;
3829 }
3830 }
3831 if (!programObject->isLinked())
3832 {
Jamie Madill437fa652016-05-03 15:13:24 -04003833 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003834 return false;
3835 }
3836 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003837 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003838 {
3839 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003840 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003841 Error(GL_INVALID_OPERATION,
3842 "Cannot change active program while transform feedback is unpaused."));
3843 return false;
3844 }
3845
3846 return true;
3847}
3848
Jamie Madillc29968b2016-01-20 11:17:23 -05003849bool ValidateCopyTexImage2D(ValidationContext *context,
3850 GLenum target,
3851 GLint level,
3852 GLenum internalformat,
3853 GLint x,
3854 GLint y,
3855 GLsizei width,
3856 GLsizei height,
3857 GLint border)
3858{
Martin Radev1be913c2016-07-11 17:59:16 +03003859 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003860 {
3861 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3862 0, x, y, width, height, border);
3863 }
3864
Martin Radev1be913c2016-07-11 17:59:16 +03003865 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003866 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3867 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003868}
Jamie Madillc29968b2016-01-20 11:17:23 -05003869
3870bool ValidateFramebufferRenderbuffer(Context *context,
3871 GLenum target,
3872 GLenum attachment,
3873 GLenum renderbuffertarget,
3874 GLuint renderbuffer)
3875{
3876 if (!ValidFramebufferTarget(target) ||
3877 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3878 {
Jamie Madill437fa652016-05-03 15:13:24 -04003879 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003880 return false;
3881 }
3882
3883 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3884 renderbuffertarget, renderbuffer);
3885}
3886
3887bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3888{
3889 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3890 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3891 {
Jamie Madill437fa652016-05-03 15:13:24 -04003892 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003893 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3894 return false;
3895 }
3896
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003897 ASSERT(context->getGLState().getDrawFramebuffer());
3898 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003899 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3900
3901 // This should come first before the check for the default frame buffer
3902 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3903 // rather than INVALID_OPERATION
3904 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3905 {
3906 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3907
3908 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003909 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3910 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003911 {
3912 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003913 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3914 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3915 // 3.1 is still a bit ambiguous about the error, but future specs are
3916 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003917 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003918 return false;
3919 }
3920 else if (bufs[colorAttachment] >= maxColorAttachment)
3921 {
Jamie Madill437fa652016-05-03 15:13:24 -04003922 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003923 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003924 return false;
3925 }
3926 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3927 frameBufferId != 0)
3928 {
3929 // INVALID_OPERATION-GL is bound to buffer and ith argument
3930 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003931 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003932 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3933 return false;
3934 }
3935 }
3936
3937 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3938 // and n is not 1 or bufs is bound to value other than BACK and NONE
3939 if (frameBufferId == 0)
3940 {
3941 if (n != 1)
3942 {
Jamie Madill437fa652016-05-03 15:13:24 -04003943 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003944 "n must be 1 when GL is bound to the default framebuffer"));
3945 return false;
3946 }
3947
3948 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3949 {
Jamie Madill437fa652016-05-03 15:13:24 -04003950 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003951 GL_INVALID_OPERATION,
3952 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3953 return false;
3954 }
3955 }
3956
3957 return true;
3958}
3959
3960bool ValidateCopyTexSubImage2D(Context *context,
3961 GLenum target,
3962 GLint level,
3963 GLint xoffset,
3964 GLint yoffset,
3965 GLint x,
3966 GLint y,
3967 GLsizei width,
3968 GLsizei height)
3969{
Martin Radev1be913c2016-07-11 17:59:16 +03003970 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003971 {
3972 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3973 yoffset, x, y, width, height, 0);
3974 }
3975
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003976 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3977 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003978}
3979
Geoff Lang496c02d2016-10-20 11:38:11 -07003980bool ValidateGetBufferPointervBase(Context *context,
3981 GLenum target,
3982 GLenum pname,
3983 GLsizei *length,
3984 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003985{
Geoff Lang496c02d2016-10-20 11:38:11 -07003986 if (length)
3987 {
3988 *length = 0;
3989 }
3990
3991 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3992 {
3993 context->handleError(
3994 Error(GL_INVALID_OPERATION,
3995 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
3996 return false;
3997 }
3998
Olli Etuaho4f667482016-03-30 15:56:35 +03003999 if (!ValidBufferTarget(context, target))
4000 {
Jamie Madill437fa652016-05-03 15:13:24 -04004001 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004002 return false;
4003 }
4004
Geoff Lang496c02d2016-10-20 11:38:11 -07004005 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004006 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004007 case GL_BUFFER_MAP_POINTER:
4008 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004009
Geoff Lang496c02d2016-10-20 11:38:11 -07004010 default:
4011 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4012 return false;
4013 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004014
4015 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4016 // target bound to zero generate an INVALID_OPERATION error."
4017 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004018 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004019 {
Jamie Madill437fa652016-05-03 15:13:24 -04004020 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004021 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4022 return false;
4023 }
4024
Geoff Lang496c02d2016-10-20 11:38:11 -07004025 if (length)
4026 {
4027 *length = 1;
4028 }
4029
Olli Etuaho4f667482016-03-30 15:56:35 +03004030 return true;
4031}
4032
4033bool ValidateUnmapBufferBase(Context *context, GLenum target)
4034{
4035 if (!ValidBufferTarget(context, target))
4036 {
Jamie Madill437fa652016-05-03 15:13:24 -04004037 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004038 return false;
4039 }
4040
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004041 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004042
4043 if (buffer == nullptr || !buffer->isMapped())
4044 {
Jamie Madill437fa652016-05-03 15:13:24 -04004045 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004046 return false;
4047 }
4048
4049 return true;
4050}
4051
4052bool ValidateMapBufferRangeBase(Context *context,
4053 GLenum target,
4054 GLintptr offset,
4055 GLsizeiptr length,
4056 GLbitfield access)
4057{
4058 if (!ValidBufferTarget(context, target))
4059 {
Jamie Madill437fa652016-05-03 15:13:24 -04004060 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004061 return false;
4062 }
4063
4064 if (offset < 0 || length < 0)
4065 {
Jamie Madill437fa652016-05-03 15:13:24 -04004066 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004067 return false;
4068 }
4069
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004070 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004071
4072 if (!buffer)
4073 {
Jamie Madill437fa652016-05-03 15:13:24 -04004074 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004075 return false;
4076 }
4077
4078 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004079 CheckedNumeric<size_t> checkedOffset(offset);
4080 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004081
Jamie Madille2e406c2016-06-02 13:04:10 -04004082 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004083 {
Jamie Madill437fa652016-05-03 15:13:24 -04004084 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004085 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4086 return false;
4087 }
4088
4089 // Check for invalid bits in the mask
4090 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4091 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4092 GL_MAP_UNSYNCHRONIZED_BIT;
4093
4094 if (access & ~(allAccessBits))
4095 {
Jamie Madill437fa652016-05-03 15:13:24 -04004096 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004097 return false;
4098 }
4099
4100 if (length == 0)
4101 {
Jamie Madill437fa652016-05-03 15:13:24 -04004102 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004103 return false;
4104 }
4105
4106 if (buffer->isMapped())
4107 {
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004109 return false;
4110 }
4111
4112 // Check for invalid bit combinations
4113 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4114 {
Jamie Madill437fa652016-05-03 15:13:24 -04004115 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004116 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4117 return false;
4118 }
4119
4120 GLbitfield writeOnlyBits =
4121 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4122
4123 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4124 {
Jamie Madill437fa652016-05-03 15:13:24 -04004125 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004126 "Invalid access bits when mapping buffer for reading: 0x%X.",
4127 access));
4128 return false;
4129 }
4130
4131 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4132 {
Jamie Madill437fa652016-05-03 15:13:24 -04004133 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004134 GL_INVALID_OPERATION,
4135 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4136 return false;
4137 }
4138 return true;
4139}
4140
4141bool ValidateFlushMappedBufferRangeBase(Context *context,
4142 GLenum target,
4143 GLintptr offset,
4144 GLsizeiptr length)
4145{
4146 if (offset < 0 || length < 0)
4147 {
Jamie Madill437fa652016-05-03 15:13:24 -04004148 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004149 return false;
4150 }
4151
4152 if (!ValidBufferTarget(context, target))
4153 {
Jamie Madill437fa652016-05-03 15:13:24 -04004154 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004155 return false;
4156 }
4157
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004158 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004159
4160 if (buffer == nullptr)
4161 {
Jamie Madill437fa652016-05-03 15:13:24 -04004162 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004163 return false;
4164 }
4165
4166 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4167 {
Jamie Madill437fa652016-05-03 15:13:24 -04004168 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004169 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4170 return false;
4171 }
4172
4173 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004174 CheckedNumeric<size_t> checkedOffset(offset);
4175 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004176
Jamie Madille2e406c2016-06-02 13:04:10 -04004177 if (!checkedSize.IsValid() ||
4178 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004179 {
Jamie Madill437fa652016-05-03 15:13:24 -04004180 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004181 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4182 return false;
4183 }
4184
4185 return true;
4186}
4187
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004188bool ValidateGenerateMipmap(Context *context, GLenum target)
4189{
4190 if (!ValidTextureTarget(context, target))
4191 {
4192 context->handleError(Error(GL_INVALID_ENUM));
4193 return false;
4194 }
4195
4196 Texture *texture = context->getTargetTexture(target);
4197
4198 if (texture == nullptr)
4199 {
4200 context->handleError(Error(GL_INVALID_OPERATION));
4201 return false;
4202 }
4203
4204 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4205
4206 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4207 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4208 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4209 {
4210 context->handleError(Error(GL_INVALID_OPERATION));
4211 return false;
4212 }
4213
Jamie Madilla3944d42016-07-22 22:13:26 -04004214 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4215 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4216 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004217
4218 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4219 // unsized formats or that are color renderable and filterable. Since we do not track if
4220 // the texture was created with sized or unsized format (only sized formats are stored),
4221 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4222 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4223 // textures since they're the only texture format that can be created with unsized formats
4224 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4225 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004226 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4227 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004228 {
4229 context->handleError(Error(GL_INVALID_OPERATION));
4230 return false;
4231 }
4232
4233 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004234 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004235 {
4236 context->handleError(Error(GL_INVALID_OPERATION));
4237 return false;
4238 }
4239
4240 // Non-power of 2 ES2 check
4241 if (!context->getExtensions().textureNPOT &&
4242 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4243 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4244 {
Martin Radev1be913c2016-07-11 17:59:16 +03004245 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004246 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
4247 context->handleError(Error(GL_INVALID_OPERATION));
4248 return false;
4249 }
4250
4251 // Cube completeness check
4252 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4253 {
4254 context->handleError(Error(GL_INVALID_OPERATION));
4255 return false;
4256 }
4257
4258 return true;
4259}
4260
Olli Etuaho41997e72016-03-10 13:38:39 +02004261bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4262{
4263 return ValidateGenOrDelete(context, n);
4264}
4265
4266bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4267{
4268 return ValidateGenOrDelete(context, n);
4269}
4270
4271bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4272{
4273 return ValidateGenOrDelete(context, n);
4274}
4275
4276bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4277{
4278 return ValidateGenOrDelete(context, n);
4279}
4280
4281bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4282{
4283 return ValidateGenOrDelete(context, n);
4284}
4285
4286bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4287{
4288 return ValidateGenOrDelete(context, n);
4289}
4290
4291bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4292{
4293 return ValidateGenOrDelete(context, n);
4294}
4295
4296bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4297{
4298 return ValidateGenOrDelete(context, n);
4299}
4300
4301bool ValidateGenOrDelete(Context *context, GLint n)
4302{
4303 if (n < 0)
4304 {
Jamie Madill437fa652016-05-03 15:13:24 -04004305 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004306 return false;
4307 }
4308 return true;
4309}
4310
Geoff Langf41a7152016-09-19 15:11:17 -04004311bool ValidateEnable(Context *context, GLenum cap)
4312{
4313 if (!ValidCap(context, cap, false))
4314 {
4315 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4316 return false;
4317 }
4318
4319 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4320 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4321 {
4322 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4323 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4324
4325 // We also output an error message to the debugger window if tracing is active, so that
4326 // developers can see the error message.
4327 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004328 return false;
4329 }
4330
4331 return true;
4332}
4333
4334bool ValidateDisable(Context *context, GLenum cap)
4335{
4336 if (!ValidCap(context, cap, false))
4337 {
4338 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4339 return false;
4340 }
4341
4342 return true;
4343}
4344
4345bool ValidateIsEnabled(Context *context, GLenum cap)
4346{
4347 if (!ValidCap(context, cap, true))
4348 {
4349 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4350 return false;
4351 }
4352
4353 return true;
4354}
4355
Geoff Langff5b2d52016-09-07 11:32:23 -04004356bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4357{
4358 if (!context->getExtensions().robustClientMemory)
4359 {
4360 context->handleError(
4361 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4362 return false;
4363 }
4364
4365 if (bufSize < 0)
4366 {
4367 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4368 return false;
4369 }
4370
4371 return true;
4372}
4373
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004374bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4375{
4376 if (bufSize < numParams)
4377 {
4378 context->handleError(Error(GL_INVALID_OPERATION,
4379 "%u parameters are required but %i were provided.", numParams,
4380 bufSize));
4381 return false;
4382 }
4383
4384 return true;
4385}
4386
Geoff Langff5b2d52016-09-07 11:32:23 -04004387bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4388 GLenum target,
4389 GLenum attachment,
4390 GLenum pname,
4391 GLsizei *numParams)
4392{
4393 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4394 *numParams = 1;
4395
4396 if (!ValidFramebufferTarget(target))
4397 {
4398 context->handleError(Error(GL_INVALID_ENUM));
4399 return false;
4400 }
4401
4402 int clientVersion = context->getClientMajorVersion();
4403
4404 switch (pname)
4405 {
4406 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4407 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4408 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4409 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4410 break;
4411
4412 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4413 if (clientVersion < 3 && !context->getExtensions().sRGB)
4414 {
4415 context->handleError(Error(GL_INVALID_ENUM));
4416 return false;
4417 }
4418 break;
4419
4420 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4421 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4422 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4423 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4424 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4425 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4426 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4427 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4428 if (clientVersion < 3)
4429 {
4430 context->handleError(Error(GL_INVALID_ENUM));
4431 return false;
4432 }
4433 break;
4434
4435 default:
4436 context->handleError(Error(GL_INVALID_ENUM));
4437 return false;
4438 }
4439
4440 // Determine if the attachment is a valid enum
4441 switch (attachment)
4442 {
4443 case GL_BACK:
4444 case GL_FRONT:
4445 case GL_DEPTH:
4446 case GL_STENCIL:
4447 case GL_DEPTH_STENCIL_ATTACHMENT:
4448 if (clientVersion < 3)
4449 {
4450 context->handleError(Error(GL_INVALID_ENUM));
4451 return false;
4452 }
4453 break;
4454
4455 case GL_DEPTH_ATTACHMENT:
4456 case GL_STENCIL_ATTACHMENT:
4457 break;
4458
4459 default:
4460 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4461 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4462 {
4463 context->handleError(Error(GL_INVALID_ENUM));
4464 return false;
4465 }
4466 break;
4467 }
4468
4469 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4470 ASSERT(framebuffer);
4471
4472 if (framebuffer->id() == 0)
4473 {
4474 if (clientVersion < 3)
4475 {
4476 context->handleError(Error(GL_INVALID_OPERATION));
4477 return false;
4478 }
4479
4480 switch (attachment)
4481 {
4482 case GL_BACK:
4483 case GL_DEPTH:
4484 case GL_STENCIL:
4485 break;
4486
4487 default:
4488 context->handleError(Error(GL_INVALID_OPERATION));
4489 return false;
4490 }
4491 }
4492 else
4493 {
4494 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4495 {
4496 // Valid attachment query
4497 }
4498 else
4499 {
4500 switch (attachment)
4501 {
4502 case GL_DEPTH_ATTACHMENT:
4503 case GL_STENCIL_ATTACHMENT:
4504 break;
4505
4506 case GL_DEPTH_STENCIL_ATTACHMENT:
4507 if (!framebuffer->hasValidDepthStencil())
4508 {
4509 context->handleError(Error(GL_INVALID_OPERATION));
4510 return false;
4511 }
4512 break;
4513
4514 default:
4515 context->handleError(Error(GL_INVALID_OPERATION));
4516 return false;
4517 }
4518 }
4519 }
4520
4521 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4522 if (attachmentObject)
4523 {
4524 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4525 attachmentObject->type() == GL_TEXTURE ||
4526 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4527
4528 switch (pname)
4529 {
4530 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4531 if (attachmentObject->type() != GL_RENDERBUFFER &&
4532 attachmentObject->type() != GL_TEXTURE)
4533 {
4534 context->handleError(Error(GL_INVALID_ENUM));
4535 return false;
4536 }
4537 break;
4538
4539 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4540 if (attachmentObject->type() != GL_TEXTURE)
4541 {
4542 context->handleError(Error(GL_INVALID_ENUM));
4543 return false;
4544 }
4545 break;
4546
4547 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4548 if (attachmentObject->type() != GL_TEXTURE)
4549 {
4550 context->handleError(Error(GL_INVALID_ENUM));
4551 return false;
4552 }
4553 break;
4554
4555 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4556 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4557 {
4558 context->handleError(Error(GL_INVALID_OPERATION));
4559 return false;
4560 }
4561 break;
4562
4563 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4564 if (attachmentObject->type() != GL_TEXTURE)
4565 {
4566 context->handleError(Error(GL_INVALID_ENUM));
4567 return false;
4568 }
4569 break;
4570
4571 default:
4572 break;
4573 }
4574 }
4575 else
4576 {
4577 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4578 // is NONE, then querying any other pname will generate INVALID_ENUM.
4579
4580 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4581 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4582 // INVALID_OPERATION for all other pnames
4583
4584 switch (pname)
4585 {
4586 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4587 break;
4588
4589 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4590 if (clientVersion < 3)
4591 {
4592 context->handleError(Error(GL_INVALID_ENUM));
4593 return false;
4594 }
4595 break;
4596
4597 default:
4598 if (clientVersion < 3)
4599 {
4600 context->handleError(Error(GL_INVALID_ENUM));
4601 return false;
4602 }
4603 else
4604 {
4605 context->handleError(Error(GL_INVALID_OPERATION));
4606 return false;
4607 }
4608 }
4609 }
4610
4611 return true;
4612}
4613
4614bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4615 GLenum target,
4616 GLenum attachment,
4617 GLenum pname,
4618 GLsizei bufSize,
4619 GLsizei *numParams)
4620{
4621 if (!ValidateRobustEntryPoint(context, bufSize))
4622 {
4623 return false;
4624 }
4625
4626 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4627 {
4628 return false;
4629 }
4630
4631 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4632 {
4633 return false;
4634 }
4635
4636 return true;
4637}
4638
4639bool ValidateGetBufferParameteriv(ValidationContext *context,
4640 GLenum target,
4641 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004642 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004643{
Geoff Langebebe1c2016-10-14 12:01:31 -04004644 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004645}
4646
4647bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4648 GLenum target,
4649 GLenum pname,
4650 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004651 GLsizei *length,
4652 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004653{
4654 if (!ValidateRobustEntryPoint(context, bufSize))
4655 {
4656 return false;
4657 }
4658
Geoff Langebebe1c2016-10-14 12:01:31 -04004659 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004660 {
4661 return false;
4662 }
4663
Geoff Langebebe1c2016-10-14 12:01:31 -04004664 if (!ValidateRobustBufferSize(context, bufSize, *length))
4665 {
4666 return false;
4667 }
4668
4669 return true;
4670}
4671
4672bool ValidateGetBufferParameteri64v(ValidationContext *context,
4673 GLenum target,
4674 GLenum pname,
4675 GLint64 *params)
4676{
4677 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4678}
4679
4680bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4681 GLenum target,
4682 GLenum pname,
4683 GLsizei bufSize,
4684 GLsizei *length,
4685 GLint64 *params)
4686{
4687 if (!ValidateRobustEntryPoint(context, bufSize))
4688 {
4689 return false;
4690 }
4691
4692 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4693 {
4694 return false;
4695 }
4696
4697 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004698 {
4699 return false;
4700 }
4701
4702 return true;
4703}
4704
4705bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4706{
4707 // Currently, all GetProgramiv queries return 1 parameter
4708 *numParams = 1;
4709
4710 Program *programObject = GetValidProgram(context, program);
4711 if (!programObject)
4712 {
4713 return false;
4714 }
4715
4716 switch (pname)
4717 {
4718 case GL_DELETE_STATUS:
4719 case GL_LINK_STATUS:
4720 case GL_VALIDATE_STATUS:
4721 case GL_INFO_LOG_LENGTH:
4722 case GL_ATTACHED_SHADERS:
4723 case GL_ACTIVE_ATTRIBUTES:
4724 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4725 case GL_ACTIVE_UNIFORMS:
4726 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4727 break;
4728
4729 case GL_PROGRAM_BINARY_LENGTH:
4730 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4731 {
4732 context->handleError(Error(GL_INVALID_ENUM,
4733 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4734 "GL_OES_get_program_binary or ES 3.0."));
4735 return false;
4736 }
4737 break;
4738
4739 case GL_ACTIVE_UNIFORM_BLOCKS:
4740 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4741 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4742 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4743 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4744 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4745 if (context->getClientMajorVersion() < 3)
4746 {
4747 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4748 return false;
4749 }
4750 break;
4751
4752 default:
4753 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4754 return false;
4755 }
4756
4757 return true;
4758}
4759
4760bool ValidateGetProgramivRobustANGLE(Context *context,
4761 GLuint program,
4762 GLenum pname,
4763 GLsizei bufSize,
4764 GLsizei *numParams)
4765{
4766 if (!ValidateRobustEntryPoint(context, bufSize))
4767 {
4768 return false;
4769 }
4770
4771 if (!ValidateGetProgramiv(context, program, pname, numParams))
4772 {
4773 return false;
4774 }
4775
4776 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4777 {
4778 return false;
4779 }
4780
4781 return true;
4782}
4783
Geoff Lang740d9022016-10-07 11:20:52 -04004784bool ValidateGetRenderbufferParameteriv(Context *context,
4785 GLenum target,
4786 GLenum pname,
4787 GLint *params)
4788{
4789 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4790}
4791
4792bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4793 GLenum target,
4794 GLenum pname,
4795 GLsizei bufSize,
4796 GLsizei *length,
4797 GLint *params)
4798{
4799 if (!ValidateRobustEntryPoint(context, bufSize))
4800 {
4801 return false;
4802 }
4803
4804 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4805 {
4806 return false;
4807 }
4808
4809 if (!ValidateRobustBufferSize(context, bufSize, *length))
4810 {
4811 return false;
4812 }
4813
4814 return true;
4815}
4816
Geoff Langd7d0ed32016-10-07 11:33:51 -04004817bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4818{
4819 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4820}
4821
4822bool ValidateGetShaderivRobustANGLE(Context *context,
4823 GLuint shader,
4824 GLenum pname,
4825 GLsizei bufSize,
4826 GLsizei *length,
4827 GLint *params)
4828{
4829 if (!ValidateRobustEntryPoint(context, bufSize))
4830 {
4831 return false;
4832 }
4833
4834 if (!ValidateGetShaderivBase(context, shader, pname, length))
4835 {
4836 return false;
4837 }
4838
4839 if (!ValidateRobustBufferSize(context, bufSize, *length))
4840 {
4841 return false;
4842 }
4843
4844 return true;
4845}
4846
Geoff Langc1984ed2016-10-07 12:41:00 -04004847bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4848{
4849 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4850}
4851
4852bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4853 GLenum target,
4854 GLenum pname,
4855 GLsizei bufSize,
4856 GLsizei *length,
4857 GLfloat *params)
4858{
4859 if (!ValidateRobustEntryPoint(context, bufSize))
4860 {
4861 return false;
4862 }
4863
4864 if (!ValidateGetTexParameterBase(context, target, pname, length))
4865 {
4866 return false;
4867 }
4868
4869 if (!ValidateRobustBufferSize(context, bufSize, *length))
4870 {
4871 return false;
4872 }
4873
4874 return true;
4875}
4876
4877bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4878{
4879 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4880}
4881
4882bool ValidateGetTexParameterivRobustANGLE(Context *context,
4883 GLenum target,
4884 GLenum pname,
4885 GLsizei bufSize,
4886 GLsizei *length,
4887 GLint *params)
4888{
4889 if (!ValidateRobustEntryPoint(context, bufSize))
4890 {
4891 return false;
4892 }
4893
4894 if (!ValidateGetTexParameterBase(context, target, pname, length))
4895 {
4896 return false;
4897 }
4898
4899 if (!ValidateRobustBufferSize(context, bufSize, *length))
4900 {
4901 return false;
4902 }
4903
4904 return true;
4905}
4906
4907bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4908{
4909 return ValidateTexParameterBase(context, target, pname, -1, &param);
4910}
4911
4912bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4913{
4914 return ValidateTexParameterBase(context, target, pname, -1, params);
4915}
4916
4917bool ValidateTexParameterfvRobustANGLE(Context *context,
4918 GLenum target,
4919 GLenum pname,
4920 GLsizei bufSize,
4921 const GLfloat *params)
4922{
4923 if (!ValidateRobustEntryPoint(context, bufSize))
4924 {
4925 return false;
4926 }
4927
4928 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4929}
4930
4931bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4932{
4933 return ValidateTexParameterBase(context, target, pname, -1, &param);
4934}
4935
4936bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4937{
4938 return ValidateTexParameterBase(context, target, pname, -1, params);
4939}
4940
4941bool ValidateTexParameterivRobustANGLE(Context *context,
4942 GLenum target,
4943 GLenum pname,
4944 GLsizei bufSize,
4945 const GLint *params)
4946{
4947 if (!ValidateRobustEntryPoint(context, bufSize))
4948 {
4949 return false;
4950 }
4951
4952 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4953}
4954
4955bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4956{
4957 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4958}
4959
4960bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4961 GLuint sampler,
4962 GLenum pname,
4963 GLuint bufSize,
4964 GLsizei *length,
4965 GLfloat *params)
4966{
4967 if (!ValidateRobustEntryPoint(context, bufSize))
4968 {
4969 return false;
4970 }
4971
4972 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4973 {
4974 return false;
4975 }
4976
4977 if (!ValidateRobustBufferSize(context, bufSize, *length))
4978 {
4979 return false;
4980 }
4981
4982 return true;
4983}
4984
4985bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4986{
4987 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4988}
4989
4990bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4991 GLuint sampler,
4992 GLenum pname,
4993 GLuint bufSize,
4994 GLsizei *length,
4995 GLint *params)
4996{
4997 if (!ValidateRobustEntryPoint(context, bufSize))
4998 {
4999 return false;
5000 }
5001
5002 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5003 {
5004 return false;
5005 }
5006
5007 if (!ValidateRobustBufferSize(context, bufSize, *length))
5008 {
5009 return false;
5010 }
5011
5012 return true;
5013}
5014
5015bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5016{
5017 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5018}
5019
5020bool ValidateSamplerParameterfv(Context *context,
5021 GLuint sampler,
5022 GLenum pname,
5023 const GLfloat *params)
5024{
5025 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5026}
5027
5028bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5029 GLuint sampler,
5030 GLenum pname,
5031 GLsizei bufSize,
5032 const GLfloat *params)
5033{
5034 if (!ValidateRobustEntryPoint(context, bufSize))
5035 {
5036 return false;
5037 }
5038
5039 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5040}
5041
5042bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5043{
5044 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5045}
5046
5047bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5048{
5049 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5050}
5051
5052bool ValidateSamplerParameterivRobustANGLE(Context *context,
5053 GLuint sampler,
5054 GLenum pname,
5055 GLsizei bufSize,
5056 const GLint *params)
5057{
5058 if (!ValidateRobustEntryPoint(context, bufSize))
5059 {
5060 return false;
5061 }
5062
5063 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5064}
5065
Geoff Lang0b031062016-10-13 14:30:04 -04005066bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5067{
5068 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5069}
5070
5071bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5072 GLuint index,
5073 GLenum pname,
5074 GLsizei bufSize,
5075 GLsizei *length,
5076 GLfloat *params)
5077{
5078 if (!ValidateRobustEntryPoint(context, bufSize))
5079 {
5080 return false;
5081 }
5082
5083 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5084 {
5085 return false;
5086 }
5087
5088 if (!ValidateRobustBufferSize(context, bufSize, *length))
5089 {
5090 return false;
5091 }
5092
5093 return true;
5094}
5095
5096bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5097{
5098 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5099}
5100
5101bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5102 GLuint index,
5103 GLenum pname,
5104 GLsizei bufSize,
5105 GLsizei *length,
5106 GLint *params)
5107{
5108 if (!ValidateRobustEntryPoint(context, bufSize))
5109 {
5110 return false;
5111 }
5112
5113 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5114 {
5115 return false;
5116 }
5117
5118 if (!ValidateRobustBufferSize(context, bufSize, *length))
5119 {
5120 return false;
5121 }
5122
5123 return true;
5124}
5125
5126bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5127{
5128 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5129}
5130
5131bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5132 GLuint index,
5133 GLenum pname,
5134 GLsizei bufSize,
5135 GLsizei *length,
5136 void **pointer)
5137{
5138 if (!ValidateRobustEntryPoint(context, bufSize))
5139 {
5140 return false;
5141 }
5142
5143 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5144 {
5145 return false;
5146 }
5147
5148 if (!ValidateRobustBufferSize(context, bufSize, *length))
5149 {
5150 return false;
5151 }
5152
5153 return true;
5154}
5155
5156bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5157{
5158 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5159}
5160
5161bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5162 GLuint index,
5163 GLenum pname,
5164 GLsizei bufSize,
5165 GLsizei *length,
5166 GLint *params)
5167{
5168 if (!ValidateRobustEntryPoint(context, bufSize))
5169 {
5170 return false;
5171 }
5172
5173 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5174 {
5175 return false;
5176 }
5177
5178 if (!ValidateRobustBufferSize(context, bufSize, *length))
5179 {
5180 return false;
5181 }
5182
5183 return true;
5184}
5185
5186bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5187{
5188 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5189}
5190
5191bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5192 GLuint index,
5193 GLenum pname,
5194 GLsizei bufSize,
5195 GLsizei *length,
5196 GLuint *params)
5197{
5198 if (!ValidateRobustEntryPoint(context, bufSize))
5199 {
5200 return false;
5201 }
5202
5203 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5204 {
5205 return false;
5206 }
5207
5208 if (!ValidateRobustBufferSize(context, bufSize, *length))
5209 {
5210 return false;
5211 }
5212
5213 return true;
5214}
5215
Geoff Lang6899b872016-10-14 11:30:13 -04005216bool ValidateGetActiveUniformBlockiv(Context *context,
5217 GLuint program,
5218 GLuint uniformBlockIndex,
5219 GLenum pname,
5220 GLint *params)
5221{
5222 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5223}
5224
5225bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5226 GLuint program,
5227 GLuint uniformBlockIndex,
5228 GLenum pname,
5229 GLsizei bufSize,
5230 GLsizei *length,
5231 GLint *params)
5232{
5233 if (!ValidateRobustEntryPoint(context, bufSize))
5234 {
5235 return false;
5236 }
5237
5238 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5239 {
5240 return false;
5241 }
5242
5243 if (!ValidateRobustBufferSize(context, bufSize, *length))
5244 {
5245 return false;
5246 }
5247
5248 return true;
5249}
5250
Geoff Lang0a9661f2016-10-20 10:59:20 -07005251bool ValidateGetInternalFormativ(Context *context,
5252 GLenum target,
5253 GLenum internalformat,
5254 GLenum pname,
5255 GLsizei bufSize,
5256 GLint *params)
5257{
5258 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5259 nullptr);
5260}
5261
5262bool ValidateGetInternalFormativRobustANGLE(Context *context,
5263 GLenum target,
5264 GLenum internalformat,
5265 GLenum pname,
5266 GLsizei bufSize,
5267 GLsizei *length,
5268 GLint *params)
5269{
5270 if (!ValidateRobustEntryPoint(context, bufSize))
5271 {
5272 return false;
5273 }
5274
5275 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5276 {
5277 return false;
5278 }
5279
5280 if (!ValidateRobustBufferSize(context, bufSize, *length))
5281 {
5282 return false;
5283 }
5284
5285 return true;
5286}
5287
Jamie Madillc29968b2016-01-20 11:17:23 -05005288} // namespace gl