blob: 96b77895d804abea7ee45f71859aaa5178d6faa1 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700165 case GL_FRAMEBUFFER_SRGB_EXT:
166 return context->getExtensions().sRGBWriteControl;
167
Geoff Langf41a7152016-09-19 15:11:17 -0400168 default:
169 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500170 }
171}
172
Geoff Lang62fce5b2016-09-30 10:46:35 -0400173bool ValidateReadPixelsBase(ValidationContext *context,
174 GLint x,
175 GLint y,
176 GLsizei width,
177 GLsizei height,
178 GLenum format,
179 GLenum type,
180 GLsizei bufSize,
181 GLsizei *length,
182 GLvoid *pixels)
183{
184 if (length != nullptr)
185 {
186 *length = 0;
187 }
188
189 if (width < 0 || height < 0)
190 {
191 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
192 return false;
193 }
194
195 auto readFramebuffer = context->getGLState().getReadFramebuffer();
196
197 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
198 {
199 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
200 return false;
201 }
202
203 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
204 {
205 context->handleError(Error(GL_INVALID_OPERATION));
206 return false;
207 }
208
209 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
210 ASSERT(framebuffer);
211
212 if (framebuffer->getReadBufferState() == GL_NONE)
213 {
214 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
215 return false;
216 }
217
218 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
219 if (!readBuffer)
220 {
221 context->handleError(Error(GL_INVALID_OPERATION));
222 return false;
223 }
224
225 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
226 GLenum currentType = framebuffer->getImplementationColorReadType();
227 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
228
229 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
230 bool validFormatTypeCombination =
231 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
232
233 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
234 {
235 context->handleError(Error(GL_INVALID_OPERATION));
236 return false;
237 }
238
239 // Check for pixel pack buffer related API errors
240 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
241 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
242 {
243 // ...the buffer object's data store is currently mapped.
244 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
245 return false;
246 }
247
248 // .. the data would be packed to the buffer object such that the memory writes required
249 // would exceed the data store size.
250 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
251 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
252 const gl::Extents size(width, height, 1);
253 const auto &pack = context->getGLState().getPackState();
254
255 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
256 if (endByteOrErr.isError())
257 {
258 context->handleError(endByteOrErr.getError());
259 return false;
260 }
261
262 size_t endByte = endByteOrErr.getResult();
263 if (bufSize >= 0)
264 {
265
266 if (static_cast<size_t>(bufSize) < endByte)
267 {
268 context->handleError(
269 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
270 return false;
271 }
272 }
273
274 if (pixelPackBuffer != nullptr)
275 {
276 CheckedNumeric<size_t> checkedEndByte(endByte);
277 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
278 checkedEndByte += checkedOffset;
279
280 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
281 {
282 // Overflow past the end of the buffer
283 context->handleError(
284 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
285 return false;
286 }
287 }
288
289 if (length != nullptr)
290 {
291 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
292 {
293 context->handleError(
294 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
295 return false;
296 }
297
298 *length = static_cast<GLsizei>(endByte);
299 }
300
301 return true;
302}
303
Geoff Lang740d9022016-10-07 11:20:52 -0400304bool ValidateGetRenderbufferParameterivBase(Context *context,
305 GLenum target,
306 GLenum pname,
307 GLsizei *length)
308{
309 if (length)
310 {
311 *length = 0;
312 }
313
314 if (target != GL_RENDERBUFFER)
315 {
316 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
317 return false;
318 }
319
320 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
321 if (renderbuffer == nullptr)
322 {
323 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
324 return false;
325 }
326
327 switch (pname)
328 {
329 case GL_RENDERBUFFER_WIDTH:
330 case GL_RENDERBUFFER_HEIGHT:
331 case GL_RENDERBUFFER_INTERNAL_FORMAT:
332 case GL_RENDERBUFFER_RED_SIZE:
333 case GL_RENDERBUFFER_GREEN_SIZE:
334 case GL_RENDERBUFFER_BLUE_SIZE:
335 case GL_RENDERBUFFER_ALPHA_SIZE:
336 case GL_RENDERBUFFER_DEPTH_SIZE:
337 case GL_RENDERBUFFER_STENCIL_SIZE:
338 break;
339
340 case GL_RENDERBUFFER_SAMPLES_ANGLE:
341 if (!context->getExtensions().framebufferMultisample)
342 {
343 context->handleError(
344 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
345 return false;
346 }
347 break;
348
349 default:
350 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
351 return false;
352 }
353
354 if (length)
355 {
356 *length = 1;
357 }
358 return true;
359}
360
Geoff Langd7d0ed32016-10-07 11:33:51 -0400361bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
362{
363 if (length)
364 {
365 *length = 0;
366 }
367
368 if (GetValidShader(context, shader) == nullptr)
369 {
370 return false;
371 }
372
373 switch (pname)
374 {
375 case GL_SHADER_TYPE:
376 case GL_DELETE_STATUS:
377 case GL_COMPILE_STATUS:
378 case GL_INFO_LOG_LENGTH:
379 case GL_SHADER_SOURCE_LENGTH:
380 break;
381
382 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
383 if (!context->getExtensions().translatedShaderSource)
384 {
385 context->handleError(
386 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
387 return false;
388 }
389 break;
390
391 default:
392 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
393 return false;
394 }
395
396 if (length)
397 {
398 *length = 1;
399 }
400 return true;
401}
402
Geoff Langc1984ed2016-10-07 12:41:00 -0400403bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
404{
405 if (length)
406 {
407 *length = 0;
408 }
409
410 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
411 {
412 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
413 return false;
414 }
415
416 if (context->getTargetTexture(target) == nullptr)
417 {
418 // Should only be possible for external textures
419 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
420 return false;
421 }
422
423 switch (pname)
424 {
425 case GL_TEXTURE_MAG_FILTER:
426 case GL_TEXTURE_MIN_FILTER:
427 case GL_TEXTURE_WRAP_S:
428 case GL_TEXTURE_WRAP_T:
429 break;
430
431 case GL_TEXTURE_USAGE_ANGLE:
432 if (!context->getExtensions().textureUsage)
433 {
434 context->handleError(
435 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
436 return false;
437 }
438 break;
439
440 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
441 if (!context->getExtensions().textureFilterAnisotropic)
442 {
443 context->handleError(
444 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
445 return false;
446 }
447 break;
448
449 case GL_TEXTURE_IMMUTABLE_FORMAT:
450 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
451 {
452 context->handleError(
453 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
454 return false;
455 }
456 break;
457
458 case GL_TEXTURE_WRAP_R:
459 case GL_TEXTURE_IMMUTABLE_LEVELS:
460 case GL_TEXTURE_SWIZZLE_R:
461 case GL_TEXTURE_SWIZZLE_G:
462 case GL_TEXTURE_SWIZZLE_B:
463 case GL_TEXTURE_SWIZZLE_A:
464 case GL_TEXTURE_BASE_LEVEL:
465 case GL_TEXTURE_MAX_LEVEL:
466 case GL_TEXTURE_MIN_LOD:
467 case GL_TEXTURE_MAX_LOD:
468 case GL_TEXTURE_COMPARE_MODE:
469 case GL_TEXTURE_COMPARE_FUNC:
470 if (context->getClientMajorVersion() < 3)
471 {
472 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
473 return false;
474 }
475 break;
476
Geoff Lang81c6b572016-10-19 14:07:52 -0700477 case GL_TEXTURE_SRGB_DECODE_EXT:
478 if (!context->getExtensions().textureSRGBDecode)
479 {
480 context->handleError(
481 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
482 return false;
483 }
484 break;
485
Geoff Langc1984ed2016-10-07 12:41:00 -0400486 default:
487 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
488 return false;
489 }
490
491 if (length)
492 {
493 *length = 1;
494 }
495 return true;
496}
497
498template <typename ParamType>
499bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
500{
501 switch (ConvertToGLenum(params[0]))
502 {
503 case GL_CLAMP_TO_EDGE:
504 break;
505
506 case GL_REPEAT:
507 case GL_MIRRORED_REPEAT:
508 if (isExternalTextureTarget)
509 {
510 // OES_EGL_image_external specifies this error.
511 context->handleError(Error(
512 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
513 return false;
514 }
515 break;
516
517 default:
518 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
519 return false;
520 }
521
522 return true;
523}
524
525template <typename ParamType>
526bool ValidateTextureMinFilterValue(Context *context,
527 ParamType *params,
528 bool isExternalTextureTarget)
529{
530 switch (ConvertToGLenum(params[0]))
531 {
532 case GL_NEAREST:
533 case GL_LINEAR:
534 break;
535
536 case GL_NEAREST_MIPMAP_NEAREST:
537 case GL_LINEAR_MIPMAP_NEAREST:
538 case GL_NEAREST_MIPMAP_LINEAR:
539 case GL_LINEAR_MIPMAP_LINEAR:
540 if (isExternalTextureTarget)
541 {
542 // OES_EGL_image_external specifies this error.
543 context->handleError(
544 Error(GL_INVALID_ENUM,
545 "external textures only support NEAREST and LINEAR filtering"));
546 return false;
547 }
548 break;
549
550 default:
551 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
552 return false;
553 }
554
555 return true;
556}
557
558template <typename ParamType>
559bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
560{
561 switch (ConvertToGLenum(params[0]))
562 {
563 case GL_NEAREST:
564 case GL_LINEAR:
565 break;
566
567 default:
568 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
569 return false;
570 }
571
572 return true;
573}
574
575template <typename ParamType>
576bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
577{
578 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
579 switch (ConvertToGLenum(params[0]))
580 {
581 case GL_NONE:
582 case GL_COMPARE_REF_TO_TEXTURE:
583 break;
584
585 default:
586 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
587 return false;
588 }
589
590 return true;
591}
592
593template <typename ParamType>
594bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
595{
596 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
597 switch (ConvertToGLenum(params[0]))
598 {
599 case GL_LEQUAL:
600 case GL_GEQUAL:
601 case GL_LESS:
602 case GL_GREATER:
603 case GL_EQUAL:
604 case GL_NOTEQUAL:
605 case GL_ALWAYS:
606 case GL_NEVER:
607 break;
608
609 default:
610 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
611 return false;
612 }
613
614 return true;
615}
616
617template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700618bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
619{
620 if (!context->getExtensions().textureSRGBDecode)
621 {
622 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
623 return false;
624 }
625
626 switch (ConvertToGLenum(params[0]))
627 {
628 case GL_DECODE_EXT:
629 case GL_SKIP_DECODE_EXT:
630 break;
631
632 default:
633 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
634 return false;
635 }
636
637 return true;
638}
639
640template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400641bool ValidateTexParameterBase(Context *context,
642 GLenum target,
643 GLenum pname,
644 GLsizei bufSize,
645 ParamType *params)
646{
647 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
648 {
649 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
650 return false;
651 }
652
653 if (context->getTargetTexture(target) == nullptr)
654 {
655 // Should only be possible for external textures
656 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
657 return false;
658 }
659
660 const GLsizei minBufSize = 1;
661 if (bufSize >= 0 && bufSize < minBufSize)
662 {
663 context->handleError(
664 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
665 return false;
666 }
667
668 switch (pname)
669 {
670 case GL_TEXTURE_WRAP_R:
671 case GL_TEXTURE_SWIZZLE_R:
672 case GL_TEXTURE_SWIZZLE_G:
673 case GL_TEXTURE_SWIZZLE_B:
674 case GL_TEXTURE_SWIZZLE_A:
675 case GL_TEXTURE_BASE_LEVEL:
676 case GL_TEXTURE_MAX_LEVEL:
677 case GL_TEXTURE_COMPARE_MODE:
678 case GL_TEXTURE_COMPARE_FUNC:
679 case GL_TEXTURE_MIN_LOD:
680 case GL_TEXTURE_MAX_LOD:
681 if (context->getClientMajorVersion() < 3)
682 {
683 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
684 return false;
685 }
686 if (target == GL_TEXTURE_EXTERNAL_OES &&
687 !context->getExtensions().eglImageExternalEssl3)
688 {
689 context->handleError(Error(GL_INVALID_ENUM,
690 "ES3 texture parameters are not available without "
691 "GL_OES_EGL_image_external_essl3."));
692 return false;
693 }
694 break;
695
696 default:
697 break;
698 }
699
700 switch (pname)
701 {
702 case GL_TEXTURE_WRAP_S:
703 case GL_TEXTURE_WRAP_T:
704 case GL_TEXTURE_WRAP_R:
705 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
706 {
707 return false;
708 }
709 break;
710
711 case GL_TEXTURE_MIN_FILTER:
712 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
713 {
714 return false;
715 }
716 break;
717
718 case GL_TEXTURE_MAG_FILTER:
719 if (!ValidateTextureMagFilterValue(context, params))
720 {
721 return false;
722 }
723 break;
724
725 case GL_TEXTURE_USAGE_ANGLE:
726 switch (ConvertToGLenum(params[0]))
727 {
728 case GL_NONE:
729 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
730 break;
731
732 default:
733 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
734 return false;
735 }
736 break;
737
738 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
739 if (!context->getExtensions().textureFilterAnisotropic)
740 {
741 context->handleError(
742 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
743 return false;
744 }
745
746 // we assume the parameter passed to this validation method is truncated, not rounded
747 if (params[0] < 1)
748 {
749 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
750 return false;
751 }
752 break;
753
754 case GL_TEXTURE_MIN_LOD:
755 case GL_TEXTURE_MAX_LOD:
756 // any value is permissible
757 break;
758
759 case GL_TEXTURE_COMPARE_MODE:
760 if (!ValidateTextureCompareModeValue(context, params))
761 {
762 return false;
763 }
764 break;
765
766 case GL_TEXTURE_COMPARE_FUNC:
767 if (!ValidateTextureCompareFuncValue(context, params))
768 {
769 return false;
770 }
771 break;
772
773 case GL_TEXTURE_SWIZZLE_R:
774 case GL_TEXTURE_SWIZZLE_G:
775 case GL_TEXTURE_SWIZZLE_B:
776 case GL_TEXTURE_SWIZZLE_A:
777 switch (ConvertToGLenum(params[0]))
778 {
779 case GL_RED:
780 case GL_GREEN:
781 case GL_BLUE:
782 case GL_ALPHA:
783 case GL_ZERO:
784 case GL_ONE:
785 break;
786
787 default:
788 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
789 return false;
790 }
791 break;
792
793 case GL_TEXTURE_BASE_LEVEL:
794 if (params[0] < 0)
795 {
796 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
797 return false;
798 }
799 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
800 {
801 context->handleError(
802 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
803 return false;
804 }
805 break;
806
807 case GL_TEXTURE_MAX_LEVEL:
808 if (params[0] < 0)
809 {
810 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
811 return false;
812 }
813 break;
814
Geoff Lang81c6b572016-10-19 14:07:52 -0700815 case GL_TEXTURE_SRGB_DECODE_EXT:
816 if (!ValidateTextureSRGBDecodeValue(context, params))
817 {
818 return false;
819 }
820 break;
821
Geoff Langc1984ed2016-10-07 12:41:00 -0400822 default:
823 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
824 return false;
825 }
826
827 return true;
828}
829
830template <typename ParamType>
831bool ValidateSamplerParameterBase(Context *context,
832 GLuint sampler,
833 GLenum pname,
834 GLsizei bufSize,
835 ParamType *params)
836{
837 if (context->getClientMajorVersion() < 3)
838 {
839 context->handleError(
840 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
841 return false;
842 }
843
844 if (!context->isSampler(sampler))
845 {
846 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
847 return false;
848 }
849
850 const GLsizei minBufSize = 1;
851 if (bufSize >= 0 && bufSize < minBufSize)
852 {
853 context->handleError(
854 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
855 return false;
856 }
857
858 switch (pname)
859 {
860 case GL_TEXTURE_WRAP_S:
861 case GL_TEXTURE_WRAP_T:
862 case GL_TEXTURE_WRAP_R:
863 if (!ValidateTextureWrapModeValue(context, params, false))
864 {
865 return false;
866 }
867 break;
868
869 case GL_TEXTURE_MIN_FILTER:
870 if (!ValidateTextureMinFilterValue(context, params, false))
871 {
872 return false;
873 }
874 break;
875
876 case GL_TEXTURE_MAG_FILTER:
877 if (!ValidateTextureMagFilterValue(context, params))
878 {
879 return false;
880 }
881 break;
882
883 case GL_TEXTURE_MIN_LOD:
884 case GL_TEXTURE_MAX_LOD:
885 // any value is permissible
886 break;
887
888 case GL_TEXTURE_COMPARE_MODE:
889 if (!ValidateTextureCompareModeValue(context, params))
890 {
891 return false;
892 }
893 break;
894
895 case GL_TEXTURE_COMPARE_FUNC:
896 if (!ValidateTextureCompareFuncValue(context, params))
897 {
898 return false;
899 }
900 break;
901
Geoff Lang81c6b572016-10-19 14:07:52 -0700902 case GL_TEXTURE_SRGB_DECODE_EXT:
903 if (!ValidateTextureSRGBDecodeValue(context, params))
904 {
905 return false;
906 }
907 break;
908
Geoff Langc1984ed2016-10-07 12:41:00 -0400909 default:
910 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
911 return false;
912 }
913
914 return true;
915}
916
917bool ValidateGetSamplerParameterBase(Context *context,
918 GLuint sampler,
919 GLenum pname,
920 GLsizei *length)
921{
922 if (length)
923 {
924 *length = 0;
925 }
926
927 if (context->getClientMajorVersion() < 3)
928 {
929 context->handleError(
930 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
931 return false;
932 }
933
934 if (!context->isSampler(sampler))
935 {
936 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
937 return false;
938 }
939
940 switch (pname)
941 {
942 case GL_TEXTURE_WRAP_S:
943 case GL_TEXTURE_WRAP_T:
944 case GL_TEXTURE_WRAP_R:
945 case GL_TEXTURE_MIN_FILTER:
946 case GL_TEXTURE_MAG_FILTER:
947 case GL_TEXTURE_MIN_LOD:
948 case GL_TEXTURE_MAX_LOD:
949 case GL_TEXTURE_COMPARE_MODE:
950 case GL_TEXTURE_COMPARE_FUNC:
951 break;
952
Geoff Lang81c6b572016-10-19 14:07:52 -0700953 case GL_TEXTURE_SRGB_DECODE_EXT:
954 if (!context->getExtensions().textureSRGBDecode)
955 {
956 context->handleError(
957 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
958 return false;
959 }
960 break;
961
Geoff Langc1984ed2016-10-07 12:41:00 -0400962 default:
963 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
964 return false;
965 }
966
967 if (length)
968 {
969 *length = 1;
970 }
971 return true;
972}
973
Geoff Lang0b031062016-10-13 14:30:04 -0400974bool ValidateGetVertexAttribBase(Context *context,
975 GLuint index,
976 GLenum pname,
977 GLsizei *length,
978 bool pointer,
979 bool pureIntegerEntryPoint)
980{
981 if (length)
982 {
983 *length = 0;
984 }
985
986 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
987 {
988 context->handleError(
989 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
990 return false;
991 }
992
993 if (index >= context->getCaps().maxVertexAttributes)
994 {
995 context->handleError(Error(
996 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
997 return false;
998 }
999
1000 if (pointer)
1001 {
1002 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1003 {
1004 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1005 return false;
1006 }
1007 }
1008 else
1009 {
1010 switch (pname)
1011 {
1012 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1013 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1014 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1015 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1016 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1017 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1018 case GL_CURRENT_VERTEX_ATTRIB:
1019 break;
1020
1021 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1022 static_assert(
1023 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1024 "ANGLE extension enums not equal to GL enums.");
1025 if (context->getClientMajorVersion() < 3 &&
1026 !context->getExtensions().instancedArrays)
1027 {
1028 context->handleError(Error(GL_INVALID_ENUM,
1029 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1030 "3.0 or GL_ANGLE_instanced_arrays."));
1031 return false;
1032 }
1033 break;
1034
1035 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1036 if (context->getClientMajorVersion() < 3)
1037 {
1038 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1039 return false;
1040 }
1041 break;
1042
1043 default:
1044 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1045 return false;
1046 }
1047 }
1048
1049 if (length)
1050 {
1051 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1052 {
1053 *length = 4;
1054 }
1055 else
1056 {
1057 *length = 1;
1058 }
1059 }
1060
1061 return true;
1062}
1063
Geoff Lang6899b872016-10-14 11:30:13 -04001064bool ValidateGetActiveUniformBlockivBase(Context *context,
1065 GLuint program,
1066 GLuint uniformBlockIndex,
1067 GLenum pname,
1068 GLsizei *length)
1069{
1070 if (length)
1071 {
1072 *length = 0;
1073 }
1074
1075 if (context->getClientMajorVersion() < 3)
1076 {
1077 context->handleError(
1078 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1079 return false;
1080 }
1081
1082 Program *programObject = GetValidProgram(context, program);
1083 if (!programObject)
1084 {
1085 return false;
1086 }
1087
1088 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1089 {
1090 context->handleError(
1091 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1092 return false;
1093 }
1094
1095 switch (pname)
1096 {
1097 case GL_UNIFORM_BLOCK_BINDING:
1098 case GL_UNIFORM_BLOCK_DATA_SIZE:
1099 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1100 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1101 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1102 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1103 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1104 break;
1105
1106 default:
1107 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1108 return false;
1109 }
1110
1111 if (length)
1112 {
1113 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1114 {
1115 const UniformBlock &uniformBlock =
1116 programObject->getUniformBlockByIndex(uniformBlockIndex);
1117 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1118 }
1119 else
1120 {
1121 *length = 1;
1122 }
1123 }
1124
1125 return true;
1126}
1127
Geoff Langebebe1c2016-10-14 12:01:31 -04001128bool ValidateGetBufferParameterBase(ValidationContext *context,
1129 GLenum target,
1130 GLenum pname,
1131 bool pointerVersion,
1132 GLsizei *numParams)
1133{
1134 if (numParams)
1135 {
1136 *numParams = 0;
1137 }
1138
1139 if (!ValidBufferTarget(context, target))
1140 {
1141 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1142 return false;
1143 }
1144
1145 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1146 if (!buffer)
1147 {
1148 // A null buffer means that "0" is bound to the requested buffer target
1149 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1150 return false;
1151 }
1152
1153 const Extensions &extensions = context->getExtensions();
1154
1155 switch (pname)
1156 {
1157 case GL_BUFFER_USAGE:
1158 case GL_BUFFER_SIZE:
1159 break;
1160
1161 case GL_BUFFER_ACCESS_OES:
1162 if (!extensions.mapBuffer)
1163 {
1164 context->handleError(
1165 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1166 return false;
1167 }
1168 break;
1169
1170 case GL_BUFFER_MAPPED:
1171 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1172 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1173 !extensions.mapBufferRange)
1174 {
1175 context->handleError(Error(
1176 GL_INVALID_ENUM,
1177 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1178 return false;
1179 }
1180 break;
1181
1182 case GL_BUFFER_MAP_POINTER:
1183 if (!pointerVersion)
1184 {
1185 context->handleError(
1186 Error(GL_INVALID_ENUM,
1187 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1188 return false;
1189 }
1190 break;
1191
1192 case GL_BUFFER_ACCESS_FLAGS:
1193 case GL_BUFFER_MAP_OFFSET:
1194 case GL_BUFFER_MAP_LENGTH:
1195 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1196 {
1197 context->handleError(Error(
1198 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1199 return false;
1200 }
1201 break;
1202
1203 default:
1204 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1205 return false;
1206 }
1207
1208 // All buffer parameter queries return one value.
1209 if (numParams)
1210 {
1211 *numParams = 1;
1212 }
1213
1214 return true;
1215}
1216
Geoff Lang0a9661f2016-10-20 10:59:20 -07001217bool ValidateGetInternalFormativBase(Context *context,
1218 GLenum target,
1219 GLenum internalformat,
1220 GLenum pname,
1221 GLsizei bufSize,
1222 GLsizei *numParams)
1223{
1224 if (numParams)
1225 {
1226 *numParams = 0;
1227 }
1228
1229 if (context->getClientMajorVersion() < 3)
1230 {
1231 context->handleError(
1232 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1233 return false;
1234 }
1235
1236 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1237 if (!formatCaps.renderable)
1238 {
1239 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1240 return false;
1241 }
1242
1243 switch (target)
1244 {
1245 case GL_RENDERBUFFER:
1246 break;
1247
1248 default:
1249 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1250 return false;
1251 }
1252
1253 if (bufSize < 0)
1254 {
1255 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1256 return false;
1257 }
1258
1259 GLsizei maxWriteParams = 0;
1260 switch (pname)
1261 {
1262 case GL_NUM_SAMPLE_COUNTS:
1263 maxWriteParams = 1;
1264 break;
1265
1266 case GL_SAMPLES:
1267 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1268 break;
1269
1270 default:
1271 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1272 return false;
1273 }
1274
1275 if (numParams)
1276 {
1277 // glGetInternalFormativ will not overflow bufSize
1278 *numParams = std::min(bufSize, maxWriteParams);
1279 }
1280
1281 return true;
1282}
1283
Geoff Langf41a7152016-09-19 15:11:17 -04001284} // anonymous namespace
1285
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001286bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001287{
Jamie Madilld7460c72014-01-21 16:38:14 -05001288 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001289 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001290 case GL_TEXTURE_2D:
1291 case GL_TEXTURE_CUBE_MAP:
1292 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001293
Jamie Madilld7460c72014-01-21 16:38:14 -05001294 case GL_TEXTURE_3D:
1295 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001296 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001297
1298 default:
1299 return false;
1300 }
Jamie Madill35d15012013-10-07 10:46:37 -04001301}
1302
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001303bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1304{
1305 switch (target)
1306 {
1307 case GL_TEXTURE_2D:
1308 case GL_TEXTURE_CUBE_MAP:
1309 return true;
1310
1311 default:
1312 return false;
1313 }
1314}
1315
1316bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1317{
1318 switch (target)
1319 {
1320 case GL_TEXTURE_3D:
1321 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001322 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001323
1324 default:
1325 return false;
1326 }
1327}
1328
Ian Ewellbda75592016-04-18 17:25:54 -04001329// Most texture GL calls are not compatible with external textures, so we have a separate validation
1330// function for use in the GL calls that do
1331bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1332{
1333 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1334 (context->getExtensions().eglImageExternal ||
1335 context->getExtensions().eglStreamConsumerExternal);
1336}
1337
Shannon Woods4dfed832014-03-17 20:03:39 -04001338// This function differs from ValidTextureTarget in that the target must be
1339// usable as the destination of a 2D operation-- so a cube face is valid, but
1340// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001341// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001342bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001343{
1344 switch (target)
1345 {
1346 case GL_TEXTURE_2D:
1347 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1348 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1349 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1350 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1351 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1352 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1353 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001354 default:
1355 return false;
1356 }
1357}
1358
1359bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1360{
1361 switch (target)
1362 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001363 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001364 case GL_TEXTURE_2D_ARRAY:
1365 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001366 default:
1367 return false;
1368 }
1369}
1370
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001371bool ValidFramebufferTarget(GLenum target)
1372{
Geoff Langd4475812015-03-18 10:53:05 -04001373 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1374 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001375
1376 switch (target)
1377 {
1378 case GL_FRAMEBUFFER: return true;
1379 case GL_READ_FRAMEBUFFER: return true;
1380 case GL_DRAW_FRAMEBUFFER: return true;
1381 default: return false;
1382 }
1383}
1384
Jamie Madill29639852016-09-02 15:00:09 -04001385bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001386{
1387 switch (target)
1388 {
1389 case GL_ARRAY_BUFFER:
1390 case GL_ELEMENT_ARRAY_BUFFER:
1391 return true;
1392
Jamie Madill8c96d582014-03-05 15:01:23 -05001393 case GL_PIXEL_PACK_BUFFER:
1394 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001395 return (context->getExtensions().pixelBufferObject ||
1396 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001397
Shannon Woodsb3801742014-03-27 14:59:19 -04001398 case GL_COPY_READ_BUFFER:
1399 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001400 case GL_TRANSFORM_FEEDBACK_BUFFER:
1401 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001402 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001403
1404 default:
1405 return false;
1406 }
1407}
1408
Jamie Madillc29968b2016-01-20 11:17:23 -05001409bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001410{
Jamie Madillc29968b2016-01-20 11:17:23 -05001411 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001412 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001413 switch (target)
1414 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001415 case GL_TEXTURE_2D:
1416 maxDimension = caps.max2DTextureSize;
1417 break;
Geoff Langce635692013-09-24 13:56:32 -04001418 case GL_TEXTURE_CUBE_MAP:
1419 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1420 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1421 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1422 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1423 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001424 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1425 maxDimension = caps.maxCubeMapTextureSize;
1426 break;
1427 case GL_TEXTURE_3D:
1428 maxDimension = caps.max3DTextureSize;
1429 break;
1430 case GL_TEXTURE_2D_ARRAY:
1431 maxDimension = caps.max2DTextureSize;
1432 break;
Geoff Langce635692013-09-24 13:56:32 -04001433 default: UNREACHABLE();
1434 }
1435
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001436 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001437}
1438
Austin Kinross08528e12015-10-07 16:24:40 -07001439bool ValidImageSizeParameters(const Context *context,
1440 GLenum target,
1441 GLint level,
1442 GLsizei width,
1443 GLsizei height,
1444 GLsizei depth,
1445 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001446{
1447 if (level < 0 || width < 0 || height < 0 || depth < 0)
1448 {
1449 return false;
1450 }
1451
Austin Kinross08528e12015-10-07 16:24:40 -07001452 // TexSubImage parameters can be NPOT without textureNPOT extension,
1453 // as long as the destination texture is POT.
1454 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001455 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001456 {
1457 return false;
1458 }
1459
1460 if (!ValidMipLevel(context, target, level))
1461 {
1462 return false;
1463 }
1464
1465 return true;
1466}
1467
Geoff Lang0d8b7242015-09-09 14:56:53 -04001468bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1469{
1470 // List of compressed format that require that the texture size is smaller than or a multiple of
1471 // the compressed block size.
1472 switch (internalFormat)
1473 {
1474 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1475 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1476 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1477 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001478 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001479 return true;
1480
1481 default:
1482 return false;
1483 }
1484}
1485
Jamie Madillc29968b2016-01-20 11:17:23 -05001486bool ValidCompressedImageSize(const ValidationContext *context,
1487 GLenum internalFormat,
1488 GLsizei width,
1489 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001490{
Geoff Lang5d601382014-07-22 15:14:06 -04001491 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1492 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001493 {
1494 return false;
1495 }
1496
Geoff Lang0d8b7242015-09-09 14:56:53 -04001497 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001498 {
1499 return false;
1500 }
1501
Geoff Lang0d8b7242015-09-09 14:56:53 -04001502 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1503 {
1504 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1505 width % formatInfo.compressedBlockWidth != 0) ||
1506 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1507 height % formatInfo.compressedBlockHeight != 0))
1508 {
1509 return false;
1510 }
1511 }
1512
Geoff Langd4f180b2013-09-24 13:57:44 -04001513 return true;
1514}
1515
Geoff Langff5b2d52016-09-07 11:32:23 -04001516bool ValidImageDataSize(ValidationContext *context,
1517 GLenum textureTarget,
1518 GLsizei width,
1519 GLsizei height,
1520 GLsizei depth,
1521 GLenum internalFormat,
1522 GLenum type,
1523 const GLvoid *pixels,
1524 GLsizei imageSize)
1525{
1526 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1527 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1528 {
1529 // Checks are not required
1530 return true;
1531 }
1532
1533 // ...the data would be unpacked from the buffer object such that the memory reads required
1534 // would exceed the data store size.
1535 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1536 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1537 const gl::Extents size(width, height, depth);
1538 const auto &unpack = context->getGLState().getUnpackState();
1539
1540 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1541 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1542 if (endByteOrErr.isError())
1543 {
1544 context->handleError(endByteOrErr.getError());
1545 return false;
1546 }
1547
1548 GLuint endByte = endByteOrErr.getResult();
1549
1550 if (pixelUnpackBuffer)
1551 {
1552 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1553 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1554 checkedEndByte += checkedOffset;
1555
1556 if (!checkedEndByte.IsValid() ||
1557 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1558 {
1559 // Overflow past the end of the buffer
1560 context->handleError(Error(GL_INVALID_OPERATION));
1561 return false;
1562 }
1563 }
1564 else
1565 {
1566 ASSERT(imageSize >= 0);
1567 if (pixels == nullptr && imageSize != 0)
1568 {
1569 context->handleError(
1570 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001571 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001572 }
1573
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001574 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001575 {
1576 context->handleError(
1577 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1578 return false;
1579 }
1580 }
1581
1582 return true;
1583}
1584
Geoff Lang37dde692014-01-31 16:34:54 -05001585bool ValidQueryType(const Context *context, GLenum queryType)
1586{
Geoff Langd4475812015-03-18 10:53:05 -04001587 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1588 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 -05001589
1590 switch (queryType)
1591 {
1592 case GL_ANY_SAMPLES_PASSED:
1593 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1594 return true;
1595 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001596 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597 case GL_TIME_ELAPSED_EXT:
1598 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001599 case GL_COMMANDS_COMPLETED_CHROMIUM:
1600 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001601 default:
1602 return false;
1603 }
1604}
1605
Jamie Madillef300b12016-10-07 15:12:09 -04001606Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001607{
1608 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1609 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1610 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1611
Dian Xiang769769a2015-09-09 15:20:08 -07001612 Program *validProgram = context->getProgram(id);
1613
1614 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001615 {
Dian Xiang769769a2015-09-09 15:20:08 -07001616 if (context->getShader(id))
1617 {
Jamie Madill437fa652016-05-03 15:13:24 -04001618 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001619 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1620 }
1621 else
1622 {
Jamie Madill437fa652016-05-03 15:13:24 -04001623 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001624 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001625 }
Dian Xiang769769a2015-09-09 15:20:08 -07001626
1627 return validProgram;
1628}
1629
Jamie Madillef300b12016-10-07 15:12:09 -04001630Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001631{
1632 // See ValidProgram for spec details.
1633
1634 Shader *validShader = context->getShader(id);
1635
1636 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001637 {
Dian Xiang769769a2015-09-09 15:20:08 -07001638 if (context->getProgram(id))
1639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001641 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1642 }
1643 else
1644 {
Jamie Madill437fa652016-05-03 15:13:24 -04001645 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001646 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001647 }
Dian Xiang769769a2015-09-09 15:20:08 -07001648
1649 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001650}
1651
Geoff Langb1196682014-07-23 13:47:29 -04001652bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001653{
1654 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1655 {
1656 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1657
Geoff Langaae65a42014-05-26 12:43:44 -04001658 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001659 {
Jamie Madill437fa652016-05-03 15:13:24 -04001660 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001661 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001662 }
1663 }
1664 else
1665 {
1666 switch (attachment)
1667 {
1668 case GL_DEPTH_ATTACHMENT:
1669 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001670 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001671
1672 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001673 if (!context->getExtensions().webglCompatibility &&
1674 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001675 {
1676 context->handleError(Error(GL_INVALID_ENUM));
1677 return false;
1678 }
1679 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001680
1681 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001682 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001683 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001684 }
1685 }
1686
1687 return true;
1688}
1689
Corentin Walleze0902642014-11-04 12:32:15 -08001690bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1691 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001692{
1693 switch (target)
1694 {
1695 case GL_RENDERBUFFER:
1696 break;
1697 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001698 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001699 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001700 }
1701
1702 if (width < 0 || height < 0 || samples < 0)
1703 {
Jamie Madill437fa652016-05-03 15:13:24 -04001704 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001705 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001706 }
1707
Geoff Langd87878e2014-09-19 15:42:59 -04001708 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1709 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001712 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001713 }
1714
1715 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1716 // 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 -08001717 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001718 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001719 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001720 {
Jamie Madill437fa652016-05-03 15:13:24 -04001721 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001722 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001723 }
1724
Geoff Langaae65a42014-05-26 12:43:44 -04001725 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001728 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729 }
1730
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001731 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001732 if (handle == 0)
1733 {
Jamie Madill437fa652016-05-03 15:13:24 -04001734 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001735 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001736 }
1737
1738 return true;
1739}
1740
Corentin Walleze0902642014-11-04 12:32:15 -08001741bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1742 GLenum internalformat, GLsizei width, GLsizei height)
1743{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001744 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001745
1746 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001747 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001748 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001749 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001752 return false;
1753 }
1754
1755 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1756 // the specified storage. This is different than ES 3.0 in which a sample number higher
1757 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001758 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001759 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001760 {
Geoff Langa4903b72015-03-02 16:02:48 -08001761 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1762 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001765 return false;
1766 }
Corentin Walleze0902642014-11-04 12:32:15 -08001767 }
1768
1769 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1770}
1771
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001772bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1773 GLenum renderbuffertarget, GLuint renderbuffer)
1774{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001775 if (!ValidFramebufferTarget(target))
1776 {
Jamie Madill437fa652016-05-03 15:13:24 -04001777 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001778 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001779 }
1780
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001781 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001782
Jamie Madill84115c92015-04-23 15:00:07 -04001783 ASSERT(framebuffer);
1784 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001785 {
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(
1787 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001788 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001789 }
1790
Jamie Madillb4472272014-07-03 10:38:55 -04001791 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001792 {
Jamie Madillb4472272014-07-03 10:38:55 -04001793 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001794 }
1795
Jamie Madillab9d82c2014-01-21 16:38:14 -05001796 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1797 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1798 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1799 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1800 if (renderbuffer != 0)
1801 {
1802 if (!context->getRenderbuffer(renderbuffer))
1803 {
Jamie Madill437fa652016-05-03 15:13:24 -04001804 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001805 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001806 }
1807 }
1808
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001809 return true;
1810}
1811
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001812bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 GLint srcX0,
1814 GLint srcY0,
1815 GLint srcX1,
1816 GLint srcY1,
1817 GLint dstX0,
1818 GLint dstY0,
1819 GLint dstX1,
1820 GLint dstY1,
1821 GLbitfield mask,
1822 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001823{
1824 switch (filter)
1825 {
1826 case GL_NEAREST:
1827 break;
1828 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001829 break;
1830 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001831 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001832 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001833 }
1834
1835 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001838 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001839 }
1840
1841 if (mask == 0)
1842 {
1843 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1844 // buffers are copied.
1845 return false;
1846 }
1847
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001848 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1849 // color buffer, leaving only nearest being unfiltered from above
1850 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1851 {
Jamie Madill437fa652016-05-03 15:13:24 -04001852 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001853 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001854 }
1855
Jamie Madill51f40ec2016-06-15 14:06:00 -04001856 const auto &glState = context->getGLState();
1857 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1858 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001859
1860 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001863 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001864 }
1865
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001866 if (readFramebuffer->id() == drawFramebuffer->id())
1867 {
1868 context->handleError(Error(GL_INVALID_OPERATION));
1869 return false;
1870 }
1871
Jamie Madill51f40ec2016-06-15 14:06:00 -04001872 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001873 {
Jamie Madill437fa652016-05-03 15:13:24 -04001874 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001875 return false;
1876 }
1877
Jamie Madill51f40ec2016-06-15 14:06:00 -04001878 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001879 {
Jamie Madill437fa652016-05-03 15:13:24 -04001880 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001881 return false;
1882 }
1883
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001884 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001887 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001888 }
1889
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001890 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1891
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001892 if (mask & GL_COLOR_BUFFER_BIT)
1893 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001894 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1895 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001896 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001897
1898 if (readColorBuffer && drawColorBuffer)
1899 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001900 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001901
Geoff Langa15472a2015-08-11 11:48:03 -04001902 for (size_t drawbufferIdx = 0;
1903 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001904 {
Geoff Langa15472a2015-08-11 11:48:03 -04001905 const FramebufferAttachment *attachment =
1906 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1907 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001908 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001909 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001910
Geoff Langb2f3d052013-08-13 12:49:27 -04001911 // The GL ES 3.0.2 spec (pg 193) states that:
1912 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1913 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1914 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001915 // Changes with EXT_color_buffer_float:
1916 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001917 GLenum readComponentType = readFormat.info->componentType;
1918 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001919 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1920 readComponentType == GL_SIGNED_NORMALIZED);
1921 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1922 drawComponentType == GL_SIGNED_NORMALIZED);
1923
1924 if (extensions.colorBufferFloat)
1925 {
1926 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1927 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1928
1929 if (readFixedOrFloat != drawFixedOrFloat)
1930 {
Jamie Madill437fa652016-05-03 15:13:24 -04001931 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001932 "If the read buffer contains fixed-point or "
1933 "floating-point values, the draw buffer "
1934 "must as well."));
1935 return false;
1936 }
1937 }
1938 else if (readFixedPoint != drawFixedPoint)
1939 {
Jamie Madill437fa652016-05-03 15:13:24 -04001940 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001941 "If the read buffer contains fixed-point "
1942 "values, the draw buffer must as well."));
1943 return false;
1944 }
1945
1946 if (readComponentType == GL_UNSIGNED_INT &&
1947 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001950 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001951 }
1952
Jamie Madill6163c752015-12-07 16:32:59 -05001953 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001956 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001957 }
1958
Jamie Madilla3944d42016-07-22 22:13:26 -04001959 if (readColorBuffer->getSamples() > 0 &&
1960 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001964 }
1965 }
1966 }
1967
Jamie Madilla3944d42016-07-22 22:13:26 -04001968 if ((readFormat.info->componentType == GL_INT ||
1969 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1970 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001973 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001974 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001975 }
1976 }
1977
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001978 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1979 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1980 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001982 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001984 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1985 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001986
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001987 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001988 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001989 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001990 {
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001992 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001993 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001994
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001995 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001996 {
Jamie Madill437fa652016-05-03 15:13:24 -04001997 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001998 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001999 }
2000 }
2001 }
2002 }
2003
2004 return true;
2005}
2006
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002007bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002008 GLint x,
2009 GLint y,
2010 GLsizei width,
2011 GLsizei height,
2012 GLenum format,
2013 GLenum type,
2014 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002015{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002016 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2017}
2018
2019bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2020 GLint x,
2021 GLint y,
2022 GLsizei width,
2023 GLsizei height,
2024 GLenum format,
2025 GLenum type,
2026 GLsizei bufSize,
2027 GLsizei *length,
2028 GLvoid *pixels)
2029{
2030 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002031 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 return false;
2033 }
2034
Geoff Lang62fce5b2016-09-30 10:46:35 -04002035 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2036 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002037 {
Geoff Langb1196682014-07-23 13:47:29 -04002038 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002039 }
2040
Geoff Lang62fce5b2016-09-30 10:46:35 -04002041 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002042 {
Geoff Langb1196682014-07-23 13:47:29 -04002043 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002044 }
2045
Jamie Madillc29968b2016-01-20 11:17:23 -05002046 return true;
2047}
2048
2049bool ValidateReadnPixelsEXT(Context *context,
2050 GLint x,
2051 GLint y,
2052 GLsizei width,
2053 GLsizei height,
2054 GLenum format,
2055 GLenum type,
2056 GLsizei bufSize,
2057 GLvoid *pixels)
2058{
2059 if (bufSize < 0)
2060 {
Jamie Madill437fa652016-05-03 15:13:24 -04002061 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002062 return false;
2063 }
2064
Geoff Lang62fce5b2016-09-30 10:46:35 -04002065 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2066 pixels);
2067}
Jamie Madill26e91952014-03-05 15:01:27 -05002068
Geoff Lang62fce5b2016-09-30 10:46:35 -04002069bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2070 GLint x,
2071 GLint y,
2072 GLsizei width,
2073 GLsizei height,
2074 GLenum format,
2075 GLenum type,
2076 GLsizei bufSize,
2077 GLsizei *length,
2078 GLvoid *data)
2079{
2080 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002081 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002082 return false;
2083 }
2084
Geoff Lang62fce5b2016-09-30 10:46:35 -04002085 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002086 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002087 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002088 }
2089
Geoff Lang62fce5b2016-09-30 10:46:35 -04002090 if (!ValidateRobustBufferSize(context, bufSize, *length))
2091 {
2092 return false;
2093 }
2094
2095 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002096}
2097
Olli Etuaho41997e72016-03-10 13:38:39 +02002098bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002099{
2100 if (!context->getExtensions().occlusionQueryBoolean &&
2101 !context->getExtensions().disjointTimerQuery)
2102 {
Jamie Madill437fa652016-05-03 15:13:24 -04002103 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002104 return false;
2105 }
2106
Olli Etuaho41997e72016-03-10 13:38:39 +02002107 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002108}
2109
Olli Etuaho41997e72016-03-10 13:38:39 +02002110bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002111{
2112 if (!context->getExtensions().occlusionQueryBoolean &&
2113 !context->getExtensions().disjointTimerQuery)
2114 {
Jamie Madill437fa652016-05-03 15:13:24 -04002115 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002116 return false;
2117 }
2118
Olli Etuaho41997e72016-03-10 13:38:39 +02002119 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002120}
2121
2122bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002123{
2124 if (!ValidQueryType(context, target))
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002127 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002128 }
2129
2130 if (id == 0)
2131 {
Jamie Madill437fa652016-05-03 15:13:24 -04002132 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002133 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002134 }
2135
2136 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2137 // of zero, if the active query object name for <target> is non-zero (for the
2138 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2139 // the active query for either target is non-zero), if <id> is the name of an
2140 // existing query object whose type does not match <target>, or if <id> is the
2141 // active query object name for any query type, the error INVALID_OPERATION is
2142 // generated.
2143
2144 // Ensure no other queries are active
2145 // NOTE: If other queries than occlusion are supported, we will need to check
2146 // separately that:
2147 // a) The query ID passed is not the current active query for any target/type
2148 // b) There are no active queries for the requested target (and in the case
2149 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2150 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002151
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002152 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002153 {
Jamie Madill437fa652016-05-03 15:13:24 -04002154 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002155 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002156 }
2157
2158 Query *queryObject = context->getQuery(id, true, target);
2159
2160 // check that name was obtained with glGenQueries
2161 if (!queryObject)
2162 {
Jamie Madill437fa652016-05-03 15:13:24 -04002163 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002164 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002165 }
2166
2167 // check for type mismatch
2168 if (queryObject->getType() != target)
2169 {
Jamie Madill437fa652016-05-03 15:13:24 -04002170 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002171 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002172 }
2173
2174 return true;
2175}
2176
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002177bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2178{
2179 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002180 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002181 {
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002183 return false;
2184 }
2185
2186 return ValidateBeginQueryBase(context, target, id);
2187}
2188
2189bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002190{
2191 if (!ValidQueryType(context, target))
2192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002194 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002195 }
2196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002197 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002198
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002199 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002200 {
Jamie Madill437fa652016-05-03 15:13:24 -04002201 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002202 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002203 }
2204
Jamie Madill45c785d2014-05-13 14:09:34 -04002205 return true;
2206}
2207
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002208bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2209{
2210 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002211 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002212 {
Jamie Madill437fa652016-05-03 15:13:24 -04002213 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002214 return false;
2215 }
2216
2217 return ValidateEndQueryBase(context, target);
2218}
2219
2220bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2221{
2222 if (!context->getExtensions().disjointTimerQuery)
2223 {
Jamie Madill437fa652016-05-03 15:13:24 -04002224 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002225 return false;
2226 }
2227
2228 if (target != GL_TIMESTAMP_EXT)
2229 {
Jamie Madill437fa652016-05-03 15:13:24 -04002230 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002231 return false;
2232 }
2233
2234 Query *queryObject = context->getQuery(id, true, target);
2235 if (queryObject == nullptr)
2236 {
Jamie Madill437fa652016-05-03 15:13:24 -04002237 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002238 return false;
2239 }
2240
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002241 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002242 {
Jamie Madill437fa652016-05-03 15:13:24 -04002243 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002244 return false;
2245 }
2246
2247 return true;
2248}
2249
Geoff Lang2186c382016-10-14 10:54:54 -04002250bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002251{
Geoff Lang2186c382016-10-14 10:54:54 -04002252 if (numParams)
2253 {
2254 *numParams = 0;
2255 }
2256
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002257 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2258 {
Jamie Madill437fa652016-05-03 15:13:24 -04002259 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002260 return false;
2261 }
2262
2263 switch (pname)
2264 {
2265 case GL_CURRENT_QUERY_EXT:
2266 if (target == GL_TIMESTAMP_EXT)
2267 {
Jamie Madill437fa652016-05-03 15:13:24 -04002268 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002269 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2270 return false;
2271 }
2272 break;
2273 case GL_QUERY_COUNTER_BITS_EXT:
2274 if (!context->getExtensions().disjointTimerQuery ||
2275 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2276 {
Jamie Madill437fa652016-05-03 15:13:24 -04002277 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002278 return false;
2279 }
2280 break;
2281 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002282 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002283 return false;
2284 }
2285
Geoff Lang2186c382016-10-14 10:54:54 -04002286 if (numParams)
2287 {
2288 // All queries return only one value
2289 *numParams = 1;
2290 }
2291
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002292 return true;
2293}
2294
2295bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2296{
2297 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002298 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002299 {
Jamie Madill437fa652016-05-03 15:13:24 -04002300 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002301 return false;
2302 }
2303
Geoff Lang2186c382016-10-14 10:54:54 -04002304 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002305}
2306
Geoff Lang2186c382016-10-14 10:54:54 -04002307bool ValidateGetQueryivRobustANGLE(Context *context,
2308 GLenum target,
2309 GLenum pname,
2310 GLsizei bufSize,
2311 GLsizei *length,
2312 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002313{
Geoff Lang2186c382016-10-14 10:54:54 -04002314 if (!ValidateRobustEntryPoint(context, bufSize))
2315 {
2316 return false;
2317 }
2318
2319 if (!ValidateGetQueryivBase(context, target, pname, length))
2320 {
2321 return false;
2322 }
2323
2324 if (!ValidateRobustBufferSize(context, bufSize, *length))
2325 {
2326 return false;
2327 }
2328
2329 return true;
2330}
2331
2332bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2333{
2334 if (numParams)
2335 {
2336 *numParams = 0;
2337 }
2338
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002339 Query *queryObject = context->getQuery(id, false, GL_NONE);
2340
2341 if (!queryObject)
2342 {
Jamie Madill437fa652016-05-03 15:13:24 -04002343 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002344 return false;
2345 }
2346
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002347 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002348 {
Jamie Madill437fa652016-05-03 15:13:24 -04002349 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002350 return false;
2351 }
2352
2353 switch (pname)
2354 {
2355 case GL_QUERY_RESULT_EXT:
2356 case GL_QUERY_RESULT_AVAILABLE_EXT:
2357 break;
2358
2359 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002360 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002361 return false;
2362 }
2363
Geoff Lang2186c382016-10-14 10:54:54 -04002364 if (numParams)
2365 {
2366 *numParams = 1;
2367 }
2368
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002369 return true;
2370}
2371
2372bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2373{
2374 if (!context->getExtensions().disjointTimerQuery)
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002377 return false;
2378 }
Geoff Lang2186c382016-10-14 10:54:54 -04002379 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2380}
2381
2382bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2383 GLuint id,
2384 GLenum pname,
2385 GLsizei bufSize,
2386 GLsizei *length,
2387 GLint *params)
2388{
2389 if (!context->getExtensions().disjointTimerQuery)
2390 {
2391 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2392 return false;
2393 }
2394
2395 if (!ValidateRobustEntryPoint(context, bufSize))
2396 {
2397 return false;
2398 }
2399
2400 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2401 {
2402 return false;
2403 }
2404
2405 if (!ValidateRobustBufferSize(context, bufSize, *length))
2406 {
2407 return false;
2408 }
2409
2410 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002411}
2412
2413bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2414{
2415 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002416 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002417 {
Jamie Madill437fa652016-05-03 15:13:24 -04002418 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002419 return false;
2420 }
Geoff Lang2186c382016-10-14 10:54:54 -04002421 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2422}
2423
2424bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2425 GLuint id,
2426 GLenum pname,
2427 GLsizei bufSize,
2428 GLsizei *length,
2429 GLuint *params)
2430{
2431 if (!context->getExtensions().disjointTimerQuery &&
2432 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2433 {
2434 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2435 return false;
2436 }
2437
2438 if (!ValidateRobustEntryPoint(context, bufSize))
2439 {
2440 return false;
2441 }
2442
2443 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2444 {
2445 return false;
2446 }
2447
2448 if (!ValidateRobustBufferSize(context, bufSize, *length))
2449 {
2450 return false;
2451 }
2452
2453 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002454}
2455
2456bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2457{
2458 if (!context->getExtensions().disjointTimerQuery)
2459 {
Jamie Madill437fa652016-05-03 15:13:24 -04002460 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002461 return false;
2462 }
Geoff Lang2186c382016-10-14 10:54:54 -04002463 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2464}
2465
2466bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2467 GLuint id,
2468 GLenum pname,
2469 GLsizei bufSize,
2470 GLsizei *length,
2471 GLint64 *params)
2472{
2473 if (!context->getExtensions().disjointTimerQuery)
2474 {
2475 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2476 return false;
2477 }
2478
2479 if (!ValidateRobustEntryPoint(context, bufSize))
2480 {
2481 return false;
2482 }
2483
2484 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2485 {
2486 return false;
2487 }
2488
2489 if (!ValidateRobustBufferSize(context, bufSize, *length))
2490 {
2491 return false;
2492 }
2493
2494 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002495}
2496
2497bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2498{
2499 if (!context->getExtensions().disjointTimerQuery)
2500 {
Jamie Madill437fa652016-05-03 15:13:24 -04002501 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002502 return false;
2503 }
Geoff Lang2186c382016-10-14 10:54:54 -04002504 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2505}
2506
2507bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2508 GLuint id,
2509 GLenum pname,
2510 GLsizei bufSize,
2511 GLsizei *length,
2512 GLuint64 *params)
2513{
2514 if (!context->getExtensions().disjointTimerQuery)
2515 {
2516 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2517 return false;
2518 }
2519
2520 if (!ValidateRobustEntryPoint(context, bufSize))
2521 {
2522 return false;
2523 }
2524
2525 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2526 {
2527 return false;
2528 }
2529
2530 if (!ValidateRobustBufferSize(context, bufSize, *length))
2531 {
2532 return false;
2533 }
2534
2535 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002536}
2537
Jamie Madill62d31cb2015-09-11 13:25:51 -04002538static bool ValidateUniformCommonBase(gl::Context *context,
2539 GLenum targetUniformType,
2540 GLint location,
2541 GLsizei count,
2542 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002543{
2544 if (count < 0)
2545 {
Jamie Madill437fa652016-05-03 15:13:24 -04002546 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002547 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002548 }
2549
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002550 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002551 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002552 {
Jamie Madill437fa652016-05-03 15:13:24 -04002553 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002555 }
2556
Geoff Langd8605522016-04-13 10:19:12 -04002557 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002558 {
2559 // Silently ignore the uniform command
2560 return false;
2561 }
2562
Geoff Lang7dd2e102014-11-10 15:19:26 -05002563 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002564 {
Jamie Madill437fa652016-05-03 15:13:24 -04002565 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002566 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002567 }
2568
Jamie Madill62d31cb2015-09-11 13:25:51 -04002569 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002570
2571 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002572 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002573 {
Jamie Madill437fa652016-05-03 15:13:24 -04002574 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002576 }
2577
Jamie Madill62d31cb2015-09-11 13:25:51 -04002578 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002579 return true;
2580}
2581
Jamie Madillaa981bd2014-05-20 10:55:55 -04002582bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2583{
2584 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002585 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2586 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002587 {
Jamie Madill437fa652016-05-03 15:13:24 -04002588 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002589 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002590 }
2591
Jamie Madill62d31cb2015-09-11 13:25:51 -04002592 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002593 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2594 {
2595 return false;
2596 }
2597
Jamie Madillf2575982014-06-25 16:04:54 -04002598 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002599 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002600 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2601 {
Jamie Madill437fa652016-05-03 15:13:24 -04002602 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002603 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002604 }
2605
2606 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002607}
2608
2609bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2610 GLboolean transpose)
2611{
2612 // Check for ES3 uniform entry points
2613 int rows = VariableRowCount(matrixType);
2614 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002615 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002616 {
Jamie Madill437fa652016-05-03 15:13:24 -04002617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002618 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002619 }
2620
Martin Radev1be913c2016-07-11 17:59:16 +03002621 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002622 {
Jamie Madill437fa652016-05-03 15:13:24 -04002623 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002624 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002625 }
2626
Jamie Madill62d31cb2015-09-11 13:25:51 -04002627 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002628 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2629 {
2630 return false;
2631 }
2632
2633 if (uniform->type != matrixType)
2634 {
Jamie Madill437fa652016-05-03 15:13:24 -04002635 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002636 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002637 }
2638
2639 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002640}
2641
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002642bool ValidateStateQuery(ValidationContext *context,
2643 GLenum pname,
2644 GLenum *nativeType,
2645 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002646{
2647 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2648 {
Jamie Madill437fa652016-05-03 15:13:24 -04002649 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002650 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002651 }
2652
Jamie Madill0af26e12015-03-05 19:54:33 -05002653 const Caps &caps = context->getCaps();
2654
Jamie Madill893ab082014-05-16 16:56:10 -04002655 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2656 {
2657 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2658
Jamie Madill0af26e12015-03-05 19:54:33 -05002659 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002660 {
Jamie Madill437fa652016-05-03 15:13:24 -04002661 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002662 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002663 }
2664 }
2665
2666 switch (pname)
2667 {
2668 case GL_TEXTURE_BINDING_2D:
2669 case GL_TEXTURE_BINDING_CUBE_MAP:
2670 case GL_TEXTURE_BINDING_3D:
2671 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002672 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002673 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002674 if (!context->getExtensions().eglStreamConsumerExternal &&
2675 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002676 {
John Bauman18319182016-09-28 14:22:27 -07002677 context->handleError(Error(GL_INVALID_ENUM,
2678 "Neither NV_EGL_stream_consumer_external nor "
2679 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002680 return false;
2681 }
2682 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002683
2684 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2685 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2686 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002687 if (context->getGLState().getReadFramebuffer()->checkStatus(
2688 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002689 {
Jamie Madill437fa652016-05-03 15:13:24 -04002690 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002691 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002692 }
2693
Jamie Madill51f40ec2016-06-15 14:06:00 -04002694 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2695 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002696
2697 if (framebuffer->getReadBufferState() == GL_NONE)
2698 {
2699 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2700 return false;
2701 }
2702
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002703 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002704 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002705 {
Jamie Madill437fa652016-05-03 15:13:24 -04002706 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002707 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002708 }
2709 }
2710 break;
2711
2712 default:
2713 break;
2714 }
2715
2716 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002717 if (*numParams == 0)
2718 {
2719 return false;
2720 }
2721
2722 return true;
2723}
2724
2725bool ValidateRobustStateQuery(ValidationContext *context,
2726 GLenum pname,
2727 GLsizei bufSize,
2728 GLenum *nativeType,
2729 unsigned int *numParams)
2730{
2731 if (!ValidateRobustEntryPoint(context, bufSize))
2732 {
2733 return false;
2734 }
2735
2736 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2737 {
2738 return false;
2739 }
2740
2741 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002742 {
2743 return false;
2744 }
2745
2746 return true;
2747}
2748
Jamie Madillc29968b2016-01-20 11:17:23 -05002749bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2750 GLenum target,
2751 GLint level,
2752 GLenum internalformat,
2753 bool isSubImage,
2754 GLint xoffset,
2755 GLint yoffset,
2756 GLint zoffset,
2757 GLint x,
2758 GLint y,
2759 GLsizei width,
2760 GLsizei height,
2761 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002762 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002763{
Jamie Madill560a8d82014-05-21 13:06:20 -04002764 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2765 {
Jamie Madill437fa652016-05-03 15:13:24 -04002766 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002767 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002768 }
2769
2770 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2771 {
Jamie Madill437fa652016-05-03 15:13:24 -04002772 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002773 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002774 }
2775
2776 if (border != 0)
2777 {
Jamie Madill437fa652016-05-03 15:13:24 -04002778 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002779 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002780 }
2781
2782 if (!ValidMipLevel(context, target, level))
2783 {
Jamie Madill437fa652016-05-03 15:13:24 -04002784 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002785 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002786 }
2787
Jamie Madill51f40ec2016-06-15 14:06:00 -04002788 const auto &state = context->getGLState();
2789 auto readFramebuffer = state.getReadFramebuffer();
2790 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002791 {
Jamie Madill437fa652016-05-03 15:13:24 -04002792 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002793 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002794 }
2795
Jamie Madill51f40ec2016-06-15 14:06:00 -04002796 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002797 {
Jamie Madill437fa652016-05-03 15:13:24 -04002798 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002799 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002800 }
2801
Martin Radev138064f2016-07-15 12:03:41 +03002802 if (readFramebuffer->getReadBufferState() == GL_NONE)
2803 {
2804 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2805 return false;
2806 }
2807
Geoff Langaae65a42014-05-26 12:43:44 -04002808 const gl::Caps &caps = context->getCaps();
2809
Geoff Langaae65a42014-05-26 12:43:44 -04002810 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002811 switch (target)
2812 {
2813 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002814 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002815 break;
2816
2817 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2818 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2819 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2820 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2821 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2822 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002823 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002824 break;
2825
2826 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002827 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002828 break;
2829
2830 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002831 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002832 break;
2833
2834 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002835 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002836 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002837 }
2838
Jamie Madillc29968b2016-01-20 11:17:23 -05002839 gl::Texture *texture =
2840 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002841 if (!texture)
2842 {
Jamie Madill437fa652016-05-03 15:13:24 -04002843 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002844 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002845 }
2846
Geoff Lang69cce582015-09-17 13:20:36 -04002847 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002848 {
Jamie Madill437fa652016-05-03 15:13:24 -04002849 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002850 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002851 }
2852
Geoff Lang5d601382014-07-22 15:14:06 -04002853 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2854
2855 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002856 {
Jamie Madill437fa652016-05-03 15:13:24 -04002857 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002858 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002859 }
2860
Geoff Langa9be0dc2014-12-17 12:34:40 -05002861 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002862 {
Jamie Madill437fa652016-05-03 15:13:24 -04002863 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002864 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002865 }
2866
2867 if (isSubImage)
2868 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002869 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2870 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2871 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002872 {
Jamie Madill437fa652016-05-03 15:13:24 -04002873 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002874 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002875 }
2876 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002877 else
2878 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002879 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002880 {
Jamie Madill437fa652016-05-03 15:13:24 -04002881 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002882 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002883 }
2884
Geoff Langeb66a6e2016-10-31 13:06:12 -04002885 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002886 {
Jamie Madill437fa652016-05-03 15:13:24 -04002887 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002888 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002889 }
2890
2891 int maxLevelDimension = (maxDimension >> level);
2892 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2893 {
Jamie Madill437fa652016-05-03 15:13:24 -04002894 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002895 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002896 }
2897 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002898
Jamie Madill0c8abca2016-07-22 20:21:26 -04002899 if (textureFormatOut)
2900 {
2901 *textureFormatOut = texture->getFormat(target, level);
2902 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002903 return true;
2904}
2905
Jamie Madillf25855c2015-11-03 11:06:18 -05002906static bool ValidateDrawBase(ValidationContext *context,
2907 GLenum mode,
2908 GLsizei count,
2909 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002910{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002911 switch (mode)
2912 {
2913 case GL_POINTS:
2914 case GL_LINES:
2915 case GL_LINE_LOOP:
2916 case GL_LINE_STRIP:
2917 case GL_TRIANGLES:
2918 case GL_TRIANGLE_STRIP:
2919 case GL_TRIANGLE_FAN:
2920 break;
2921 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002922 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002923 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002924 }
2925
Jamie Madill250d33f2014-06-06 17:09:03 -04002926 if (count < 0)
2927 {
Jamie Madill437fa652016-05-03 15:13:24 -04002928 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002929 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002930 }
2931
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002932 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002933
Jamie Madill250d33f2014-06-06 17:09:03 -04002934 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002935 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002936 {
Jamie Madill437fa652016-05-03 15:13:24 -04002937 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002938 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002939 }
2940
Jamie Madill51f40ec2016-06-15 14:06:00 -04002941 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002942 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002943 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002944 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2945 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2946 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2947 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2948 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2949 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002950 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002951 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2952 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002953 {
2954 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2955 // Section 6.10 of the WebGL 1.0 spec
2956 ERR(
2957 "This ANGLE implementation does not support separate front/back stencil "
2958 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002959 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002960 return false;
2961 }
Jamie Madillac528012014-06-20 13:21:23 -04002962 }
2963
Jamie Madill51f40ec2016-06-15 14:06:00 -04002964 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002965 {
Jamie Madill437fa652016-05-03 15:13:24 -04002966 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002968 }
2969
Geoff Lang7dd2e102014-11-10 15:19:26 -05002970 gl::Program *program = state.getProgram();
2971 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002972 {
Jamie Madill437fa652016-05-03 15:13:24 -04002973 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002974 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002975 }
2976
Geoff Lang7dd2e102014-11-10 15:19:26 -05002977 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002978 {
Jamie Madill437fa652016-05-03 15:13:24 -04002979 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002980 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002981 }
2982
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002983 // Uniform buffer validation
2984 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2985 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002986 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002987 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002988 const OffsetBindingPointer<Buffer> &uniformBuffer =
2989 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002990
Geoff Lang5d124a62015-09-15 13:03:27 -04002991 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002992 {
2993 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002994 context->handleError(
2995 Error(GL_INVALID_OPERATION,
2996 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002997 return false;
2998 }
2999
Geoff Lang5d124a62015-09-15 13:03:27 -04003000 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003001 if (uniformBufferSize == 0)
3002 {
3003 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003004 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003005 }
3006
Jamie Madill62d31cb2015-09-11 13:25:51 -04003007 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003008 {
3009 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003010 context->handleError(
3011 Error(GL_INVALID_OPERATION,
3012 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003013 return false;
3014 }
3015 }
3016
Jamie Madill250d33f2014-06-06 17:09:03 -04003017 // No-op if zero count
3018 return (count > 0);
3019}
3020
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003021bool ValidateDrawArrays(ValidationContext *context,
3022 GLenum mode,
3023 GLint first,
3024 GLsizei count,
3025 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003026{
Jamie Madillfd716582014-06-06 17:09:04 -04003027 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003031 }
3032
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003033 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003034 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003035 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
3036 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003037 {
3038 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
3039 // that does not match the current transform feedback object's draw mode (if transform feedback
3040 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003041 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003042 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003043 }
3044
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003045 if (!ValidateDrawBase(context, mode, count, primcount))
3046 {
3047 return false;
3048 }
3049
3050 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003051 {
3052 return false;
3053 }
3054
3055 return true;
3056}
3057
Geoff Langb1196682014-07-23 13:47:29 -04003058bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003059{
3060 if (primcount < 0)
3061 {
Jamie Madill437fa652016-05-03 15:13:24 -04003062 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003063 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003064 }
3065
Jamie Madill2b976812014-08-25 15:47:49 -04003066 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003067 {
3068 return false;
3069 }
3070
3071 // No-op if zero primitive count
3072 return (primcount > 0);
3073}
3074
Geoff Lang87a93302014-09-16 13:29:43 -04003075static bool ValidateDrawInstancedANGLE(Context *context)
3076{
3077 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003078 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003079
Geoff Lang7dd2e102014-11-10 15:19:26 -05003080 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003081
3082 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003083 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003084 {
3085 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003086 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003087 {
3088 return true;
3089 }
3090 }
3091
Jamie Madill437fa652016-05-03 15:13:24 -04003092 context->handleError(Error(GL_INVALID_OPERATION,
3093 "ANGLE_instanced_arrays requires that at least one active attribute"
3094 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003095 return false;
3096}
3097
3098bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
3099{
3100 if (!ValidateDrawInstancedANGLE(context))
3101 {
3102 return false;
3103 }
3104
3105 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3106}
3107
Jamie Madillf25855c2015-11-03 11:06:18 -05003108bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003109 GLenum mode,
3110 GLsizei count,
3111 GLenum type,
3112 const GLvoid *indices,
3113 GLsizei primcount,
3114 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003115{
Jamie Madill250d33f2014-06-06 17:09:03 -04003116 switch (type)
3117 {
3118 case GL_UNSIGNED_BYTE:
3119 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03003120 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003121 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03003122 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3123 {
3124 context->handleError(Error(GL_INVALID_ENUM));
3125 return false;
3126 }
3127 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003128 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003129 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003130 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003131 }
3132
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003133 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003134
3135 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003136 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003137 {
3138 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3139 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003140 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003141 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003142 }
3143
3144 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003145 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003146 {
Jamie Madill437fa652016-05-03 15:13:24 -04003147 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003148 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003149 }
3150
Jamie Madill2b976812014-08-25 15:47:49 -04003151 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003152 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003153 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003154 {
Jamie Madill437fa652016-05-03 15:13:24 -04003155 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003156 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003157 }
3158
Jamie Madillae3000b2014-08-25 15:47:51 -04003159 if (elementArrayBuffer)
3160 {
3161 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3162
3163 GLint64 offset = reinterpret_cast<GLint64>(indices);
3164 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3165
3166 // check for integer overflows
3167 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3168 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3169 {
Jamie Madill437fa652016-05-03 15:13:24 -04003170 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003171 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003172 }
3173
3174 // Check for reading past the end of the bound buffer object
3175 if (byteCount > elementArrayBuffer->getSize())
3176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003179 }
3180 }
3181 else if (!indices)
3182 {
3183 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003184 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003185 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003186 }
3187
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003188 if (!ValidateDrawBase(context, mode, count, primcount))
3189 {
3190 return false;
3191 }
3192
Jamie Madill2b976812014-08-25 15:47:49 -04003193 // Use max index to validate if our vertex buffers are large enough for the pull.
3194 // TODO: offer fast path, with disabled index validation.
3195 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3196 if (elementArrayBuffer)
3197 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003198 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003199 Error error =
3200 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3201 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003202 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003203 {
Jamie Madill437fa652016-05-03 15:13:24 -04003204 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003205 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003206 }
3207 }
3208 else
3209 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003210 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003211 }
3212
Jamie Madille79b1e12015-11-04 16:36:37 -05003213 // If we use an index greater than our maximum supported index range, return an error.
3214 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3215 // return an error if possible here.
3216 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3217 {
Jamie Madill437fa652016-05-03 15:13:24 -04003218 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003219 return false;
3220 }
3221
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003222 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003223 {
3224 return false;
3225 }
3226
Geoff Lang3edfe032015-09-04 16:38:24 -04003227 // No op if there are no real indices in the index data (all are primitive restart).
3228 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003229}
3230
Geoff Langb1196682014-07-23 13:47:29 -04003231bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003232 GLenum mode,
3233 GLsizei count,
3234 GLenum type,
3235 const GLvoid *indices,
3236 GLsizei primcount,
3237 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003238{
3239 if (primcount < 0)
3240 {
Jamie Madill437fa652016-05-03 15:13:24 -04003241 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003242 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003243 }
3244
Jamie Madill2b976812014-08-25 15:47:49 -04003245 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003246 {
3247 return false;
3248 }
3249
3250 // No-op zero primitive count
3251 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003252}
3253
Geoff Lang3edfe032015-09-04 16:38:24 -04003254bool ValidateDrawElementsInstancedANGLE(Context *context,
3255 GLenum mode,
3256 GLsizei count,
3257 GLenum type,
3258 const GLvoid *indices,
3259 GLsizei primcount,
3260 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003261{
3262 if (!ValidateDrawInstancedANGLE(context))
3263 {
3264 return false;
3265 }
3266
3267 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3268}
3269
Geoff Langb1196682014-07-23 13:47:29 -04003270bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003271 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003272{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003273 if (!ValidFramebufferTarget(target))
3274 {
Jamie Madill437fa652016-05-03 15:13:24 -04003275 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003276 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003277 }
3278
3279 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003280 {
3281 return false;
3282 }
3283
Jamie Madill55ec3b12014-07-03 10:38:57 -04003284 if (texture != 0)
3285 {
3286 gl::Texture *tex = context->getTexture(texture);
3287
3288 if (tex == NULL)
3289 {
Jamie Madill437fa652016-05-03 15:13:24 -04003290 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003291 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003292 }
3293
3294 if (level < 0)
3295 {
Jamie Madill437fa652016-05-03 15:13:24 -04003296 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003297 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003298 }
3299 }
3300
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003301 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003302 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003303
Jamie Madill84115c92015-04-23 15:00:07 -04003304 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003305 {
Jamie Madill437fa652016-05-03 15:13:24 -04003306 context->handleError(
3307 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003308 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003309 }
3310
3311 return true;
3312}
3313
Geoff Langb1196682014-07-23 13:47:29 -04003314bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003315 GLenum textarget, GLuint texture, GLint level)
3316{
Geoff Lang95663912015-04-02 15:54:45 -04003317 // 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 +03003318 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3319 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003320 {
Jamie Madill437fa652016-05-03 15:13:24 -04003321 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003322 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003323 }
3324
3325 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003326 {
3327 return false;
3328 }
3329
Jamie Madill55ec3b12014-07-03 10:38:57 -04003330 if (texture != 0)
3331 {
3332 gl::Texture *tex = context->getTexture(texture);
3333 ASSERT(tex);
3334
Jamie Madill2a6564e2014-07-11 09:53:19 -04003335 const gl::Caps &caps = context->getCaps();
3336
Jamie Madill55ec3b12014-07-03 10:38:57 -04003337 switch (textarget)
3338 {
3339 case GL_TEXTURE_2D:
3340 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003341 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003342 {
Jamie Madill437fa652016-05-03 15:13:24 -04003343 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003344 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003345 }
3346 if (tex->getTarget() != GL_TEXTURE_2D)
3347 {
Jamie Madill437fa652016-05-03 15:13:24 -04003348 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003349 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003350 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003351 }
3352 break;
3353
3354 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3355 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3356 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3357 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3358 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3359 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3360 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003361 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003362 {
Jamie Madill437fa652016-05-03 15:13:24 -04003363 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003364 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003365 }
3366 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3367 {
Jamie Madill437fa652016-05-03 15:13:24 -04003368 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003369 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003370 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003371 }
3372 break;
3373
3374 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003375 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003376 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003377 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003378
Jamie Madilla3944d42016-07-22 22:13:26 -04003379 const Format &format = tex->getFormat(textarget, level);
3380 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003381 {
Jamie Madill437fa652016-05-03 15:13:24 -04003382 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003383 return false;
3384 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003385 }
3386
Jamie Madill570f7c82014-07-03 10:38:54 -04003387 return true;
3388}
3389
Geoff Langb1196682014-07-23 13:47:29 -04003390bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003391{
3392 if (program == 0)
3393 {
Jamie Madill437fa652016-05-03 15:13:24 -04003394 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003395 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003396 }
3397
Dian Xiang769769a2015-09-09 15:20:08 -07003398 gl::Program *programObject = GetValidProgram(context, program);
3399 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003400 {
3401 return false;
3402 }
3403
Jamie Madill0063c512014-08-25 15:47:53 -04003404 if (!programObject || !programObject->isLinked())
3405 {
Jamie Madill437fa652016-05-03 15:13:24 -04003406 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003407 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003408 }
3409
Geoff Lang7dd2e102014-11-10 15:19:26 -05003410 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003411 {
Jamie Madill437fa652016-05-03 15:13:24 -04003412 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003413 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003414 }
3415
Jamie Madill0063c512014-08-25 15:47:53 -04003416 return true;
3417}
3418
Geoff Langb1196682014-07-23 13:47:29 -04003419bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003420{
3421 return ValidateGetUniformBase(context, program, location);
3422}
3423
Geoff Langb1196682014-07-23 13:47:29 -04003424bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003425{
Jamie Madill78f41802014-08-25 15:47:55 -04003426 return ValidateGetUniformBase(context, program, location);
3427}
3428
Geoff Langf41d0ee2016-10-07 13:04:23 -04003429static bool ValidateSizedGetUniform(Context *context,
3430 GLuint program,
3431 GLint location,
3432 GLsizei bufSize,
3433 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003434{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003435 if (length)
3436 {
3437 *length = 0;
3438 }
3439
Jamie Madill78f41802014-08-25 15:47:55 -04003440 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003441 {
Jamie Madill78f41802014-08-25 15:47:55 -04003442 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003443 }
3444
Geoff Langf41d0ee2016-10-07 13:04:23 -04003445 if (bufSize < 0)
3446 {
3447 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3448 return false;
3449 }
3450
Jamie Madilla502c742014-08-28 17:19:13 -04003451 gl::Program *programObject = context->getProgram(program);
3452 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003453
Jamie Madill78f41802014-08-25 15:47:55 -04003454 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003455 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3456 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003457 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003458 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003459 context->handleError(
3460 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003461 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003462 }
3463
Geoff Langf41d0ee2016-10-07 13:04:23 -04003464 if (length)
3465 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003466 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003467 }
3468
Jamie Madill0063c512014-08-25 15:47:53 -04003469 return true;
3470}
3471
Geoff Langb1196682014-07-23 13:47:29 -04003472bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003473{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003474 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003475}
3476
Geoff Langb1196682014-07-23 13:47:29 -04003477bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003478{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003479 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3480}
3481
3482bool ValidateGetUniformfvRobustANGLE(Context *context,
3483 GLuint program,
3484 GLint location,
3485 GLsizei bufSize,
3486 GLsizei *length,
3487 GLfloat *params)
3488{
3489 if (!ValidateRobustEntryPoint(context, bufSize))
3490 {
3491 return false;
3492 }
3493
3494 // bufSize is validated in ValidateSizedGetUniform
3495 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3496}
3497
3498bool ValidateGetUniformivRobustANGLE(Context *context,
3499 GLuint program,
3500 GLint location,
3501 GLsizei bufSize,
3502 GLsizei *length,
3503 GLint *params)
3504{
3505 if (!ValidateRobustEntryPoint(context, bufSize))
3506 {
3507 return false;
3508 }
3509
3510 // bufSize is validated in ValidateSizedGetUniform
3511 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3512}
3513
3514bool ValidateGetUniformuivRobustANGLE(Context *context,
3515 GLuint program,
3516 GLint location,
3517 GLsizei bufSize,
3518 GLsizei *length,
3519 GLuint *params)
3520{
3521 if (!ValidateRobustEntryPoint(context, bufSize))
3522 {
3523 return false;
3524 }
3525
3526 if (context->getClientMajorVersion() < 3)
3527 {
3528 context->handleError(
3529 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3530 return false;
3531 }
3532
3533 // bufSize is validated in ValidateSizedGetUniform
3534 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003535}
3536
Austin Kinross08332632015-05-05 13:35:47 -07003537bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3538 const GLenum *attachments, bool defaultFramebuffer)
3539{
3540 if (numAttachments < 0)
3541 {
Jamie Madill437fa652016-05-03 15:13:24 -04003542 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003543 return false;
3544 }
3545
3546 for (GLsizei i = 0; i < numAttachments; ++i)
3547 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003548 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003549 {
3550 if (defaultFramebuffer)
3551 {
Jamie Madill437fa652016-05-03 15:13:24 -04003552 context->handleError(Error(
3553 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003554 return false;
3555 }
3556
3557 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3558 {
Jamie Madill437fa652016-05-03 15:13:24 -04003559 context->handleError(Error(GL_INVALID_OPERATION,
3560 "Requested color attachment is greater than the maximum "
3561 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003562 return false;
3563 }
3564 }
3565 else
3566 {
3567 switch (attachments[i])
3568 {
3569 case GL_DEPTH_ATTACHMENT:
3570 case GL_STENCIL_ATTACHMENT:
3571 case GL_DEPTH_STENCIL_ATTACHMENT:
3572 if (defaultFramebuffer)
3573 {
Jamie Madill437fa652016-05-03 15:13:24 -04003574 context->handleError(
3575 Error(GL_INVALID_ENUM,
3576 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003577 return false;
3578 }
3579 break;
3580 case GL_COLOR:
3581 case GL_DEPTH:
3582 case GL_STENCIL:
3583 if (!defaultFramebuffer)
3584 {
Jamie Madill437fa652016-05-03 15:13:24 -04003585 context->handleError(
3586 Error(GL_INVALID_ENUM,
3587 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003588 return false;
3589 }
3590 break;
3591 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003592 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003593 return false;
3594 }
3595 }
3596 }
3597
3598 return true;
3599}
3600
Austin Kinross6ee1e782015-05-29 17:05:37 -07003601bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3602{
3603 // Note that debug marker calls must not set error state
3604
3605 if (length < 0)
3606 {
3607 return false;
3608 }
3609
3610 if (marker == nullptr)
3611 {
3612 return false;
3613 }
3614
3615 return true;
3616}
3617
3618bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3619{
3620 // Note that debug marker calls must not set error state
3621
3622 if (length < 0)
3623 {
3624 return false;
3625 }
3626
3627 if (length > 0 && marker == nullptr)
3628 {
3629 return false;
3630 }
3631
3632 return true;
3633}
3634
Geoff Langdcab33b2015-07-21 13:03:16 -04003635bool ValidateEGLImageTargetTexture2DOES(Context *context,
3636 egl::Display *display,
3637 GLenum target,
3638 egl::Image *image)
3639{
Geoff Langa8406172015-07-21 16:53:39 -04003640 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3641 {
Jamie Madill437fa652016-05-03 15:13:24 -04003642 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003643 return false;
3644 }
3645
3646 switch (target)
3647 {
3648 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003649 if (!context->getExtensions().eglImage)
3650 {
3651 context->handleError(Error(
3652 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3653 }
3654 break;
3655
3656 case GL_TEXTURE_EXTERNAL_OES:
3657 if (!context->getExtensions().eglImageExternal)
3658 {
3659 context->handleError(Error(
3660 GL_INVALID_ENUM,
3661 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3662 }
Geoff Langa8406172015-07-21 16:53:39 -04003663 break;
3664
3665 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003666 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003667 return false;
3668 }
3669
3670 if (!display->isValidImage(image))
3671 {
Jamie Madill437fa652016-05-03 15:13:24 -04003672 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003673 return false;
3674 }
3675
3676 if (image->getSamples() > 0)
3677 {
Jamie Madill437fa652016-05-03 15:13:24 -04003678 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003679 "cannot create a 2D texture from a multisampled EGL image."));
3680 return false;
3681 }
3682
Jamie Madilla3944d42016-07-22 22:13:26 -04003683 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003684 if (!textureCaps.texturable)
3685 {
Jamie Madill437fa652016-05-03 15:13:24 -04003686 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003687 "EGL image internal format is not supported as a texture."));
3688 return false;
3689 }
3690
Geoff Langdcab33b2015-07-21 13:03:16 -04003691 return true;
3692}
3693
3694bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3695 egl::Display *display,
3696 GLenum target,
3697 egl::Image *image)
3698{
Geoff Langa8406172015-07-21 16:53:39 -04003699 if (!context->getExtensions().eglImage)
3700 {
Jamie Madill437fa652016-05-03 15:13:24 -04003701 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003702 return false;
3703 }
3704
3705 switch (target)
3706 {
3707 case GL_RENDERBUFFER:
3708 break;
3709
3710 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003711 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003712 return false;
3713 }
3714
3715 if (!display->isValidImage(image))
3716 {
Jamie Madill437fa652016-05-03 15:13:24 -04003717 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003718 return false;
3719 }
3720
Jamie Madilla3944d42016-07-22 22:13:26 -04003721 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003722 if (!textureCaps.renderable)
3723 {
Jamie Madill437fa652016-05-03 15:13:24 -04003724 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003725 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3726 return false;
3727 }
3728
Geoff Langdcab33b2015-07-21 13:03:16 -04003729 return true;
3730}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003731
3732bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3733{
Geoff Lang36167ab2015-12-07 10:27:14 -05003734 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003735 {
3736 // The default VAO should always exist
3737 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003738 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003739 return false;
3740 }
3741
3742 return true;
3743}
3744
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003745bool ValidateLinkProgram(Context *context, GLuint program)
3746{
3747 if (context->hasActiveTransformFeedback(program))
3748 {
3749 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003750 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003751 "Cannot link program while program is associated with an active "
3752 "transform feedback object."));
3753 return false;
3754 }
3755 return true;
3756}
3757
Geoff Langc5629752015-12-07 16:29:04 -05003758bool ValidateProgramBinaryBase(Context *context,
3759 GLuint program,
3760 GLenum binaryFormat,
3761 const void *binary,
3762 GLint length)
3763{
3764 Program *programObject = GetValidProgram(context, program);
3765 if (programObject == nullptr)
3766 {
3767 return false;
3768 }
3769
3770 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3771 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3772 programBinaryFormats.end())
3773 {
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003775 return false;
3776 }
3777
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003778 if (context->hasActiveTransformFeedback(program))
3779 {
3780 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003781 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003782 "Cannot change program binary while program is associated with "
3783 "an active transform feedback object."));
3784 return false;
3785 }
3786
Geoff Langc5629752015-12-07 16:29:04 -05003787 return true;
3788}
3789
3790bool ValidateGetProgramBinaryBase(Context *context,
3791 GLuint program,
3792 GLsizei bufSize,
3793 GLsizei *length,
3794 GLenum *binaryFormat,
3795 void *binary)
3796{
3797 Program *programObject = GetValidProgram(context, program);
3798 if (programObject == nullptr)
3799 {
3800 return false;
3801 }
3802
3803 if (!programObject->isLinked())
3804 {
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003806 return false;
3807 }
3808
3809 return true;
3810}
Jamie Madillc29968b2016-01-20 11:17:23 -05003811
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003812bool ValidateUseProgram(Context *context, GLuint program)
3813{
3814 if (program != 0)
3815 {
3816 Program *programObject = context->getProgram(program);
3817 if (!programObject)
3818 {
3819 // ES 3.1.0 section 7.3 page 72
3820 if (context->getShader(program))
3821 {
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003823 Error(GL_INVALID_OPERATION,
3824 "Attempted to use a single shader instead of a shader program."));
3825 return false;
3826 }
3827 else
3828 {
Jamie Madill437fa652016-05-03 15:13:24 -04003829 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003830 return false;
3831 }
3832 }
3833 if (!programObject->isLinked())
3834 {
Jamie Madill437fa652016-05-03 15:13:24 -04003835 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003836 return false;
3837 }
3838 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003839 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003840 {
3841 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003842 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003843 Error(GL_INVALID_OPERATION,
3844 "Cannot change active program while transform feedback is unpaused."));
3845 return false;
3846 }
3847
3848 return true;
3849}
3850
Jamie Madillc29968b2016-01-20 11:17:23 -05003851bool ValidateCopyTexImage2D(ValidationContext *context,
3852 GLenum target,
3853 GLint level,
3854 GLenum internalformat,
3855 GLint x,
3856 GLint y,
3857 GLsizei width,
3858 GLsizei height,
3859 GLint border)
3860{
Martin Radev1be913c2016-07-11 17:59:16 +03003861 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003862 {
3863 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3864 0, x, y, width, height, border);
3865 }
3866
Martin Radev1be913c2016-07-11 17:59:16 +03003867 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003868 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3869 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003870}
Jamie Madillc29968b2016-01-20 11:17:23 -05003871
3872bool ValidateFramebufferRenderbuffer(Context *context,
3873 GLenum target,
3874 GLenum attachment,
3875 GLenum renderbuffertarget,
3876 GLuint renderbuffer)
3877{
3878 if (!ValidFramebufferTarget(target) ||
3879 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3880 {
Jamie Madill437fa652016-05-03 15:13:24 -04003881 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003882 return false;
3883 }
3884
3885 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3886 renderbuffertarget, renderbuffer);
3887}
3888
3889bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3890{
3891 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3892 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3893 {
Jamie Madill437fa652016-05-03 15:13:24 -04003894 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003895 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3896 return false;
3897 }
3898
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003899 ASSERT(context->getGLState().getDrawFramebuffer());
3900 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003901 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3902
3903 // This should come first before the check for the default frame buffer
3904 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3905 // rather than INVALID_OPERATION
3906 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3907 {
3908 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3909
3910 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003911 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3912 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003913 {
3914 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003915 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3916 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3917 // 3.1 is still a bit ambiguous about the error, but future specs are
3918 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003919 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003920 return false;
3921 }
3922 else if (bufs[colorAttachment] >= maxColorAttachment)
3923 {
Jamie Madill437fa652016-05-03 15:13:24 -04003924 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003925 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003926 return false;
3927 }
3928 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3929 frameBufferId != 0)
3930 {
3931 // INVALID_OPERATION-GL is bound to buffer and ith argument
3932 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003933 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003934 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3935 return false;
3936 }
3937 }
3938
3939 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3940 // and n is not 1 or bufs is bound to value other than BACK and NONE
3941 if (frameBufferId == 0)
3942 {
3943 if (n != 1)
3944 {
Jamie Madill437fa652016-05-03 15:13:24 -04003945 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003946 "n must be 1 when GL is bound to the default framebuffer"));
3947 return false;
3948 }
3949
3950 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3951 {
Jamie Madill437fa652016-05-03 15:13:24 -04003952 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003953 GL_INVALID_OPERATION,
3954 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3955 return false;
3956 }
3957 }
3958
3959 return true;
3960}
3961
3962bool ValidateCopyTexSubImage2D(Context *context,
3963 GLenum target,
3964 GLint level,
3965 GLint xoffset,
3966 GLint yoffset,
3967 GLint x,
3968 GLint y,
3969 GLsizei width,
3970 GLsizei height)
3971{
Martin Radev1be913c2016-07-11 17:59:16 +03003972 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003973 {
3974 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3975 yoffset, x, y, width, height, 0);
3976 }
3977
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003978 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3979 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003980}
3981
Geoff Lang496c02d2016-10-20 11:38:11 -07003982bool ValidateGetBufferPointervBase(Context *context,
3983 GLenum target,
3984 GLenum pname,
3985 GLsizei *length,
3986 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003987{
Geoff Lang496c02d2016-10-20 11:38:11 -07003988 if (length)
3989 {
3990 *length = 0;
3991 }
3992
3993 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3994 {
3995 context->handleError(
3996 Error(GL_INVALID_OPERATION,
3997 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
3998 return false;
3999 }
4000
Olli Etuaho4f667482016-03-30 15:56:35 +03004001 if (!ValidBufferTarget(context, target))
4002 {
Jamie Madill437fa652016-05-03 15:13:24 -04004003 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004004 return false;
4005 }
4006
Geoff Lang496c02d2016-10-20 11:38:11 -07004007 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004008 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004009 case GL_BUFFER_MAP_POINTER:
4010 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004011
Geoff Lang496c02d2016-10-20 11:38:11 -07004012 default:
4013 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4014 return false;
4015 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004016
4017 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4018 // target bound to zero generate an INVALID_OPERATION error."
4019 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004020 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004021 {
Jamie Madill437fa652016-05-03 15:13:24 -04004022 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004023 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4024 return false;
4025 }
4026
Geoff Lang496c02d2016-10-20 11:38:11 -07004027 if (length)
4028 {
4029 *length = 1;
4030 }
4031
Olli Etuaho4f667482016-03-30 15:56:35 +03004032 return true;
4033}
4034
4035bool ValidateUnmapBufferBase(Context *context, GLenum target)
4036{
4037 if (!ValidBufferTarget(context, target))
4038 {
Jamie Madill437fa652016-05-03 15:13:24 -04004039 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004040 return false;
4041 }
4042
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004043 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004044
4045 if (buffer == nullptr || !buffer->isMapped())
4046 {
Jamie Madill437fa652016-05-03 15:13:24 -04004047 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004048 return false;
4049 }
4050
4051 return true;
4052}
4053
4054bool ValidateMapBufferRangeBase(Context *context,
4055 GLenum target,
4056 GLintptr offset,
4057 GLsizeiptr length,
4058 GLbitfield access)
4059{
4060 if (!ValidBufferTarget(context, target))
4061 {
Jamie Madill437fa652016-05-03 15:13:24 -04004062 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004063 return false;
4064 }
4065
4066 if (offset < 0 || length < 0)
4067 {
Jamie Madill437fa652016-05-03 15:13:24 -04004068 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004069 return false;
4070 }
4071
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004072 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004073
4074 if (!buffer)
4075 {
Jamie Madill437fa652016-05-03 15:13:24 -04004076 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004077 return false;
4078 }
4079
4080 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004081 CheckedNumeric<size_t> checkedOffset(offset);
4082 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004083
Jamie Madille2e406c2016-06-02 13:04:10 -04004084 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004085 {
Jamie Madill437fa652016-05-03 15:13:24 -04004086 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004087 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4088 return false;
4089 }
4090
4091 // Check for invalid bits in the mask
4092 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4093 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4094 GL_MAP_UNSYNCHRONIZED_BIT;
4095
4096 if (access & ~(allAccessBits))
4097 {
Jamie Madill437fa652016-05-03 15:13:24 -04004098 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004099 return false;
4100 }
4101
4102 if (length == 0)
4103 {
Jamie Madill437fa652016-05-03 15:13:24 -04004104 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004105 return false;
4106 }
4107
4108 if (buffer->isMapped())
4109 {
Jamie Madill437fa652016-05-03 15:13:24 -04004110 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004111 return false;
4112 }
4113
4114 // Check for invalid bit combinations
4115 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4116 {
Jamie Madill437fa652016-05-03 15:13:24 -04004117 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004118 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4119 return false;
4120 }
4121
4122 GLbitfield writeOnlyBits =
4123 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4124
4125 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4126 {
Jamie Madill437fa652016-05-03 15:13:24 -04004127 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004128 "Invalid access bits when mapping buffer for reading: 0x%X.",
4129 access));
4130 return false;
4131 }
4132
4133 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4134 {
Jamie Madill437fa652016-05-03 15:13:24 -04004135 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004136 GL_INVALID_OPERATION,
4137 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4138 return false;
4139 }
4140 return true;
4141}
4142
4143bool ValidateFlushMappedBufferRangeBase(Context *context,
4144 GLenum target,
4145 GLintptr offset,
4146 GLsizeiptr length)
4147{
4148 if (offset < 0 || length < 0)
4149 {
Jamie Madill437fa652016-05-03 15:13:24 -04004150 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004151 return false;
4152 }
4153
4154 if (!ValidBufferTarget(context, target))
4155 {
Jamie Madill437fa652016-05-03 15:13:24 -04004156 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004157 return false;
4158 }
4159
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004160 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004161
4162 if (buffer == nullptr)
4163 {
Jamie Madill437fa652016-05-03 15:13:24 -04004164 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004165 return false;
4166 }
4167
4168 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4169 {
Jamie Madill437fa652016-05-03 15:13:24 -04004170 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004171 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4172 return false;
4173 }
4174
4175 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004176 CheckedNumeric<size_t> checkedOffset(offset);
4177 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004178
Jamie Madille2e406c2016-06-02 13:04:10 -04004179 if (!checkedSize.IsValid() ||
4180 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004181 {
Jamie Madill437fa652016-05-03 15:13:24 -04004182 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004183 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4184 return false;
4185 }
4186
4187 return true;
4188}
4189
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004190bool ValidateGenerateMipmap(Context *context, GLenum target)
4191{
4192 if (!ValidTextureTarget(context, target))
4193 {
4194 context->handleError(Error(GL_INVALID_ENUM));
4195 return false;
4196 }
4197
4198 Texture *texture = context->getTargetTexture(target);
4199
4200 if (texture == nullptr)
4201 {
4202 context->handleError(Error(GL_INVALID_OPERATION));
4203 return false;
4204 }
4205
4206 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4207
4208 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4209 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4210 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4211 {
4212 context->handleError(Error(GL_INVALID_OPERATION));
4213 return false;
4214 }
4215
Jamie Madilla3944d42016-07-22 22:13:26 -04004216 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4217 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4218 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004219
4220 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4221 // unsized formats or that are color renderable and filterable. Since we do not track if
4222 // the texture was created with sized or unsized format (only sized formats are stored),
4223 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4224 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4225 // textures since they're the only texture format that can be created with unsized formats
4226 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4227 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004228 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4229 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004230 {
4231 context->handleError(Error(GL_INVALID_OPERATION));
4232 return false;
4233 }
4234
4235 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004236 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004237 {
4238 context->handleError(Error(GL_INVALID_OPERATION));
4239 return false;
4240 }
4241
4242 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004243 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004244 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4245 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4246 {
Geoff Lang55482a12016-11-21 16:54:01 -05004247 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004248 context->handleError(Error(GL_INVALID_OPERATION));
4249 return false;
4250 }
4251
4252 // Cube completeness check
4253 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4254 {
4255 context->handleError(Error(GL_INVALID_OPERATION));
4256 return false;
4257 }
4258
4259 return true;
4260}
4261
Olli Etuaho41997e72016-03-10 13:38:39 +02004262bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4263{
4264 return ValidateGenOrDelete(context, n);
4265}
4266
4267bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4268{
4269 return ValidateGenOrDelete(context, n);
4270}
4271
4272bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4273{
4274 return ValidateGenOrDelete(context, n);
4275}
4276
4277bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4278{
4279 return ValidateGenOrDelete(context, n);
4280}
4281
4282bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4283{
4284 return ValidateGenOrDelete(context, n);
4285}
4286
4287bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4288{
4289 return ValidateGenOrDelete(context, n);
4290}
4291
4292bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4293{
4294 return ValidateGenOrDelete(context, n);
4295}
4296
4297bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4298{
4299 return ValidateGenOrDelete(context, n);
4300}
4301
4302bool ValidateGenOrDelete(Context *context, GLint n)
4303{
4304 if (n < 0)
4305 {
Jamie Madill437fa652016-05-03 15:13:24 -04004306 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004307 return false;
4308 }
4309 return true;
4310}
4311
Geoff Langf41a7152016-09-19 15:11:17 -04004312bool ValidateEnable(Context *context, GLenum cap)
4313{
4314 if (!ValidCap(context, cap, false))
4315 {
4316 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4317 return false;
4318 }
4319
4320 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4321 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4322 {
4323 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4324 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4325
4326 // We also output an error message to the debugger window if tracing is active, so that
4327 // developers can see the error message.
4328 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004329 return false;
4330 }
4331
4332 return true;
4333}
4334
4335bool ValidateDisable(Context *context, GLenum cap)
4336{
4337 if (!ValidCap(context, cap, false))
4338 {
4339 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4340 return false;
4341 }
4342
4343 return true;
4344}
4345
4346bool ValidateIsEnabled(Context *context, GLenum cap)
4347{
4348 if (!ValidCap(context, cap, true))
4349 {
4350 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4351 return false;
4352 }
4353
4354 return true;
4355}
4356
Geoff Langff5b2d52016-09-07 11:32:23 -04004357bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4358{
4359 if (!context->getExtensions().robustClientMemory)
4360 {
4361 context->handleError(
4362 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4363 return false;
4364 }
4365
4366 if (bufSize < 0)
4367 {
4368 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4369 return false;
4370 }
4371
4372 return true;
4373}
4374
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004375bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4376{
4377 if (bufSize < numParams)
4378 {
4379 context->handleError(Error(GL_INVALID_OPERATION,
4380 "%u parameters are required but %i were provided.", numParams,
4381 bufSize));
4382 return false;
4383 }
4384
4385 return true;
4386}
4387
Geoff Langff5b2d52016-09-07 11:32:23 -04004388bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4389 GLenum target,
4390 GLenum attachment,
4391 GLenum pname,
4392 GLsizei *numParams)
4393{
4394 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4395 *numParams = 1;
4396
4397 if (!ValidFramebufferTarget(target))
4398 {
4399 context->handleError(Error(GL_INVALID_ENUM));
4400 return false;
4401 }
4402
4403 int clientVersion = context->getClientMajorVersion();
4404
4405 switch (pname)
4406 {
4407 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4408 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4409 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4410 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4411 break;
4412
4413 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4414 if (clientVersion < 3 && !context->getExtensions().sRGB)
4415 {
4416 context->handleError(Error(GL_INVALID_ENUM));
4417 return false;
4418 }
4419 break;
4420
4421 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4422 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4423 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4424 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4425 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4426 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4427 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4428 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4429 if (clientVersion < 3)
4430 {
4431 context->handleError(Error(GL_INVALID_ENUM));
4432 return false;
4433 }
4434 break;
4435
4436 default:
4437 context->handleError(Error(GL_INVALID_ENUM));
4438 return false;
4439 }
4440
4441 // Determine if the attachment is a valid enum
4442 switch (attachment)
4443 {
4444 case GL_BACK:
4445 case GL_FRONT:
4446 case GL_DEPTH:
4447 case GL_STENCIL:
4448 case GL_DEPTH_STENCIL_ATTACHMENT:
4449 if (clientVersion < 3)
4450 {
4451 context->handleError(Error(GL_INVALID_ENUM));
4452 return false;
4453 }
4454 break;
4455
4456 case GL_DEPTH_ATTACHMENT:
4457 case GL_STENCIL_ATTACHMENT:
4458 break;
4459
4460 default:
4461 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4462 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4463 {
4464 context->handleError(Error(GL_INVALID_ENUM));
4465 return false;
4466 }
4467 break;
4468 }
4469
4470 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4471 ASSERT(framebuffer);
4472
4473 if (framebuffer->id() == 0)
4474 {
4475 if (clientVersion < 3)
4476 {
4477 context->handleError(Error(GL_INVALID_OPERATION));
4478 return false;
4479 }
4480
4481 switch (attachment)
4482 {
4483 case GL_BACK:
4484 case GL_DEPTH:
4485 case GL_STENCIL:
4486 break;
4487
4488 default:
4489 context->handleError(Error(GL_INVALID_OPERATION));
4490 return false;
4491 }
4492 }
4493 else
4494 {
4495 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4496 {
4497 // Valid attachment query
4498 }
4499 else
4500 {
4501 switch (attachment)
4502 {
4503 case GL_DEPTH_ATTACHMENT:
4504 case GL_STENCIL_ATTACHMENT:
4505 break;
4506
4507 case GL_DEPTH_STENCIL_ATTACHMENT:
4508 if (!framebuffer->hasValidDepthStencil())
4509 {
4510 context->handleError(Error(GL_INVALID_OPERATION));
4511 return false;
4512 }
4513 break;
4514
4515 default:
4516 context->handleError(Error(GL_INVALID_OPERATION));
4517 return false;
4518 }
4519 }
4520 }
4521
4522 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4523 if (attachmentObject)
4524 {
4525 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4526 attachmentObject->type() == GL_TEXTURE ||
4527 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4528
4529 switch (pname)
4530 {
4531 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4532 if (attachmentObject->type() != GL_RENDERBUFFER &&
4533 attachmentObject->type() != GL_TEXTURE)
4534 {
4535 context->handleError(Error(GL_INVALID_ENUM));
4536 return false;
4537 }
4538 break;
4539
4540 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4541 if (attachmentObject->type() != GL_TEXTURE)
4542 {
4543 context->handleError(Error(GL_INVALID_ENUM));
4544 return false;
4545 }
4546 break;
4547
4548 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4549 if (attachmentObject->type() != GL_TEXTURE)
4550 {
4551 context->handleError(Error(GL_INVALID_ENUM));
4552 return false;
4553 }
4554 break;
4555
4556 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4557 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4558 {
4559 context->handleError(Error(GL_INVALID_OPERATION));
4560 return false;
4561 }
4562 break;
4563
4564 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4565 if (attachmentObject->type() != GL_TEXTURE)
4566 {
4567 context->handleError(Error(GL_INVALID_ENUM));
4568 return false;
4569 }
4570 break;
4571
4572 default:
4573 break;
4574 }
4575 }
4576 else
4577 {
4578 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4579 // is NONE, then querying any other pname will generate INVALID_ENUM.
4580
4581 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4582 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4583 // INVALID_OPERATION for all other pnames
4584
4585 switch (pname)
4586 {
4587 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4588 break;
4589
4590 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4591 if (clientVersion < 3)
4592 {
4593 context->handleError(Error(GL_INVALID_ENUM));
4594 return false;
4595 }
4596 break;
4597
4598 default:
4599 if (clientVersion < 3)
4600 {
4601 context->handleError(Error(GL_INVALID_ENUM));
4602 return false;
4603 }
4604 else
4605 {
4606 context->handleError(Error(GL_INVALID_OPERATION));
4607 return false;
4608 }
4609 }
4610 }
4611
4612 return true;
4613}
4614
4615bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4616 GLenum target,
4617 GLenum attachment,
4618 GLenum pname,
4619 GLsizei bufSize,
4620 GLsizei *numParams)
4621{
4622 if (!ValidateRobustEntryPoint(context, bufSize))
4623 {
4624 return false;
4625 }
4626
4627 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4628 {
4629 return false;
4630 }
4631
4632 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4633 {
4634 return false;
4635 }
4636
4637 return true;
4638}
4639
4640bool ValidateGetBufferParameteriv(ValidationContext *context,
4641 GLenum target,
4642 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004643 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004644{
Geoff Langebebe1c2016-10-14 12:01:31 -04004645 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004646}
4647
4648bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4649 GLenum target,
4650 GLenum pname,
4651 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004652 GLsizei *length,
4653 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004654{
4655 if (!ValidateRobustEntryPoint(context, bufSize))
4656 {
4657 return false;
4658 }
4659
Geoff Langebebe1c2016-10-14 12:01:31 -04004660 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004661 {
4662 return false;
4663 }
4664
Geoff Langebebe1c2016-10-14 12:01:31 -04004665 if (!ValidateRobustBufferSize(context, bufSize, *length))
4666 {
4667 return false;
4668 }
4669
4670 return true;
4671}
4672
4673bool ValidateGetBufferParameteri64v(ValidationContext *context,
4674 GLenum target,
4675 GLenum pname,
4676 GLint64 *params)
4677{
4678 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4679}
4680
4681bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4682 GLenum target,
4683 GLenum pname,
4684 GLsizei bufSize,
4685 GLsizei *length,
4686 GLint64 *params)
4687{
4688 if (!ValidateRobustEntryPoint(context, bufSize))
4689 {
4690 return false;
4691 }
4692
4693 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4694 {
4695 return false;
4696 }
4697
4698 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004699 {
4700 return false;
4701 }
4702
4703 return true;
4704}
4705
4706bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4707{
4708 // Currently, all GetProgramiv queries return 1 parameter
4709 *numParams = 1;
4710
4711 Program *programObject = GetValidProgram(context, program);
4712 if (!programObject)
4713 {
4714 return false;
4715 }
4716
4717 switch (pname)
4718 {
4719 case GL_DELETE_STATUS:
4720 case GL_LINK_STATUS:
4721 case GL_VALIDATE_STATUS:
4722 case GL_INFO_LOG_LENGTH:
4723 case GL_ATTACHED_SHADERS:
4724 case GL_ACTIVE_ATTRIBUTES:
4725 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4726 case GL_ACTIVE_UNIFORMS:
4727 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4728 break;
4729
4730 case GL_PROGRAM_BINARY_LENGTH:
4731 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4732 {
4733 context->handleError(Error(GL_INVALID_ENUM,
4734 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4735 "GL_OES_get_program_binary or ES 3.0."));
4736 return false;
4737 }
4738 break;
4739
4740 case GL_ACTIVE_UNIFORM_BLOCKS:
4741 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4742 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4743 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4744 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4745 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4746 if (context->getClientMajorVersion() < 3)
4747 {
4748 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4749 return false;
4750 }
4751 break;
4752
4753 default:
4754 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4755 return false;
4756 }
4757
4758 return true;
4759}
4760
4761bool ValidateGetProgramivRobustANGLE(Context *context,
4762 GLuint program,
4763 GLenum pname,
4764 GLsizei bufSize,
4765 GLsizei *numParams)
4766{
4767 if (!ValidateRobustEntryPoint(context, bufSize))
4768 {
4769 return false;
4770 }
4771
4772 if (!ValidateGetProgramiv(context, program, pname, numParams))
4773 {
4774 return false;
4775 }
4776
4777 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4778 {
4779 return false;
4780 }
4781
4782 return true;
4783}
4784
Geoff Lang740d9022016-10-07 11:20:52 -04004785bool ValidateGetRenderbufferParameteriv(Context *context,
4786 GLenum target,
4787 GLenum pname,
4788 GLint *params)
4789{
4790 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4791}
4792
4793bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4794 GLenum target,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 GLsizei *length,
4798 GLint *params)
4799{
4800 if (!ValidateRobustEntryPoint(context, bufSize))
4801 {
4802 return false;
4803 }
4804
4805 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4806 {
4807 return false;
4808 }
4809
4810 if (!ValidateRobustBufferSize(context, bufSize, *length))
4811 {
4812 return false;
4813 }
4814
4815 return true;
4816}
4817
Geoff Langd7d0ed32016-10-07 11:33:51 -04004818bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4819{
4820 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4821}
4822
4823bool ValidateGetShaderivRobustANGLE(Context *context,
4824 GLuint shader,
4825 GLenum pname,
4826 GLsizei bufSize,
4827 GLsizei *length,
4828 GLint *params)
4829{
4830 if (!ValidateRobustEntryPoint(context, bufSize))
4831 {
4832 return false;
4833 }
4834
4835 if (!ValidateGetShaderivBase(context, shader, pname, length))
4836 {
4837 return false;
4838 }
4839
4840 if (!ValidateRobustBufferSize(context, bufSize, *length))
4841 {
4842 return false;
4843 }
4844
4845 return true;
4846}
4847
Geoff Langc1984ed2016-10-07 12:41:00 -04004848bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4849{
4850 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4851}
4852
4853bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4854 GLenum target,
4855 GLenum pname,
4856 GLsizei bufSize,
4857 GLsizei *length,
4858 GLfloat *params)
4859{
4860 if (!ValidateRobustEntryPoint(context, bufSize))
4861 {
4862 return false;
4863 }
4864
4865 if (!ValidateGetTexParameterBase(context, target, pname, length))
4866 {
4867 return false;
4868 }
4869
4870 if (!ValidateRobustBufferSize(context, bufSize, *length))
4871 {
4872 return false;
4873 }
4874
4875 return true;
4876}
4877
4878bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4879{
4880 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4881}
4882
4883bool ValidateGetTexParameterivRobustANGLE(Context *context,
4884 GLenum target,
4885 GLenum pname,
4886 GLsizei bufSize,
4887 GLsizei *length,
4888 GLint *params)
4889{
4890 if (!ValidateRobustEntryPoint(context, bufSize))
4891 {
4892 return false;
4893 }
4894
4895 if (!ValidateGetTexParameterBase(context, target, pname, length))
4896 {
4897 return false;
4898 }
4899
4900 if (!ValidateRobustBufferSize(context, bufSize, *length))
4901 {
4902 return false;
4903 }
4904
4905 return true;
4906}
4907
4908bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4909{
4910 return ValidateTexParameterBase(context, target, pname, -1, &param);
4911}
4912
4913bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4914{
4915 return ValidateTexParameterBase(context, target, pname, -1, params);
4916}
4917
4918bool ValidateTexParameterfvRobustANGLE(Context *context,
4919 GLenum target,
4920 GLenum pname,
4921 GLsizei bufSize,
4922 const GLfloat *params)
4923{
4924 if (!ValidateRobustEntryPoint(context, bufSize))
4925 {
4926 return false;
4927 }
4928
4929 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4930}
4931
4932bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4933{
4934 return ValidateTexParameterBase(context, target, pname, -1, &param);
4935}
4936
4937bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4938{
4939 return ValidateTexParameterBase(context, target, pname, -1, params);
4940}
4941
4942bool ValidateTexParameterivRobustANGLE(Context *context,
4943 GLenum target,
4944 GLenum pname,
4945 GLsizei bufSize,
4946 const GLint *params)
4947{
4948 if (!ValidateRobustEntryPoint(context, bufSize))
4949 {
4950 return false;
4951 }
4952
4953 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4954}
4955
4956bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4957{
4958 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4959}
4960
4961bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4962 GLuint sampler,
4963 GLenum pname,
4964 GLuint bufSize,
4965 GLsizei *length,
4966 GLfloat *params)
4967{
4968 if (!ValidateRobustEntryPoint(context, bufSize))
4969 {
4970 return false;
4971 }
4972
4973 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4974 {
4975 return false;
4976 }
4977
4978 if (!ValidateRobustBufferSize(context, bufSize, *length))
4979 {
4980 return false;
4981 }
4982
4983 return true;
4984}
4985
4986bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4987{
4988 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4989}
4990
4991bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4992 GLuint sampler,
4993 GLenum pname,
4994 GLuint bufSize,
4995 GLsizei *length,
4996 GLint *params)
4997{
4998 if (!ValidateRobustEntryPoint(context, bufSize))
4999 {
5000 return false;
5001 }
5002
5003 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5004 {
5005 return false;
5006 }
5007
5008 if (!ValidateRobustBufferSize(context, bufSize, *length))
5009 {
5010 return false;
5011 }
5012
5013 return true;
5014}
5015
5016bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5017{
5018 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5019}
5020
5021bool ValidateSamplerParameterfv(Context *context,
5022 GLuint sampler,
5023 GLenum pname,
5024 const GLfloat *params)
5025{
5026 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5027}
5028
5029bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5030 GLuint sampler,
5031 GLenum pname,
5032 GLsizei bufSize,
5033 const GLfloat *params)
5034{
5035 if (!ValidateRobustEntryPoint(context, bufSize))
5036 {
5037 return false;
5038 }
5039
5040 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5041}
5042
5043bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5044{
5045 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5046}
5047
5048bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5049{
5050 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5051}
5052
5053bool ValidateSamplerParameterivRobustANGLE(Context *context,
5054 GLuint sampler,
5055 GLenum pname,
5056 GLsizei bufSize,
5057 const GLint *params)
5058{
5059 if (!ValidateRobustEntryPoint(context, bufSize))
5060 {
5061 return false;
5062 }
5063
5064 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5065}
5066
Geoff Lang0b031062016-10-13 14:30:04 -04005067bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5068{
5069 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5070}
5071
5072bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5073 GLuint index,
5074 GLenum pname,
5075 GLsizei bufSize,
5076 GLsizei *length,
5077 GLfloat *params)
5078{
5079 if (!ValidateRobustEntryPoint(context, bufSize))
5080 {
5081 return false;
5082 }
5083
5084 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5085 {
5086 return false;
5087 }
5088
5089 if (!ValidateRobustBufferSize(context, bufSize, *length))
5090 {
5091 return false;
5092 }
5093
5094 return true;
5095}
5096
5097bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5098{
5099 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5100}
5101
5102bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5103 GLuint index,
5104 GLenum pname,
5105 GLsizei bufSize,
5106 GLsizei *length,
5107 GLint *params)
5108{
5109 if (!ValidateRobustEntryPoint(context, bufSize))
5110 {
5111 return false;
5112 }
5113
5114 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5115 {
5116 return false;
5117 }
5118
5119 if (!ValidateRobustBufferSize(context, bufSize, *length))
5120 {
5121 return false;
5122 }
5123
5124 return true;
5125}
5126
5127bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5128{
5129 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5130}
5131
5132bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5133 GLuint index,
5134 GLenum pname,
5135 GLsizei bufSize,
5136 GLsizei *length,
5137 void **pointer)
5138{
5139 if (!ValidateRobustEntryPoint(context, bufSize))
5140 {
5141 return false;
5142 }
5143
5144 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5145 {
5146 return false;
5147 }
5148
5149 if (!ValidateRobustBufferSize(context, bufSize, *length))
5150 {
5151 return false;
5152 }
5153
5154 return true;
5155}
5156
5157bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5158{
5159 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5160}
5161
5162bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5163 GLuint index,
5164 GLenum pname,
5165 GLsizei bufSize,
5166 GLsizei *length,
5167 GLint *params)
5168{
5169 if (!ValidateRobustEntryPoint(context, bufSize))
5170 {
5171 return false;
5172 }
5173
5174 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5175 {
5176 return false;
5177 }
5178
5179 if (!ValidateRobustBufferSize(context, bufSize, *length))
5180 {
5181 return false;
5182 }
5183
5184 return true;
5185}
5186
5187bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5188{
5189 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5190}
5191
5192bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5193 GLuint index,
5194 GLenum pname,
5195 GLsizei bufSize,
5196 GLsizei *length,
5197 GLuint *params)
5198{
5199 if (!ValidateRobustEntryPoint(context, bufSize))
5200 {
5201 return false;
5202 }
5203
5204 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5205 {
5206 return false;
5207 }
5208
5209 if (!ValidateRobustBufferSize(context, bufSize, *length))
5210 {
5211 return false;
5212 }
5213
5214 return true;
5215}
5216
Geoff Lang6899b872016-10-14 11:30:13 -04005217bool ValidateGetActiveUniformBlockiv(Context *context,
5218 GLuint program,
5219 GLuint uniformBlockIndex,
5220 GLenum pname,
5221 GLint *params)
5222{
5223 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5224}
5225
5226bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5227 GLuint program,
5228 GLuint uniformBlockIndex,
5229 GLenum pname,
5230 GLsizei bufSize,
5231 GLsizei *length,
5232 GLint *params)
5233{
5234 if (!ValidateRobustEntryPoint(context, bufSize))
5235 {
5236 return false;
5237 }
5238
5239 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5240 {
5241 return false;
5242 }
5243
5244 if (!ValidateRobustBufferSize(context, bufSize, *length))
5245 {
5246 return false;
5247 }
5248
5249 return true;
5250}
5251
Geoff Lang0a9661f2016-10-20 10:59:20 -07005252bool ValidateGetInternalFormativ(Context *context,
5253 GLenum target,
5254 GLenum internalformat,
5255 GLenum pname,
5256 GLsizei bufSize,
5257 GLint *params)
5258{
5259 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5260 nullptr);
5261}
5262
5263bool ValidateGetInternalFormativRobustANGLE(Context *context,
5264 GLenum target,
5265 GLenum internalformat,
5266 GLenum pname,
5267 GLsizei bufSize,
5268 GLsizei *length,
5269 GLint *params)
5270{
5271 if (!ValidateRobustEntryPoint(context, bufSize))
5272 {
5273 return false;
5274 }
5275
5276 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5277 {
5278 return false;
5279 }
5280
5281 if (!ValidateRobustBufferSize(context, bufSize, *length))
5282 {
5283 return false;
5284 }
5285
5286 return true;
5287}
5288
Jamie Madillc29968b2016-01-20 11:17:23 -05005289} // namespace gl