blob: eae0c35ce5285a6efc088264f7a76ab2ffb2a836 [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
4243 if (!context->getExtensions().textureNPOT &&
4244 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4245 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4246 {
Martin Radev1be913c2016-07-11 17:59:16 +03004247 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004248 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
4249 context->handleError(Error(GL_INVALID_OPERATION));
4250 return false;
4251 }
4252
4253 // Cube completeness check
4254 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4255 {
4256 context->handleError(Error(GL_INVALID_OPERATION));
4257 return false;
4258 }
4259
4260 return true;
4261}
4262
Olli Etuaho41997e72016-03-10 13:38:39 +02004263bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4264{
4265 return ValidateGenOrDelete(context, n);
4266}
4267
4268bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4269{
4270 return ValidateGenOrDelete(context, n);
4271}
4272
4273bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4274{
4275 return ValidateGenOrDelete(context, n);
4276}
4277
4278bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4279{
4280 return ValidateGenOrDelete(context, n);
4281}
4282
4283bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4284{
4285 return ValidateGenOrDelete(context, n);
4286}
4287
4288bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4289{
4290 return ValidateGenOrDelete(context, n);
4291}
4292
4293bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4294{
4295 return ValidateGenOrDelete(context, n);
4296}
4297
4298bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4299{
4300 return ValidateGenOrDelete(context, n);
4301}
4302
4303bool ValidateGenOrDelete(Context *context, GLint n)
4304{
4305 if (n < 0)
4306 {
Jamie Madill437fa652016-05-03 15:13:24 -04004307 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004308 return false;
4309 }
4310 return true;
4311}
4312
Geoff Langf41a7152016-09-19 15:11:17 -04004313bool ValidateEnable(Context *context, GLenum cap)
4314{
4315 if (!ValidCap(context, cap, false))
4316 {
4317 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4318 return false;
4319 }
4320
4321 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4322 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4323 {
4324 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4325 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4326
4327 // We also output an error message to the debugger window if tracing is active, so that
4328 // developers can see the error message.
4329 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004330 return false;
4331 }
4332
4333 return true;
4334}
4335
4336bool ValidateDisable(Context *context, GLenum cap)
4337{
4338 if (!ValidCap(context, cap, false))
4339 {
4340 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4341 return false;
4342 }
4343
4344 return true;
4345}
4346
4347bool ValidateIsEnabled(Context *context, GLenum cap)
4348{
4349 if (!ValidCap(context, cap, true))
4350 {
4351 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4352 return false;
4353 }
4354
4355 return true;
4356}
4357
Geoff Langff5b2d52016-09-07 11:32:23 -04004358bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4359{
4360 if (!context->getExtensions().robustClientMemory)
4361 {
4362 context->handleError(
4363 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4364 return false;
4365 }
4366
4367 if (bufSize < 0)
4368 {
4369 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4370 return false;
4371 }
4372
4373 return true;
4374}
4375
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004376bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4377{
4378 if (bufSize < numParams)
4379 {
4380 context->handleError(Error(GL_INVALID_OPERATION,
4381 "%u parameters are required but %i were provided.", numParams,
4382 bufSize));
4383 return false;
4384 }
4385
4386 return true;
4387}
4388
Geoff Langff5b2d52016-09-07 11:32:23 -04004389bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4390 GLenum target,
4391 GLenum attachment,
4392 GLenum pname,
4393 GLsizei *numParams)
4394{
4395 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4396 *numParams = 1;
4397
4398 if (!ValidFramebufferTarget(target))
4399 {
4400 context->handleError(Error(GL_INVALID_ENUM));
4401 return false;
4402 }
4403
4404 int clientVersion = context->getClientMajorVersion();
4405
4406 switch (pname)
4407 {
4408 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4409 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4410 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4411 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4412 break;
4413
4414 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4415 if (clientVersion < 3 && !context->getExtensions().sRGB)
4416 {
4417 context->handleError(Error(GL_INVALID_ENUM));
4418 return false;
4419 }
4420 break;
4421
4422 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4423 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4424 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4425 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4426 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4427 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4428 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4429 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4430 if (clientVersion < 3)
4431 {
4432 context->handleError(Error(GL_INVALID_ENUM));
4433 return false;
4434 }
4435 break;
4436
4437 default:
4438 context->handleError(Error(GL_INVALID_ENUM));
4439 return false;
4440 }
4441
4442 // Determine if the attachment is a valid enum
4443 switch (attachment)
4444 {
4445 case GL_BACK:
4446 case GL_FRONT:
4447 case GL_DEPTH:
4448 case GL_STENCIL:
4449 case GL_DEPTH_STENCIL_ATTACHMENT:
4450 if (clientVersion < 3)
4451 {
4452 context->handleError(Error(GL_INVALID_ENUM));
4453 return false;
4454 }
4455 break;
4456
4457 case GL_DEPTH_ATTACHMENT:
4458 case GL_STENCIL_ATTACHMENT:
4459 break;
4460
4461 default:
4462 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4463 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4464 {
4465 context->handleError(Error(GL_INVALID_ENUM));
4466 return false;
4467 }
4468 break;
4469 }
4470
4471 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4472 ASSERT(framebuffer);
4473
4474 if (framebuffer->id() == 0)
4475 {
4476 if (clientVersion < 3)
4477 {
4478 context->handleError(Error(GL_INVALID_OPERATION));
4479 return false;
4480 }
4481
4482 switch (attachment)
4483 {
4484 case GL_BACK:
4485 case GL_DEPTH:
4486 case GL_STENCIL:
4487 break;
4488
4489 default:
4490 context->handleError(Error(GL_INVALID_OPERATION));
4491 return false;
4492 }
4493 }
4494 else
4495 {
4496 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4497 {
4498 // Valid attachment query
4499 }
4500 else
4501 {
4502 switch (attachment)
4503 {
4504 case GL_DEPTH_ATTACHMENT:
4505 case GL_STENCIL_ATTACHMENT:
4506 break;
4507
4508 case GL_DEPTH_STENCIL_ATTACHMENT:
4509 if (!framebuffer->hasValidDepthStencil())
4510 {
4511 context->handleError(Error(GL_INVALID_OPERATION));
4512 return false;
4513 }
4514 break;
4515
4516 default:
4517 context->handleError(Error(GL_INVALID_OPERATION));
4518 return false;
4519 }
4520 }
4521 }
4522
4523 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4524 if (attachmentObject)
4525 {
4526 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4527 attachmentObject->type() == GL_TEXTURE ||
4528 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4529
4530 switch (pname)
4531 {
4532 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4533 if (attachmentObject->type() != GL_RENDERBUFFER &&
4534 attachmentObject->type() != GL_TEXTURE)
4535 {
4536 context->handleError(Error(GL_INVALID_ENUM));
4537 return false;
4538 }
4539 break;
4540
4541 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4542 if (attachmentObject->type() != GL_TEXTURE)
4543 {
4544 context->handleError(Error(GL_INVALID_ENUM));
4545 return false;
4546 }
4547 break;
4548
4549 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4550 if (attachmentObject->type() != GL_TEXTURE)
4551 {
4552 context->handleError(Error(GL_INVALID_ENUM));
4553 return false;
4554 }
4555 break;
4556
4557 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4558 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4559 {
4560 context->handleError(Error(GL_INVALID_OPERATION));
4561 return false;
4562 }
4563 break;
4564
4565 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4566 if (attachmentObject->type() != GL_TEXTURE)
4567 {
4568 context->handleError(Error(GL_INVALID_ENUM));
4569 return false;
4570 }
4571 break;
4572
4573 default:
4574 break;
4575 }
4576 }
4577 else
4578 {
4579 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4580 // is NONE, then querying any other pname will generate INVALID_ENUM.
4581
4582 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4583 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4584 // INVALID_OPERATION for all other pnames
4585
4586 switch (pname)
4587 {
4588 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4589 break;
4590
4591 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4592 if (clientVersion < 3)
4593 {
4594 context->handleError(Error(GL_INVALID_ENUM));
4595 return false;
4596 }
4597 break;
4598
4599 default:
4600 if (clientVersion < 3)
4601 {
4602 context->handleError(Error(GL_INVALID_ENUM));
4603 return false;
4604 }
4605 else
4606 {
4607 context->handleError(Error(GL_INVALID_OPERATION));
4608 return false;
4609 }
4610 }
4611 }
4612
4613 return true;
4614}
4615
4616bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4617 GLenum target,
4618 GLenum attachment,
4619 GLenum pname,
4620 GLsizei bufSize,
4621 GLsizei *numParams)
4622{
4623 if (!ValidateRobustEntryPoint(context, bufSize))
4624 {
4625 return false;
4626 }
4627
4628 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4629 {
4630 return false;
4631 }
4632
4633 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4634 {
4635 return false;
4636 }
4637
4638 return true;
4639}
4640
4641bool ValidateGetBufferParameteriv(ValidationContext *context,
4642 GLenum target,
4643 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004644 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004645{
Geoff Langebebe1c2016-10-14 12:01:31 -04004646 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004647}
4648
4649bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4650 GLenum target,
4651 GLenum pname,
4652 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004653 GLsizei *length,
4654 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004655{
4656 if (!ValidateRobustEntryPoint(context, bufSize))
4657 {
4658 return false;
4659 }
4660
Geoff Langebebe1c2016-10-14 12:01:31 -04004661 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004662 {
4663 return false;
4664 }
4665
Geoff Langebebe1c2016-10-14 12:01:31 -04004666 if (!ValidateRobustBufferSize(context, bufSize, *length))
4667 {
4668 return false;
4669 }
4670
4671 return true;
4672}
4673
4674bool ValidateGetBufferParameteri64v(ValidationContext *context,
4675 GLenum target,
4676 GLenum pname,
4677 GLint64 *params)
4678{
4679 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4680}
4681
4682bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4683 GLenum target,
4684 GLenum pname,
4685 GLsizei bufSize,
4686 GLsizei *length,
4687 GLint64 *params)
4688{
4689 if (!ValidateRobustEntryPoint(context, bufSize))
4690 {
4691 return false;
4692 }
4693
4694 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4695 {
4696 return false;
4697 }
4698
4699 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004700 {
4701 return false;
4702 }
4703
4704 return true;
4705}
4706
4707bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4708{
4709 // Currently, all GetProgramiv queries return 1 parameter
4710 *numParams = 1;
4711
4712 Program *programObject = GetValidProgram(context, program);
4713 if (!programObject)
4714 {
4715 return false;
4716 }
4717
4718 switch (pname)
4719 {
4720 case GL_DELETE_STATUS:
4721 case GL_LINK_STATUS:
4722 case GL_VALIDATE_STATUS:
4723 case GL_INFO_LOG_LENGTH:
4724 case GL_ATTACHED_SHADERS:
4725 case GL_ACTIVE_ATTRIBUTES:
4726 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4727 case GL_ACTIVE_UNIFORMS:
4728 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4729 break;
4730
4731 case GL_PROGRAM_BINARY_LENGTH:
4732 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4733 {
4734 context->handleError(Error(GL_INVALID_ENUM,
4735 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4736 "GL_OES_get_program_binary or ES 3.0."));
4737 return false;
4738 }
4739 break;
4740
4741 case GL_ACTIVE_UNIFORM_BLOCKS:
4742 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4743 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4744 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4745 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4746 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4747 if (context->getClientMajorVersion() < 3)
4748 {
4749 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4750 return false;
4751 }
4752 break;
4753
4754 default:
4755 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4756 return false;
4757 }
4758
4759 return true;
4760}
4761
4762bool ValidateGetProgramivRobustANGLE(Context *context,
4763 GLuint program,
4764 GLenum pname,
4765 GLsizei bufSize,
4766 GLsizei *numParams)
4767{
4768 if (!ValidateRobustEntryPoint(context, bufSize))
4769 {
4770 return false;
4771 }
4772
4773 if (!ValidateGetProgramiv(context, program, pname, numParams))
4774 {
4775 return false;
4776 }
4777
4778 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4779 {
4780 return false;
4781 }
4782
4783 return true;
4784}
4785
Geoff Lang740d9022016-10-07 11:20:52 -04004786bool ValidateGetRenderbufferParameteriv(Context *context,
4787 GLenum target,
4788 GLenum pname,
4789 GLint *params)
4790{
4791 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4792}
4793
4794bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4795 GLenum target,
4796 GLenum pname,
4797 GLsizei bufSize,
4798 GLsizei *length,
4799 GLint *params)
4800{
4801 if (!ValidateRobustEntryPoint(context, bufSize))
4802 {
4803 return false;
4804 }
4805
4806 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4807 {
4808 return false;
4809 }
4810
4811 if (!ValidateRobustBufferSize(context, bufSize, *length))
4812 {
4813 return false;
4814 }
4815
4816 return true;
4817}
4818
Geoff Langd7d0ed32016-10-07 11:33:51 -04004819bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4820{
4821 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4822}
4823
4824bool ValidateGetShaderivRobustANGLE(Context *context,
4825 GLuint shader,
4826 GLenum pname,
4827 GLsizei bufSize,
4828 GLsizei *length,
4829 GLint *params)
4830{
4831 if (!ValidateRobustEntryPoint(context, bufSize))
4832 {
4833 return false;
4834 }
4835
4836 if (!ValidateGetShaderivBase(context, shader, pname, length))
4837 {
4838 return false;
4839 }
4840
4841 if (!ValidateRobustBufferSize(context, bufSize, *length))
4842 {
4843 return false;
4844 }
4845
4846 return true;
4847}
4848
Geoff Langc1984ed2016-10-07 12:41:00 -04004849bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4850{
4851 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4852}
4853
4854bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4855 GLenum target,
4856 GLenum pname,
4857 GLsizei bufSize,
4858 GLsizei *length,
4859 GLfloat *params)
4860{
4861 if (!ValidateRobustEntryPoint(context, bufSize))
4862 {
4863 return false;
4864 }
4865
4866 if (!ValidateGetTexParameterBase(context, target, pname, length))
4867 {
4868 return false;
4869 }
4870
4871 if (!ValidateRobustBufferSize(context, bufSize, *length))
4872 {
4873 return false;
4874 }
4875
4876 return true;
4877}
4878
4879bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4880{
4881 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4882}
4883
4884bool ValidateGetTexParameterivRobustANGLE(Context *context,
4885 GLenum target,
4886 GLenum pname,
4887 GLsizei bufSize,
4888 GLsizei *length,
4889 GLint *params)
4890{
4891 if (!ValidateRobustEntryPoint(context, bufSize))
4892 {
4893 return false;
4894 }
4895
4896 if (!ValidateGetTexParameterBase(context, target, pname, length))
4897 {
4898 return false;
4899 }
4900
4901 if (!ValidateRobustBufferSize(context, bufSize, *length))
4902 {
4903 return false;
4904 }
4905
4906 return true;
4907}
4908
4909bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4910{
4911 return ValidateTexParameterBase(context, target, pname, -1, &param);
4912}
4913
4914bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4915{
4916 return ValidateTexParameterBase(context, target, pname, -1, params);
4917}
4918
4919bool ValidateTexParameterfvRobustANGLE(Context *context,
4920 GLenum target,
4921 GLenum pname,
4922 GLsizei bufSize,
4923 const GLfloat *params)
4924{
4925 if (!ValidateRobustEntryPoint(context, bufSize))
4926 {
4927 return false;
4928 }
4929
4930 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4931}
4932
4933bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4934{
4935 return ValidateTexParameterBase(context, target, pname, -1, &param);
4936}
4937
4938bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4939{
4940 return ValidateTexParameterBase(context, target, pname, -1, params);
4941}
4942
4943bool ValidateTexParameterivRobustANGLE(Context *context,
4944 GLenum target,
4945 GLenum pname,
4946 GLsizei bufSize,
4947 const GLint *params)
4948{
4949 if (!ValidateRobustEntryPoint(context, bufSize))
4950 {
4951 return false;
4952 }
4953
4954 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4955}
4956
4957bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4958{
4959 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4960}
4961
4962bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4963 GLuint sampler,
4964 GLenum pname,
4965 GLuint bufSize,
4966 GLsizei *length,
4967 GLfloat *params)
4968{
4969 if (!ValidateRobustEntryPoint(context, bufSize))
4970 {
4971 return false;
4972 }
4973
4974 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4975 {
4976 return false;
4977 }
4978
4979 if (!ValidateRobustBufferSize(context, bufSize, *length))
4980 {
4981 return false;
4982 }
4983
4984 return true;
4985}
4986
4987bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4988{
4989 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4990}
4991
4992bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4993 GLuint sampler,
4994 GLenum pname,
4995 GLuint bufSize,
4996 GLsizei *length,
4997 GLint *params)
4998{
4999 if (!ValidateRobustEntryPoint(context, bufSize))
5000 {
5001 return false;
5002 }
5003
5004 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5005 {
5006 return false;
5007 }
5008
5009 if (!ValidateRobustBufferSize(context, bufSize, *length))
5010 {
5011 return false;
5012 }
5013
5014 return true;
5015}
5016
5017bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5018{
5019 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5020}
5021
5022bool ValidateSamplerParameterfv(Context *context,
5023 GLuint sampler,
5024 GLenum pname,
5025 const GLfloat *params)
5026{
5027 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5028}
5029
5030bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5031 GLuint sampler,
5032 GLenum pname,
5033 GLsizei bufSize,
5034 const GLfloat *params)
5035{
5036 if (!ValidateRobustEntryPoint(context, bufSize))
5037 {
5038 return false;
5039 }
5040
5041 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5042}
5043
5044bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5045{
5046 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5047}
5048
5049bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5050{
5051 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5052}
5053
5054bool ValidateSamplerParameterivRobustANGLE(Context *context,
5055 GLuint sampler,
5056 GLenum pname,
5057 GLsizei bufSize,
5058 const GLint *params)
5059{
5060 if (!ValidateRobustEntryPoint(context, bufSize))
5061 {
5062 return false;
5063 }
5064
5065 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5066}
5067
Geoff Lang0b031062016-10-13 14:30:04 -04005068bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5069{
5070 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5071}
5072
5073bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5074 GLuint index,
5075 GLenum pname,
5076 GLsizei bufSize,
5077 GLsizei *length,
5078 GLfloat *params)
5079{
5080 if (!ValidateRobustEntryPoint(context, bufSize))
5081 {
5082 return false;
5083 }
5084
5085 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5086 {
5087 return false;
5088 }
5089
5090 if (!ValidateRobustBufferSize(context, bufSize, *length))
5091 {
5092 return false;
5093 }
5094
5095 return true;
5096}
5097
5098bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5099{
5100 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5101}
5102
5103bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5104 GLuint index,
5105 GLenum pname,
5106 GLsizei bufSize,
5107 GLsizei *length,
5108 GLint *params)
5109{
5110 if (!ValidateRobustEntryPoint(context, bufSize))
5111 {
5112 return false;
5113 }
5114
5115 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5116 {
5117 return false;
5118 }
5119
5120 if (!ValidateRobustBufferSize(context, bufSize, *length))
5121 {
5122 return false;
5123 }
5124
5125 return true;
5126}
5127
5128bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5129{
5130 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5131}
5132
5133bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5134 GLuint index,
5135 GLenum pname,
5136 GLsizei bufSize,
5137 GLsizei *length,
5138 void **pointer)
5139{
5140 if (!ValidateRobustEntryPoint(context, bufSize))
5141 {
5142 return false;
5143 }
5144
5145 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5146 {
5147 return false;
5148 }
5149
5150 if (!ValidateRobustBufferSize(context, bufSize, *length))
5151 {
5152 return false;
5153 }
5154
5155 return true;
5156}
5157
5158bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5159{
5160 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5161}
5162
5163bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5164 GLuint index,
5165 GLenum pname,
5166 GLsizei bufSize,
5167 GLsizei *length,
5168 GLint *params)
5169{
5170 if (!ValidateRobustEntryPoint(context, bufSize))
5171 {
5172 return false;
5173 }
5174
5175 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5176 {
5177 return false;
5178 }
5179
5180 if (!ValidateRobustBufferSize(context, bufSize, *length))
5181 {
5182 return false;
5183 }
5184
5185 return true;
5186}
5187
5188bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5189{
5190 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5191}
5192
5193bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5194 GLuint index,
5195 GLenum pname,
5196 GLsizei bufSize,
5197 GLsizei *length,
5198 GLuint *params)
5199{
5200 if (!ValidateRobustEntryPoint(context, bufSize))
5201 {
5202 return false;
5203 }
5204
5205 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5206 {
5207 return false;
5208 }
5209
5210 if (!ValidateRobustBufferSize(context, bufSize, *length))
5211 {
5212 return false;
5213 }
5214
5215 return true;
5216}
5217
Geoff Lang6899b872016-10-14 11:30:13 -04005218bool ValidateGetActiveUniformBlockiv(Context *context,
5219 GLuint program,
5220 GLuint uniformBlockIndex,
5221 GLenum pname,
5222 GLint *params)
5223{
5224 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5225}
5226
5227bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5228 GLuint program,
5229 GLuint uniformBlockIndex,
5230 GLenum pname,
5231 GLsizei bufSize,
5232 GLsizei *length,
5233 GLint *params)
5234{
5235 if (!ValidateRobustEntryPoint(context, bufSize))
5236 {
5237 return false;
5238 }
5239
5240 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5241 {
5242 return false;
5243 }
5244
5245 if (!ValidateRobustBufferSize(context, bufSize, *length))
5246 {
5247 return false;
5248 }
5249
5250 return true;
5251}
5252
Geoff Lang0a9661f2016-10-20 10:59:20 -07005253bool ValidateGetInternalFormativ(Context *context,
5254 GLenum target,
5255 GLenum internalformat,
5256 GLenum pname,
5257 GLsizei bufSize,
5258 GLint *params)
5259{
5260 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5261 nullptr);
5262}
5263
5264bool ValidateGetInternalFormativRobustANGLE(Context *context,
5265 GLenum target,
5266 GLenum internalformat,
5267 GLenum pname,
5268 GLsizei bufSize,
5269 GLsizei *length,
5270 GLint *params)
5271{
5272 if (!ValidateRobustEntryPoint(context, bufSize))
5273 {
5274 return false;
5275 }
5276
5277 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5278 {
5279 return false;
5280 }
5281
5282 if (!ValidateRobustBufferSize(context, bufSize, *length))
5283 {
5284 return false;
5285 }
5286
5287 return true;
5288}
5289
Jamie Madillc29968b2016-01-20 11:17:23 -05005290} // namespace gl