blob: 73f028fc5715a35ed513d0f724917159533219ba [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
He Yunchaoced53ae2016-11-29 15:00:51 +080042 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
44 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040045 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 {
He Yunchaoced53ae2016-11-29 15:00:51 +080054 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
Jamie Madill1ca74672015-07-21 15:14:11 -040055 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 Lang3b573612016-10-31 14:08:10 -0400168 case GL_SAMPLE_MASK:
169 UNIMPLEMENTED();
170 return context->getClientVersion() >= Version(3, 1);
171
Geoff Langf41a7152016-09-19 15:11:17 -0400172 default:
173 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500174 }
175}
176
Geoff Lang62fce5b2016-09-30 10:46:35 -0400177bool ValidateReadPixelsBase(ValidationContext *context,
178 GLint x,
179 GLint y,
180 GLsizei width,
181 GLsizei height,
182 GLenum format,
183 GLenum type,
184 GLsizei bufSize,
185 GLsizei *length,
186 GLvoid *pixels)
187{
188 if (length != nullptr)
189 {
190 *length = 0;
191 }
192
193 if (width < 0 || height < 0)
194 {
195 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
196 return false;
197 }
198
199 auto readFramebuffer = context->getGLState().getReadFramebuffer();
200
201 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
202 {
203 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
204 return false;
205 }
206
207 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
208 {
209 context->handleError(Error(GL_INVALID_OPERATION));
210 return false;
211 }
212
213 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
214 ASSERT(framebuffer);
215
216 if (framebuffer->getReadBufferState() == GL_NONE)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
219 return false;
220 }
221
222 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
223 if (!readBuffer)
224 {
225 context->handleError(Error(GL_INVALID_OPERATION));
226 return false;
227 }
228
229 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
230 GLenum currentType = framebuffer->getImplementationColorReadType();
231 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
232
233 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
234 bool validFormatTypeCombination =
235 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
236
237 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
238 {
239 context->handleError(Error(GL_INVALID_OPERATION));
240 return false;
241 }
242
243 // Check for pixel pack buffer related API errors
244 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
245 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
246 {
247 // ...the buffer object's data store is currently mapped.
248 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
249 return false;
250 }
251
252 // .. the data would be packed to the buffer object such that the memory writes required
253 // would exceed the data store size.
254 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
255 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
256 const gl::Extents size(width, height, 1);
257 const auto &pack = context->getGLState().getPackState();
258
259 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
260 if (endByteOrErr.isError())
261 {
262 context->handleError(endByteOrErr.getError());
263 return false;
264 }
265
266 size_t endByte = endByteOrErr.getResult();
267 if (bufSize >= 0)
268 {
269
270 if (static_cast<size_t>(bufSize) < endByte)
271 {
272 context->handleError(
273 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
274 return false;
275 }
276 }
277
278 if (pixelPackBuffer != nullptr)
279 {
280 CheckedNumeric<size_t> checkedEndByte(endByte);
281 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
282 checkedEndByte += checkedOffset;
283
284 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
285 {
286 // Overflow past the end of the buffer
287 context->handleError(
288 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
289 return false;
290 }
291 }
292
293 if (length != nullptr)
294 {
295 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
296 {
297 context->handleError(
298 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
299 return false;
300 }
301
302 *length = static_cast<GLsizei>(endByte);
303 }
304
305 return true;
306}
307
Geoff Lang740d9022016-10-07 11:20:52 -0400308bool ValidateGetRenderbufferParameterivBase(Context *context,
309 GLenum target,
310 GLenum pname,
311 GLsizei *length)
312{
313 if (length)
314 {
315 *length = 0;
316 }
317
318 if (target != GL_RENDERBUFFER)
319 {
320 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
321 return false;
322 }
323
324 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
325 if (renderbuffer == nullptr)
326 {
327 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
328 return false;
329 }
330
331 switch (pname)
332 {
333 case GL_RENDERBUFFER_WIDTH:
334 case GL_RENDERBUFFER_HEIGHT:
335 case GL_RENDERBUFFER_INTERNAL_FORMAT:
336 case GL_RENDERBUFFER_RED_SIZE:
337 case GL_RENDERBUFFER_GREEN_SIZE:
338 case GL_RENDERBUFFER_BLUE_SIZE:
339 case GL_RENDERBUFFER_ALPHA_SIZE:
340 case GL_RENDERBUFFER_DEPTH_SIZE:
341 case GL_RENDERBUFFER_STENCIL_SIZE:
342 break;
343
344 case GL_RENDERBUFFER_SAMPLES_ANGLE:
345 if (!context->getExtensions().framebufferMultisample)
346 {
347 context->handleError(
348 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
349 return false;
350 }
351 break;
352
353 default:
354 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
355 return false;
356 }
357
358 if (length)
359 {
360 *length = 1;
361 }
362 return true;
363}
364
Geoff Langd7d0ed32016-10-07 11:33:51 -0400365bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
366{
367 if (length)
368 {
369 *length = 0;
370 }
371
372 if (GetValidShader(context, shader) == nullptr)
373 {
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_SHADER_TYPE:
380 case GL_DELETE_STATUS:
381 case GL_COMPILE_STATUS:
382 case GL_INFO_LOG_LENGTH:
383 case GL_SHADER_SOURCE_LENGTH:
384 break;
385
386 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
387 if (!context->getExtensions().translatedShaderSource)
388 {
389 context->handleError(
390 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
391 return false;
392 }
393 break;
394
395 default:
396 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
397 return false;
398 }
399
400 if (length)
401 {
402 *length = 1;
403 }
404 return true;
405}
406
Geoff Langc1984ed2016-10-07 12:41:00 -0400407bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
408{
409 if (length)
410 {
411 *length = 0;
412 }
413
414 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
415 {
416 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
417 return false;
418 }
419
420 if (context->getTargetTexture(target) == nullptr)
421 {
422 // Should only be possible for external textures
423 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
424 return false;
425 }
426
427 switch (pname)
428 {
429 case GL_TEXTURE_MAG_FILTER:
430 case GL_TEXTURE_MIN_FILTER:
431 case GL_TEXTURE_WRAP_S:
432 case GL_TEXTURE_WRAP_T:
433 break;
434
435 case GL_TEXTURE_USAGE_ANGLE:
436 if (!context->getExtensions().textureUsage)
437 {
438 context->handleError(
439 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
445 if (!context->getExtensions().textureFilterAnisotropic)
446 {
447 context->handleError(
448 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
449 return false;
450 }
451 break;
452
453 case GL_TEXTURE_IMMUTABLE_FORMAT:
454 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
455 {
456 context->handleError(
457 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
458 return false;
459 }
460 break;
461
462 case GL_TEXTURE_WRAP_R:
463 case GL_TEXTURE_IMMUTABLE_LEVELS:
464 case GL_TEXTURE_SWIZZLE_R:
465 case GL_TEXTURE_SWIZZLE_G:
466 case GL_TEXTURE_SWIZZLE_B:
467 case GL_TEXTURE_SWIZZLE_A:
468 case GL_TEXTURE_BASE_LEVEL:
469 case GL_TEXTURE_MAX_LEVEL:
470 case GL_TEXTURE_MIN_LOD:
471 case GL_TEXTURE_MAX_LOD:
472 case GL_TEXTURE_COMPARE_MODE:
473 case GL_TEXTURE_COMPARE_FUNC:
474 if (context->getClientMajorVersion() < 3)
475 {
476 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
477 return false;
478 }
479 break;
480
Geoff Lang81c6b572016-10-19 14:07:52 -0700481 case GL_TEXTURE_SRGB_DECODE_EXT:
482 if (!context->getExtensions().textureSRGBDecode)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
486 return false;
487 }
488 break;
489
Geoff Langc1984ed2016-10-07 12:41:00 -0400490 default:
491 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
492 return false;
493 }
494
495 if (length)
496 {
497 *length = 1;
498 }
499 return true;
500}
501
502template <typename ParamType>
503bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
504{
505 switch (ConvertToGLenum(params[0]))
506 {
507 case GL_CLAMP_TO_EDGE:
508 break;
509
510 case GL_REPEAT:
511 case GL_MIRRORED_REPEAT:
512 if (isExternalTextureTarget)
513 {
514 // OES_EGL_image_external specifies this error.
515 context->handleError(Error(
516 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
517 return false;
518 }
519 break;
520
521 default:
522 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
523 return false;
524 }
525
526 return true;
527}
528
529template <typename ParamType>
530bool ValidateTextureMinFilterValue(Context *context,
531 ParamType *params,
532 bool isExternalTextureTarget)
533{
534 switch (ConvertToGLenum(params[0]))
535 {
536 case GL_NEAREST:
537 case GL_LINEAR:
538 break;
539
540 case GL_NEAREST_MIPMAP_NEAREST:
541 case GL_LINEAR_MIPMAP_NEAREST:
542 case GL_NEAREST_MIPMAP_LINEAR:
543 case GL_LINEAR_MIPMAP_LINEAR:
544 if (isExternalTextureTarget)
545 {
546 // OES_EGL_image_external specifies this error.
547 context->handleError(
548 Error(GL_INVALID_ENUM,
549 "external textures only support NEAREST and LINEAR filtering"));
550 return false;
551 }
552 break;
553
554 default:
555 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
556 return false;
557 }
558
559 return true;
560}
561
562template <typename ParamType>
563bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
564{
565 switch (ConvertToGLenum(params[0]))
566 {
567 case GL_NEAREST:
568 case GL_LINEAR:
569 break;
570
571 default:
572 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
573 return false;
574 }
575
576 return true;
577}
578
579template <typename ParamType>
580bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
581{
582 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
583 switch (ConvertToGLenum(params[0]))
584 {
585 case GL_NONE:
586 case GL_COMPARE_REF_TO_TEXTURE:
587 break;
588
589 default:
590 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
591 return false;
592 }
593
594 return true;
595}
596
597template <typename ParamType>
598bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
599{
600 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
601 switch (ConvertToGLenum(params[0]))
602 {
603 case GL_LEQUAL:
604 case GL_GEQUAL:
605 case GL_LESS:
606 case GL_GREATER:
607 case GL_EQUAL:
608 case GL_NOTEQUAL:
609 case GL_ALWAYS:
610 case GL_NEVER:
611 break;
612
613 default:
614 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
615 return false;
616 }
617
618 return true;
619}
620
621template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700622bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
623{
624 if (!context->getExtensions().textureSRGBDecode)
625 {
626 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
627 return false;
628 }
629
630 switch (ConvertToGLenum(params[0]))
631 {
632 case GL_DECODE_EXT:
633 case GL_SKIP_DECODE_EXT:
634 break;
635
636 default:
637 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
638 return false;
639 }
640
641 return true;
642}
643
644template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400645bool ValidateTexParameterBase(Context *context,
646 GLenum target,
647 GLenum pname,
648 GLsizei bufSize,
649 ParamType *params)
650{
651 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
652 {
653 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
654 return false;
655 }
656
657 if (context->getTargetTexture(target) == nullptr)
658 {
659 // Should only be possible for external textures
660 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
661 return false;
662 }
663
664 const GLsizei minBufSize = 1;
665 if (bufSize >= 0 && bufSize < minBufSize)
666 {
667 context->handleError(
668 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
669 return false;
670 }
671
672 switch (pname)
673 {
674 case GL_TEXTURE_WRAP_R:
675 case GL_TEXTURE_SWIZZLE_R:
676 case GL_TEXTURE_SWIZZLE_G:
677 case GL_TEXTURE_SWIZZLE_B:
678 case GL_TEXTURE_SWIZZLE_A:
679 case GL_TEXTURE_BASE_LEVEL:
680 case GL_TEXTURE_MAX_LEVEL:
681 case GL_TEXTURE_COMPARE_MODE:
682 case GL_TEXTURE_COMPARE_FUNC:
683 case GL_TEXTURE_MIN_LOD:
684 case GL_TEXTURE_MAX_LOD:
685 if (context->getClientMajorVersion() < 3)
686 {
687 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
688 return false;
689 }
690 if (target == GL_TEXTURE_EXTERNAL_OES &&
691 !context->getExtensions().eglImageExternalEssl3)
692 {
693 context->handleError(Error(GL_INVALID_ENUM,
694 "ES3 texture parameters are not available without "
695 "GL_OES_EGL_image_external_essl3."));
696 return false;
697 }
698 break;
699
700 default:
701 break;
702 }
703
704 switch (pname)
705 {
706 case GL_TEXTURE_WRAP_S:
707 case GL_TEXTURE_WRAP_T:
708 case GL_TEXTURE_WRAP_R:
709 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
710 {
711 return false;
712 }
713 break;
714
715 case GL_TEXTURE_MIN_FILTER:
716 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
717 {
718 return false;
719 }
720 break;
721
722 case GL_TEXTURE_MAG_FILTER:
723 if (!ValidateTextureMagFilterValue(context, params))
724 {
725 return false;
726 }
727 break;
728
729 case GL_TEXTURE_USAGE_ANGLE:
730 switch (ConvertToGLenum(params[0]))
731 {
732 case GL_NONE:
733 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
734 break;
735
736 default:
737 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
738 return false;
739 }
740 break;
741
742 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
743 if (!context->getExtensions().textureFilterAnisotropic)
744 {
745 context->handleError(
746 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
747 return false;
748 }
749
750 // we assume the parameter passed to this validation method is truncated, not rounded
751 if (params[0] < 1)
752 {
753 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
754 return false;
755 }
756 break;
757
758 case GL_TEXTURE_MIN_LOD:
759 case GL_TEXTURE_MAX_LOD:
760 // any value is permissible
761 break;
762
763 case GL_TEXTURE_COMPARE_MODE:
764 if (!ValidateTextureCompareModeValue(context, params))
765 {
766 return false;
767 }
768 break;
769
770 case GL_TEXTURE_COMPARE_FUNC:
771 if (!ValidateTextureCompareFuncValue(context, params))
772 {
773 return false;
774 }
775 break;
776
777 case GL_TEXTURE_SWIZZLE_R:
778 case GL_TEXTURE_SWIZZLE_G:
779 case GL_TEXTURE_SWIZZLE_B:
780 case GL_TEXTURE_SWIZZLE_A:
781 switch (ConvertToGLenum(params[0]))
782 {
783 case GL_RED:
784 case GL_GREEN:
785 case GL_BLUE:
786 case GL_ALPHA:
787 case GL_ZERO:
788 case GL_ONE:
789 break;
790
791 default:
792 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
793 return false;
794 }
795 break;
796
797 case GL_TEXTURE_BASE_LEVEL:
798 if (params[0] < 0)
799 {
800 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
801 return false;
802 }
803 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
804 {
805 context->handleError(
806 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
807 return false;
808 }
809 break;
810
811 case GL_TEXTURE_MAX_LEVEL:
812 if (params[0] < 0)
813 {
814 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
815 return false;
816 }
817 break;
818
Geoff Lang3b573612016-10-31 14:08:10 -0400819 case GL_DEPTH_STENCIL_TEXTURE_MODE:
820 if (context->getClientVersion() < Version(3, 1))
821 {
822 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
823 return false;
824 }
825 UNIMPLEMENTED();
826 break;
827
Geoff Lang81c6b572016-10-19 14:07:52 -0700828 case GL_TEXTURE_SRGB_DECODE_EXT:
829 if (!ValidateTextureSRGBDecodeValue(context, params))
830 {
831 return false;
832 }
833 break;
834
Geoff Langc1984ed2016-10-07 12:41:00 -0400835 default:
836 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
837 return false;
838 }
839
840 return true;
841}
842
843template <typename ParamType>
844bool ValidateSamplerParameterBase(Context *context,
845 GLuint sampler,
846 GLenum pname,
847 GLsizei bufSize,
848 ParamType *params)
849{
850 if (context->getClientMajorVersion() < 3)
851 {
852 context->handleError(
853 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
854 return false;
855 }
856
857 if (!context->isSampler(sampler))
858 {
859 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
860 return false;
861 }
862
863 const GLsizei minBufSize = 1;
864 if (bufSize >= 0 && bufSize < minBufSize)
865 {
866 context->handleError(
867 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
868 return false;
869 }
870
871 switch (pname)
872 {
873 case GL_TEXTURE_WRAP_S:
874 case GL_TEXTURE_WRAP_T:
875 case GL_TEXTURE_WRAP_R:
876 if (!ValidateTextureWrapModeValue(context, params, false))
877 {
878 return false;
879 }
880 break;
881
882 case GL_TEXTURE_MIN_FILTER:
883 if (!ValidateTextureMinFilterValue(context, params, false))
884 {
885 return false;
886 }
887 break;
888
889 case GL_TEXTURE_MAG_FILTER:
890 if (!ValidateTextureMagFilterValue(context, params))
891 {
892 return false;
893 }
894 break;
895
896 case GL_TEXTURE_MIN_LOD:
897 case GL_TEXTURE_MAX_LOD:
898 // any value is permissible
899 break;
900
901 case GL_TEXTURE_COMPARE_MODE:
902 if (!ValidateTextureCompareModeValue(context, params))
903 {
904 return false;
905 }
906 break;
907
908 case GL_TEXTURE_COMPARE_FUNC:
909 if (!ValidateTextureCompareFuncValue(context, params))
910 {
911 return false;
912 }
913 break;
914
Geoff Lang81c6b572016-10-19 14:07:52 -0700915 case GL_TEXTURE_SRGB_DECODE_EXT:
916 if (!ValidateTextureSRGBDecodeValue(context, params))
917 {
918 return false;
919 }
920 break;
921
Geoff Langc1984ed2016-10-07 12:41:00 -0400922 default:
923 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
924 return false;
925 }
926
927 return true;
928}
929
930bool ValidateGetSamplerParameterBase(Context *context,
931 GLuint sampler,
932 GLenum pname,
933 GLsizei *length)
934{
935 if (length)
936 {
937 *length = 0;
938 }
939
940 if (context->getClientMajorVersion() < 3)
941 {
942 context->handleError(
943 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
944 return false;
945 }
946
947 if (!context->isSampler(sampler))
948 {
949 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
950 return false;
951 }
952
953 switch (pname)
954 {
955 case GL_TEXTURE_WRAP_S:
956 case GL_TEXTURE_WRAP_T:
957 case GL_TEXTURE_WRAP_R:
958 case GL_TEXTURE_MIN_FILTER:
959 case GL_TEXTURE_MAG_FILTER:
960 case GL_TEXTURE_MIN_LOD:
961 case GL_TEXTURE_MAX_LOD:
962 case GL_TEXTURE_COMPARE_MODE:
963 case GL_TEXTURE_COMPARE_FUNC:
964 break;
965
Geoff Lang81c6b572016-10-19 14:07:52 -0700966 case GL_TEXTURE_SRGB_DECODE_EXT:
967 if (!context->getExtensions().textureSRGBDecode)
968 {
969 context->handleError(
970 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
971 return false;
972 }
973 break;
974
Geoff Langc1984ed2016-10-07 12:41:00 -0400975 default:
976 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
977 return false;
978 }
979
980 if (length)
981 {
982 *length = 1;
983 }
984 return true;
985}
986
Geoff Lang0b031062016-10-13 14:30:04 -0400987bool ValidateGetVertexAttribBase(Context *context,
988 GLuint index,
989 GLenum pname,
990 GLsizei *length,
991 bool pointer,
992 bool pureIntegerEntryPoint)
993{
994 if (length)
995 {
996 *length = 0;
997 }
998
999 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1000 {
1001 context->handleError(
1002 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1003 return false;
1004 }
1005
1006 if (index >= context->getCaps().maxVertexAttributes)
1007 {
1008 context->handleError(Error(
1009 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1010 return false;
1011 }
1012
1013 if (pointer)
1014 {
1015 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1016 {
1017 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1018 return false;
1019 }
1020 }
1021 else
1022 {
1023 switch (pname)
1024 {
1025 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1026 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1027 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1028 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1029 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1030 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1031 case GL_CURRENT_VERTEX_ATTRIB:
1032 break;
1033
1034 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1035 static_assert(
1036 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1037 "ANGLE extension enums not equal to GL enums.");
1038 if (context->getClientMajorVersion() < 3 &&
1039 !context->getExtensions().instancedArrays)
1040 {
1041 context->handleError(Error(GL_INVALID_ENUM,
1042 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1043 "3.0 or GL_ANGLE_instanced_arrays."));
1044 return false;
1045 }
1046 break;
1047
1048 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1049 if (context->getClientMajorVersion() < 3)
1050 {
1051 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1052 return false;
1053 }
1054 break;
1055
1056 default:
1057 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1058 return false;
1059 }
1060 }
1061
1062 if (length)
1063 {
1064 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1065 {
1066 *length = 4;
1067 }
1068 else
1069 {
1070 *length = 1;
1071 }
1072 }
1073
1074 return true;
1075}
1076
Geoff Lang6899b872016-10-14 11:30:13 -04001077bool ValidateGetActiveUniformBlockivBase(Context *context,
1078 GLuint program,
1079 GLuint uniformBlockIndex,
1080 GLenum pname,
1081 GLsizei *length)
1082{
1083 if (length)
1084 {
1085 *length = 0;
1086 }
1087
1088 if (context->getClientMajorVersion() < 3)
1089 {
1090 context->handleError(
1091 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1092 return false;
1093 }
1094
1095 Program *programObject = GetValidProgram(context, program);
1096 if (!programObject)
1097 {
1098 return false;
1099 }
1100
1101 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1102 {
1103 context->handleError(
1104 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1105 return false;
1106 }
1107
1108 switch (pname)
1109 {
1110 case GL_UNIFORM_BLOCK_BINDING:
1111 case GL_UNIFORM_BLOCK_DATA_SIZE:
1112 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1113 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1114 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1115 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1116 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1117 break;
1118
1119 default:
1120 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1121 return false;
1122 }
1123
1124 if (length)
1125 {
1126 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1127 {
1128 const UniformBlock &uniformBlock =
1129 programObject->getUniformBlockByIndex(uniformBlockIndex);
1130 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1131 }
1132 else
1133 {
1134 *length = 1;
1135 }
1136 }
1137
1138 return true;
1139}
1140
Geoff Langebebe1c2016-10-14 12:01:31 -04001141bool ValidateGetBufferParameterBase(ValidationContext *context,
1142 GLenum target,
1143 GLenum pname,
1144 bool pointerVersion,
1145 GLsizei *numParams)
1146{
1147 if (numParams)
1148 {
1149 *numParams = 0;
1150 }
1151
1152 if (!ValidBufferTarget(context, target))
1153 {
1154 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1155 return false;
1156 }
1157
1158 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1159 if (!buffer)
1160 {
1161 // A null buffer means that "0" is bound to the requested buffer target
1162 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1163 return false;
1164 }
1165
1166 const Extensions &extensions = context->getExtensions();
1167
1168 switch (pname)
1169 {
1170 case GL_BUFFER_USAGE:
1171 case GL_BUFFER_SIZE:
1172 break;
1173
1174 case GL_BUFFER_ACCESS_OES:
1175 if (!extensions.mapBuffer)
1176 {
1177 context->handleError(
1178 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1179 return false;
1180 }
1181 break;
1182
1183 case GL_BUFFER_MAPPED:
1184 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1185 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1186 !extensions.mapBufferRange)
1187 {
1188 context->handleError(Error(
1189 GL_INVALID_ENUM,
1190 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1191 return false;
1192 }
1193 break;
1194
1195 case GL_BUFFER_MAP_POINTER:
1196 if (!pointerVersion)
1197 {
1198 context->handleError(
1199 Error(GL_INVALID_ENUM,
1200 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1201 return false;
1202 }
1203 break;
1204
1205 case GL_BUFFER_ACCESS_FLAGS:
1206 case GL_BUFFER_MAP_OFFSET:
1207 case GL_BUFFER_MAP_LENGTH:
1208 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1209 {
1210 context->handleError(Error(
1211 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1212 return false;
1213 }
1214 break;
1215
1216 default:
1217 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1218 return false;
1219 }
1220
1221 // All buffer parameter queries return one value.
1222 if (numParams)
1223 {
1224 *numParams = 1;
1225 }
1226
1227 return true;
1228}
1229
Geoff Lang0a9661f2016-10-20 10:59:20 -07001230bool ValidateGetInternalFormativBase(Context *context,
1231 GLenum target,
1232 GLenum internalformat,
1233 GLenum pname,
1234 GLsizei bufSize,
1235 GLsizei *numParams)
1236{
1237 if (numParams)
1238 {
1239 *numParams = 0;
1240 }
1241
1242 if (context->getClientMajorVersion() < 3)
1243 {
1244 context->handleError(
1245 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1246 return false;
1247 }
1248
1249 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1250 if (!formatCaps.renderable)
1251 {
1252 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1253 return false;
1254 }
1255
1256 switch (target)
1257 {
1258 case GL_RENDERBUFFER:
1259 break;
1260
1261 default:
1262 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1263 return false;
1264 }
1265
1266 if (bufSize < 0)
1267 {
1268 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1269 return false;
1270 }
1271
1272 GLsizei maxWriteParams = 0;
1273 switch (pname)
1274 {
1275 case GL_NUM_SAMPLE_COUNTS:
1276 maxWriteParams = 1;
1277 break;
1278
1279 case GL_SAMPLES:
1280 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1281 break;
1282
1283 default:
1284 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1285 return false;
1286 }
1287
1288 if (numParams)
1289 {
1290 // glGetInternalFormativ will not overflow bufSize
1291 *numParams = std::min(bufSize, maxWriteParams);
1292 }
1293
1294 return true;
1295}
1296
Geoff Langf41a7152016-09-19 15:11:17 -04001297} // anonymous namespace
1298
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001299bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001300{
Jamie Madilld7460c72014-01-21 16:38:14 -05001301 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001302 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001303 case GL_TEXTURE_2D:
1304 case GL_TEXTURE_CUBE_MAP:
1305 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001306
He Yunchaoced53ae2016-11-29 15:00:51 +08001307 case GL_TEXTURE_3D:
1308 case GL_TEXTURE_2D_ARRAY:
1309 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001310
He Yunchaoced53ae2016-11-29 15:00:51 +08001311 case GL_TEXTURE_2D_MULTISAMPLE:
1312 UNIMPLEMENTED();
1313 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001314
He Yunchaoced53ae2016-11-29 15:00:51 +08001315 default:
1316 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001317 }
Jamie Madill35d15012013-10-07 10:46:37 -04001318}
1319
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001320bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1321{
1322 switch (target)
1323 {
1324 case GL_TEXTURE_2D:
1325 case GL_TEXTURE_CUBE_MAP:
1326 return true;
1327
1328 default:
1329 return false;
1330 }
1331}
1332
1333bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1334{
1335 switch (target)
1336 {
1337 case GL_TEXTURE_3D:
1338 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001339 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001340
1341 default:
1342 return false;
1343 }
1344}
1345
Ian Ewellbda75592016-04-18 17:25:54 -04001346// Most texture GL calls are not compatible with external textures, so we have a separate validation
1347// function for use in the GL calls that do
1348bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1349{
1350 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1351 (context->getExtensions().eglImageExternal ||
1352 context->getExtensions().eglStreamConsumerExternal);
1353}
1354
Shannon Woods4dfed832014-03-17 20:03:39 -04001355// This function differs from ValidTextureTarget in that the target must be
1356// usable as the destination of a 2D operation-- so a cube face is valid, but
1357// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001358// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001359bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001360{
1361 switch (target)
1362 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001363 case GL_TEXTURE_2D:
1364 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1365 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1366 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1367 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1368 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1369 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1370 return true;
1371 default:
1372 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001373 }
1374}
1375
1376bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1377{
1378 switch (target)
1379 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001380 case GL_TEXTURE_3D:
1381 case GL_TEXTURE_2D_ARRAY:
1382 return true;
1383 default:
1384 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001385 }
1386}
1387
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001388bool ValidFramebufferTarget(GLenum target)
1389{
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1391 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001392 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001393
1394 switch (target)
1395 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001396 case GL_FRAMEBUFFER:
1397 return true;
1398 case GL_READ_FRAMEBUFFER:
1399 return true;
1400 case GL_DRAW_FRAMEBUFFER:
1401 return true;
1402 default:
1403 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001404 }
1405}
1406
Jamie Madill29639852016-09-02 15:00:09 -04001407bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001408{
1409 switch (target)
1410 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001411 case GL_ARRAY_BUFFER:
1412 case GL_ELEMENT_ARRAY_BUFFER:
1413 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001414
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 case GL_PIXEL_PACK_BUFFER:
1416 case GL_PIXEL_UNPACK_BUFFER:
1417 return (context->getExtensions().pixelBufferObject ||
1418 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001419
He Yunchaoced53ae2016-11-29 15:00:51 +08001420 case GL_COPY_READ_BUFFER:
1421 case GL_COPY_WRITE_BUFFER:
1422 case GL_TRANSFORM_FEEDBACK_BUFFER:
1423 case GL_UNIFORM_BUFFER:
1424 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001425
He Yunchaoced53ae2016-11-29 15:00:51 +08001426 case GL_ATOMIC_COUNTER_BUFFER:
1427 case GL_SHADER_STORAGE_BUFFER:
1428 case GL_DRAW_INDIRECT_BUFFER:
1429 case GL_DISPATCH_INDIRECT_BUFFER:
1430 UNIMPLEMENTED();
1431 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001432
He Yunchaoced53ae2016-11-29 15:00:51 +08001433 default:
1434 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001435 }
1436}
1437
Jamie Madillc29968b2016-01-20 11:17:23 -05001438bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001439{
Jamie Madillc29968b2016-01-20 11:17:23 -05001440 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001441 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001442 switch (target)
1443 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001444 case GL_TEXTURE_2D:
1445 maxDimension = caps.max2DTextureSize;
1446 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001447 case GL_TEXTURE_CUBE_MAP:
1448 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1449 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1450 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1451 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1452 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1453 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1454 maxDimension = caps.maxCubeMapTextureSize;
1455 break;
1456 case GL_TEXTURE_3D:
1457 maxDimension = caps.max3DTextureSize;
1458 break;
1459 case GL_TEXTURE_2D_ARRAY:
1460 maxDimension = caps.max2DTextureSize;
1461 break;
1462 default:
1463 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001464 }
1465
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001466 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001467}
1468
Austin Kinross08528e12015-10-07 16:24:40 -07001469bool ValidImageSizeParameters(const Context *context,
1470 GLenum target,
1471 GLint level,
1472 GLsizei width,
1473 GLsizei height,
1474 GLsizei depth,
1475 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001476{
1477 if (level < 0 || width < 0 || height < 0 || depth < 0)
1478 {
1479 return false;
1480 }
1481
Austin Kinross08528e12015-10-07 16:24:40 -07001482 // TexSubImage parameters can be NPOT without textureNPOT extension,
1483 // as long as the destination texture is POT.
1484 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001485 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001486 {
1487 return false;
1488 }
1489
1490 if (!ValidMipLevel(context, target, level))
1491 {
1492 return false;
1493 }
1494
1495 return true;
1496}
1497
Geoff Lang0d8b7242015-09-09 14:56:53 -04001498bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1499{
1500 // List of compressed format that require that the texture size is smaller than or a multiple of
1501 // the compressed block size.
1502 switch (internalFormat)
1503 {
1504 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1505 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1506 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1507 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001508 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001509 return true;
1510
1511 default:
1512 return false;
1513 }
1514}
1515
Jamie Madillc29968b2016-01-20 11:17:23 -05001516bool ValidCompressedImageSize(const ValidationContext *context,
1517 GLenum internalFormat,
1518 GLsizei width,
1519 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001520{
Geoff Lang5d601382014-07-22 15:14:06 -04001521 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1522 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001523 {
1524 return false;
1525 }
1526
Geoff Lang0d8b7242015-09-09 14:56:53 -04001527 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001528 {
1529 return false;
1530 }
1531
Geoff Lang0d8b7242015-09-09 14:56:53 -04001532 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1533 {
1534 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1535 width % formatInfo.compressedBlockWidth != 0) ||
1536 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1537 height % formatInfo.compressedBlockHeight != 0))
1538 {
1539 return false;
1540 }
1541 }
1542
Geoff Langd4f180b2013-09-24 13:57:44 -04001543 return true;
1544}
1545
Geoff Langff5b2d52016-09-07 11:32:23 -04001546bool ValidImageDataSize(ValidationContext *context,
1547 GLenum textureTarget,
1548 GLsizei width,
1549 GLsizei height,
1550 GLsizei depth,
1551 GLenum internalFormat,
1552 GLenum type,
1553 const GLvoid *pixels,
1554 GLsizei imageSize)
1555{
1556 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1557 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1558 {
1559 // Checks are not required
1560 return true;
1561 }
1562
1563 // ...the data would be unpacked from the buffer object such that the memory reads required
1564 // would exceed the data store size.
1565 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1566 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1567 const gl::Extents size(width, height, depth);
1568 const auto &unpack = context->getGLState().getUnpackState();
1569
1570 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1571 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1572 if (endByteOrErr.isError())
1573 {
1574 context->handleError(endByteOrErr.getError());
1575 return false;
1576 }
1577
1578 GLuint endByte = endByteOrErr.getResult();
1579
1580 if (pixelUnpackBuffer)
1581 {
1582 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1583 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1584 checkedEndByte += checkedOffset;
1585
1586 if (!checkedEndByte.IsValid() ||
1587 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1588 {
1589 // Overflow past the end of the buffer
1590 context->handleError(Error(GL_INVALID_OPERATION));
1591 return false;
1592 }
1593 }
1594 else
1595 {
1596 ASSERT(imageSize >= 0);
1597 if (pixels == nullptr && imageSize != 0)
1598 {
1599 context->handleError(
1600 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001601 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001602 }
1603
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001604 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001605 {
1606 context->handleError(
1607 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1608 return false;
1609 }
1610 }
1611
1612 return true;
1613}
1614
Geoff Lang37dde692014-01-31 16:34:54 -05001615bool ValidQueryType(const Context *context, GLenum queryType)
1616{
He Yunchaoced53ae2016-11-29 15:00:51 +08001617 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1618 "GL extension enums not equal.");
1619 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1620 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001621
1622 switch (queryType)
1623 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001624 case GL_ANY_SAMPLES_PASSED:
1625 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1626 return true;
1627 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1628 return (context->getClientMajorVersion() >= 3);
1629 case GL_TIME_ELAPSED_EXT:
1630 return context->getExtensions().disjointTimerQuery;
1631 case GL_COMMANDS_COMPLETED_CHROMIUM:
1632 return context->getExtensions().syncQuery;
1633 default:
1634 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001635 }
1636}
1637
Jamie Madillef300b12016-10-07 15:12:09 -04001638Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001639{
He Yunchaoced53ae2016-11-29 15:00:51 +08001640 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1641 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1642 // or program object and INVALID_OPERATION if the provided name identifies an object
1643 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001644
Dian Xiang769769a2015-09-09 15:20:08 -07001645 Program *validProgram = context->getProgram(id);
1646
1647 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001648 {
Dian Xiang769769a2015-09-09 15:20:08 -07001649 if (context->getShader(id))
1650 {
Jamie Madill437fa652016-05-03 15:13:24 -04001651 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001652 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1653 }
1654 else
1655 {
Jamie Madill437fa652016-05-03 15:13:24 -04001656 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001657 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001658 }
Dian Xiang769769a2015-09-09 15:20:08 -07001659
1660 return validProgram;
1661}
1662
Jamie Madillef300b12016-10-07 15:12:09 -04001663Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001664{
1665 // See ValidProgram for spec details.
1666
1667 Shader *validShader = context->getShader(id);
1668
1669 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001670 {
Dian Xiang769769a2015-09-09 15:20:08 -07001671 if (context->getProgram(id))
1672 {
Jamie Madill437fa652016-05-03 15:13:24 -04001673 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001674 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1675 }
1676 else
1677 {
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001679 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001680 }
Dian Xiang769769a2015-09-09 15:20:08 -07001681
1682 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001683}
1684
Geoff Langb1196682014-07-23 13:47:29 -04001685bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001686{
1687 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1688 {
1689 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1690
Geoff Langaae65a42014-05-26 12:43:44 -04001691 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001692 {
Jamie Madill437fa652016-05-03 15:13:24 -04001693 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001694 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001695 }
1696 }
1697 else
1698 {
1699 switch (attachment)
1700 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001701 case GL_DEPTH_ATTACHMENT:
1702 case GL_STENCIL_ATTACHMENT:
1703 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001704
He Yunchaoced53ae2016-11-29 15:00:51 +08001705 case GL_DEPTH_STENCIL_ATTACHMENT:
1706 if (!context->getExtensions().webglCompatibility &&
1707 context->getClientMajorVersion() < 3)
1708 {
1709 context->handleError(Error(GL_INVALID_ENUM));
1710 return false;
1711 }
1712 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001713
He Yunchaoced53ae2016-11-29 15:00:51 +08001714 default:
1715 context->handleError(Error(GL_INVALID_ENUM));
1716 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001717 }
1718 }
1719
1720 return true;
1721}
1722
He Yunchaoced53ae2016-11-29 15:00:51 +08001723bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1724 GLenum target,
1725 GLsizei samples,
1726 GLenum internalformat,
1727 GLsizei width,
1728 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729{
1730 switch (target)
1731 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001732 case GL_RENDERBUFFER:
1733 break;
1734 default:
1735 context->handleError(Error(GL_INVALID_ENUM));
1736 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001737 }
1738
1739 if (width < 0 || height < 0 || samples < 0)
1740 {
Jamie Madill437fa652016-05-03 15:13:24 -04001741 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001742 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001743 }
1744
Geoff Langd87878e2014-09-19 15:42:59 -04001745 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1746 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001747 {
Jamie Madill437fa652016-05-03 15:13:24 -04001748 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001749 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 }
1751
1752 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1753 // 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 -08001754 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001755 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001756 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 }
1761
Geoff Langaae65a42014-05-26 12:43:44 -04001762 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001766 }
1767
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001768 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001769 if (handle == 0)
1770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001772 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001773 }
1774
1775 return true;
1776}
1777
He Yunchaoced53ae2016-11-29 15:00:51 +08001778bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1779 GLenum target,
1780 GLsizei samples,
1781 GLenum internalformat,
1782 GLsizei width,
1783 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001784{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001785 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001786
1787 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001788 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001789 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001790 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001793 return false;
1794 }
1795
1796 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1797 // the specified storage. This is different than ES 3.0 in which a sample number higher
1798 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001799 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001800 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001801 {
Geoff Langa4903b72015-03-02 16:02:48 -08001802 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1803 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001806 return false;
1807 }
Corentin Walleze0902642014-11-04 12:32:15 -08001808 }
1809
He Yunchaoced53ae2016-11-29 15:00:51 +08001810 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1811 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001812}
1813
He Yunchaoced53ae2016-11-29 15:00:51 +08001814bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1815 GLenum target,
1816 GLenum attachment,
1817 GLenum renderbuffertarget,
1818 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001819{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001820 if (!ValidFramebufferTarget(target))
1821 {
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001823 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001824 }
1825
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001826 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001827
Jamie Madill84115c92015-04-23 15:00:07 -04001828 ASSERT(framebuffer);
1829 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001830 {
Jamie Madill437fa652016-05-03 15:13:24 -04001831 context->handleError(
1832 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001833 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001834 }
1835
Jamie Madillb4472272014-07-03 10:38:55 -04001836 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001837 {
Jamie Madillb4472272014-07-03 10:38:55 -04001838 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001839 }
1840
Jamie Madillab9d82c2014-01-21 16:38:14 -05001841 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1842 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1843 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1844 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1845 if (renderbuffer != 0)
1846 {
1847 if (!context->getRenderbuffer(renderbuffer))
1848 {
Jamie Madill437fa652016-05-03 15:13:24 -04001849 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001850 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001851 }
1852 }
1853
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001854 return true;
1855}
1856
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001857bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 GLint srcX0,
1859 GLint srcY0,
1860 GLint srcX1,
1861 GLint srcY1,
1862 GLint dstX0,
1863 GLint dstY0,
1864 GLint dstX1,
1865 GLint dstY1,
1866 GLbitfield mask,
1867 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001868{
1869 switch (filter)
1870 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001871 case GL_NEAREST:
1872 break;
1873 case GL_LINEAR:
1874 break;
1875 default:
1876 context->handleError(Error(GL_INVALID_ENUM));
1877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001878 }
1879
1880 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1881 {
Jamie Madill437fa652016-05-03 15:13:24 -04001882 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001883 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001884 }
1885
1886 if (mask == 0)
1887 {
1888 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1889 // buffers are copied.
1890 return false;
1891 }
1892
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001893 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1894 // color buffer, leaving only nearest being unfiltered from above
1895 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1896 {
Jamie Madill437fa652016-05-03 15:13:24 -04001897 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001898 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001899 }
1900
Jamie Madill51f40ec2016-06-15 14:06:00 -04001901 const auto &glState = context->getGLState();
1902 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1903 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001904
1905 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001906 {
Jamie Madill437fa652016-05-03 15:13:24 -04001907 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001908 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001909 }
1910
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001911 if (readFramebuffer->id() == drawFramebuffer->id())
1912 {
1913 context->handleError(Error(GL_INVALID_OPERATION));
1914 return false;
1915 }
1916
Jamie Madill51f40ec2016-06-15 14:06:00 -04001917 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001918 {
Jamie Madill437fa652016-05-03 15:13:24 -04001919 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001920 return false;
1921 }
1922
Jamie Madill51f40ec2016-06-15 14:06:00 -04001923 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001926 return false;
1927 }
1928
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001929 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001930 {
Jamie Madill437fa652016-05-03 15:13:24 -04001931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001932 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001933 }
1934
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001935 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1936
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001937 if (mask & GL_COLOR_BUFFER_BIT)
1938 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001939 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1940 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001941 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001942
1943 if (readColorBuffer && drawColorBuffer)
1944 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001945 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001946
Geoff Langa15472a2015-08-11 11:48:03 -04001947 for (size_t drawbufferIdx = 0;
1948 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001949 {
Geoff Langa15472a2015-08-11 11:48:03 -04001950 const FramebufferAttachment *attachment =
1951 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1952 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001953 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001954 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955
Geoff Langb2f3d052013-08-13 12:49:27 -04001956 // The GL ES 3.0.2 spec (pg 193) states that:
1957 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001958 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1959 // as well
1960 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1961 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001962 // Changes with EXT_color_buffer_float:
1963 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001964 GLenum readComponentType = readFormat.info->componentType;
1965 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001966 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001967 readComponentType == GL_SIGNED_NORMALIZED);
1968 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1969 drawComponentType == GL_SIGNED_NORMALIZED);
1970
1971 if (extensions.colorBufferFloat)
1972 {
1973 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1974 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1975
1976 if (readFixedOrFloat != drawFixedOrFloat)
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001979 "If the read buffer contains fixed-point or "
1980 "floating-point values, the draw buffer "
1981 "must as well."));
1982 return false;
1983 }
1984 }
1985 else if (readFixedPoint != drawFixedPoint)
1986 {
Jamie Madill437fa652016-05-03 15:13:24 -04001987 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001988 "If the read buffer contains fixed-point "
1989 "values, the draw buffer must as well."));
1990 return false;
1991 }
1992
1993 if (readComponentType == GL_UNSIGNED_INT &&
1994 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001995 {
Jamie Madill437fa652016-05-03 15:13:24 -04001996 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001998 }
1999
Jamie Madill6163c752015-12-07 16:32:59 -05002000 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002001 {
Jamie Madill437fa652016-05-03 15:13:24 -04002002 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002003 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002004 }
2005
Jamie Madilla3944d42016-07-22 22:13:26 -04002006 if (readColorBuffer->getSamples() > 0 &&
2007 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002008 {
Jamie Madill437fa652016-05-03 15:13:24 -04002009 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002010 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002011 }
2012 }
2013 }
2014
Jamie Madilla3944d42016-07-22 22:13:26 -04002015 if ((readFormat.info->componentType == GL_INT ||
2016 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2017 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002021 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002022 }
2023 }
2024
He Yunchaoced53ae2016-11-29 15:00:51 +08002025 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002026 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2027 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002028 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002029 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002030 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002031 const gl::FramebufferAttachment *readBuffer =
2032 readFramebuffer->getAttachment(attachments[i]);
2033 const gl::FramebufferAttachment *drawBuffer =
2034 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002035
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002036 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002037 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002038 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039 {
Jamie Madill437fa652016-05-03 15:13:24 -04002040 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002041 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002042 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002043
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002044 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002047 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002048 }
2049 }
2050 }
2051 }
2052
2053 return true;
2054}
2055
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002056bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002057 GLint x,
2058 GLint y,
2059 GLsizei width,
2060 GLsizei height,
2061 GLenum format,
2062 GLenum type,
2063 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002064{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002065 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2066}
2067
2068bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2069 GLint x,
2070 GLint y,
2071 GLsizei width,
2072 GLsizei height,
2073 GLenum format,
2074 GLenum type,
2075 GLsizei bufSize,
2076 GLsizei *length,
2077 GLvoid *pixels)
2078{
2079 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002080 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002081 return false;
2082 }
2083
Geoff Lang62fce5b2016-09-30 10:46:35 -04002084 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2085 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002086 {
Geoff Langb1196682014-07-23 13:47:29 -04002087 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002088 }
2089
Geoff Lang62fce5b2016-09-30 10:46:35 -04002090 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002091 {
Geoff Langb1196682014-07-23 13:47:29 -04002092 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002093 }
2094
Jamie Madillc29968b2016-01-20 11:17:23 -05002095 return true;
2096}
2097
2098bool ValidateReadnPixelsEXT(Context *context,
2099 GLint x,
2100 GLint y,
2101 GLsizei width,
2102 GLsizei height,
2103 GLenum format,
2104 GLenum type,
2105 GLsizei bufSize,
2106 GLvoid *pixels)
2107{
2108 if (bufSize < 0)
2109 {
Jamie Madill437fa652016-05-03 15:13:24 -04002110 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002111 return false;
2112 }
2113
Geoff Lang62fce5b2016-09-30 10:46:35 -04002114 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2115 pixels);
2116}
Jamie Madill26e91952014-03-05 15:01:27 -05002117
Geoff Lang62fce5b2016-09-30 10:46:35 -04002118bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2119 GLint x,
2120 GLint y,
2121 GLsizei width,
2122 GLsizei height,
2123 GLenum format,
2124 GLenum type,
2125 GLsizei bufSize,
2126 GLsizei *length,
2127 GLvoid *data)
2128{
2129 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002130 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002131 return false;
2132 }
2133
Geoff Lang62fce5b2016-09-30 10:46:35 -04002134 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002135 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002136 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002137 }
2138
Geoff Lang62fce5b2016-09-30 10:46:35 -04002139 if (!ValidateRobustBufferSize(context, bufSize, *length))
2140 {
2141 return false;
2142 }
2143
2144 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002145}
2146
Olli Etuaho41997e72016-03-10 13:38:39 +02002147bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002148{
2149 if (!context->getExtensions().occlusionQueryBoolean &&
2150 !context->getExtensions().disjointTimerQuery)
2151 {
Jamie Madill437fa652016-05-03 15:13:24 -04002152 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002153 return false;
2154 }
2155
Olli Etuaho41997e72016-03-10 13:38:39 +02002156 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002157}
2158
Olli Etuaho41997e72016-03-10 13:38:39 +02002159bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002160{
2161 if (!context->getExtensions().occlusionQueryBoolean &&
2162 !context->getExtensions().disjointTimerQuery)
2163 {
Jamie Madill437fa652016-05-03 15:13:24 -04002164 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002165 return false;
2166 }
2167
Olli Etuaho41997e72016-03-10 13:38:39 +02002168 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002169}
2170
2171bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002172{
2173 if (!ValidQueryType(context, target))
2174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002176 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002177 }
2178
2179 if (id == 0)
2180 {
Jamie Madill437fa652016-05-03 15:13:24 -04002181 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002182 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002183 }
2184
2185 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2186 // of zero, if the active query object name for <target> is non-zero (for the
2187 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2188 // the active query for either target is non-zero), if <id> is the name of an
2189 // existing query object whose type does not match <target>, or if <id> is the
2190 // active query object name for any query type, the error INVALID_OPERATION is
2191 // generated.
2192
2193 // Ensure no other queries are active
2194 // NOTE: If other queries than occlusion are supported, we will need to check
2195 // separately that:
2196 // a) The query ID passed is not the current active query for any target/type
2197 // b) There are no active queries for the requested target (and in the case
2198 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2199 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002200
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002201 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002202 {
Jamie Madill437fa652016-05-03 15:13:24 -04002203 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002204 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002205 }
2206
2207 Query *queryObject = context->getQuery(id, true, target);
2208
2209 // check that name was obtained with glGenQueries
2210 if (!queryObject)
2211 {
Jamie Madill437fa652016-05-03 15:13:24 -04002212 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002213 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002214 }
2215
2216 // check for type mismatch
2217 if (queryObject->getType() != target)
2218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002220 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002221 }
2222
2223 return true;
2224}
2225
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002226bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2227{
2228 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002229 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002230 {
Jamie Madill437fa652016-05-03 15:13:24 -04002231 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002232 return false;
2233 }
2234
2235 return ValidateBeginQueryBase(context, target, id);
2236}
2237
2238bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002239{
2240 if (!ValidQueryType(context, target))
2241 {
Jamie Madill437fa652016-05-03 15:13:24 -04002242 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002243 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002244 }
2245
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002246 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002247
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002248 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002249 {
Jamie Madill437fa652016-05-03 15:13:24 -04002250 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002251 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002252 }
2253
Jamie Madill45c785d2014-05-13 14:09:34 -04002254 return true;
2255}
2256
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002257bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2258{
2259 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002260 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002261 {
Jamie Madill437fa652016-05-03 15:13:24 -04002262 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002263 return false;
2264 }
2265
2266 return ValidateEndQueryBase(context, target);
2267}
2268
2269bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2270{
2271 if (!context->getExtensions().disjointTimerQuery)
2272 {
Jamie Madill437fa652016-05-03 15:13:24 -04002273 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274 return false;
2275 }
2276
2277 if (target != GL_TIMESTAMP_EXT)
2278 {
Jamie Madill437fa652016-05-03 15:13:24 -04002279 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280 return false;
2281 }
2282
2283 Query *queryObject = context->getQuery(id, true, target);
2284 if (queryObject == nullptr)
2285 {
Jamie Madill437fa652016-05-03 15:13:24 -04002286 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002287 return false;
2288 }
2289
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002290 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
2295
2296 return true;
2297}
2298
Geoff Lang2186c382016-10-14 10:54:54 -04002299bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002300{
Geoff Lang2186c382016-10-14 10:54:54 -04002301 if (numParams)
2302 {
2303 *numParams = 0;
2304 }
2305
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002306 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2307 {
Jamie Madill437fa652016-05-03 15:13:24 -04002308 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002309 return false;
2310 }
2311
2312 switch (pname)
2313 {
2314 case GL_CURRENT_QUERY_EXT:
2315 if (target == GL_TIMESTAMP_EXT)
2316 {
Jamie Madill437fa652016-05-03 15:13:24 -04002317 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002318 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2319 return false;
2320 }
2321 break;
2322 case GL_QUERY_COUNTER_BITS_EXT:
2323 if (!context->getExtensions().disjointTimerQuery ||
2324 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2325 {
Jamie Madill437fa652016-05-03 15:13:24 -04002326 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002327 return false;
2328 }
2329 break;
2330 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002331 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002332 return false;
2333 }
2334
Geoff Lang2186c382016-10-14 10:54:54 -04002335 if (numParams)
2336 {
2337 // All queries return only one value
2338 *numParams = 1;
2339 }
2340
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002341 return true;
2342}
2343
2344bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2345{
2346 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002347 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002348 {
Jamie Madill437fa652016-05-03 15:13:24 -04002349 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002350 return false;
2351 }
2352
Geoff Lang2186c382016-10-14 10:54:54 -04002353 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002354}
2355
Geoff Lang2186c382016-10-14 10:54:54 -04002356bool ValidateGetQueryivRobustANGLE(Context *context,
2357 GLenum target,
2358 GLenum pname,
2359 GLsizei bufSize,
2360 GLsizei *length,
2361 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362{
Geoff Lang2186c382016-10-14 10:54:54 -04002363 if (!ValidateRobustEntryPoint(context, bufSize))
2364 {
2365 return false;
2366 }
2367
2368 if (!ValidateGetQueryivBase(context, target, pname, length))
2369 {
2370 return false;
2371 }
2372
2373 if (!ValidateRobustBufferSize(context, bufSize, *length))
2374 {
2375 return false;
2376 }
2377
2378 return true;
2379}
2380
2381bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2382{
2383 if (numParams)
2384 {
2385 *numParams = 0;
2386 }
2387
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002388 Query *queryObject = context->getQuery(id, false, GL_NONE);
2389
2390 if (!queryObject)
2391 {
Jamie Madill437fa652016-05-03 15:13:24 -04002392 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002393 return false;
2394 }
2395
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002396 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002397 {
Jamie Madill437fa652016-05-03 15:13:24 -04002398 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002399 return false;
2400 }
2401
2402 switch (pname)
2403 {
2404 case GL_QUERY_RESULT_EXT:
2405 case GL_QUERY_RESULT_AVAILABLE_EXT:
2406 break;
2407
2408 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002409 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002410 return false;
2411 }
2412
Geoff Lang2186c382016-10-14 10:54:54 -04002413 if (numParams)
2414 {
2415 *numParams = 1;
2416 }
2417
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002418 return true;
2419}
2420
2421bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2422{
2423 if (!context->getExtensions().disjointTimerQuery)
2424 {
Jamie Madill437fa652016-05-03 15:13:24 -04002425 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002426 return false;
2427 }
Geoff Lang2186c382016-10-14 10:54:54 -04002428 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2429}
2430
2431bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2432 GLuint id,
2433 GLenum pname,
2434 GLsizei bufSize,
2435 GLsizei *length,
2436 GLint *params)
2437{
2438 if (!context->getExtensions().disjointTimerQuery)
2439 {
2440 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2441 return false;
2442 }
2443
2444 if (!ValidateRobustEntryPoint(context, bufSize))
2445 {
2446 return false;
2447 }
2448
2449 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2450 {
2451 return false;
2452 }
2453
2454 if (!ValidateRobustBufferSize(context, bufSize, *length))
2455 {
2456 return false;
2457 }
2458
2459 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460}
2461
2462bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2463{
2464 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002465 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002466 {
Jamie Madill437fa652016-05-03 15:13:24 -04002467 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002468 return false;
2469 }
Geoff Lang2186c382016-10-14 10:54:54 -04002470 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2471}
2472
2473bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2474 GLuint id,
2475 GLenum pname,
2476 GLsizei bufSize,
2477 GLsizei *length,
2478 GLuint *params)
2479{
2480 if (!context->getExtensions().disjointTimerQuery &&
2481 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2482 {
2483 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2484 return false;
2485 }
2486
2487 if (!ValidateRobustEntryPoint(context, bufSize))
2488 {
2489 return false;
2490 }
2491
2492 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2493 {
2494 return false;
2495 }
2496
2497 if (!ValidateRobustBufferSize(context, bufSize, *length))
2498 {
2499 return false;
2500 }
2501
2502 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002503}
2504
2505bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2506{
2507 if (!context->getExtensions().disjointTimerQuery)
2508 {
Jamie Madill437fa652016-05-03 15:13:24 -04002509 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002510 return false;
2511 }
Geoff Lang2186c382016-10-14 10:54:54 -04002512 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2513}
2514
2515bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2516 GLuint id,
2517 GLenum pname,
2518 GLsizei bufSize,
2519 GLsizei *length,
2520 GLint64 *params)
2521{
2522 if (!context->getExtensions().disjointTimerQuery)
2523 {
2524 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2525 return false;
2526 }
2527
2528 if (!ValidateRobustEntryPoint(context, bufSize))
2529 {
2530 return false;
2531 }
2532
2533 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2534 {
2535 return false;
2536 }
2537
2538 if (!ValidateRobustBufferSize(context, bufSize, *length))
2539 {
2540 return false;
2541 }
2542
2543 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544}
2545
2546bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2547{
2548 if (!context->getExtensions().disjointTimerQuery)
2549 {
Jamie Madill437fa652016-05-03 15:13:24 -04002550 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002551 return false;
2552 }
Geoff Lang2186c382016-10-14 10:54:54 -04002553 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2554}
2555
2556bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2557 GLuint id,
2558 GLenum pname,
2559 GLsizei bufSize,
2560 GLsizei *length,
2561 GLuint64 *params)
2562{
2563 if (!context->getExtensions().disjointTimerQuery)
2564 {
2565 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2566 return false;
2567 }
2568
2569 if (!ValidateRobustEntryPoint(context, bufSize))
2570 {
2571 return false;
2572 }
2573
2574 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2575 {
2576 return false;
2577 }
2578
2579 if (!ValidateRobustBufferSize(context, bufSize, *length))
2580 {
2581 return false;
2582 }
2583
2584 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002585}
2586
Jamie Madill62d31cb2015-09-11 13:25:51 -04002587static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002588 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002589 GLenum targetUniformType,
2590 GLint location,
2591 GLsizei count,
2592 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002593{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002594 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002595 if (count < 0)
2596 {
Jamie Madill437fa652016-05-03 15:13:24 -04002597 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002598 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002599 }
2600
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002601 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002602 {
Jamie Madill437fa652016-05-03 15:13:24 -04002603 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002604 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002605 }
2606
Geoff Langd8605522016-04-13 10:19:12 -04002607 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002608 {
2609 // Silently ignore the uniform command
2610 return false;
2611 }
2612
Geoff Lang7dd2e102014-11-10 15:19:26 -05002613 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002614 {
Jamie Madill437fa652016-05-03 15:13:24 -04002615 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002616 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002617 }
2618
Jamie Madill62d31cb2015-09-11 13:25:51 -04002619 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002620
2621 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002622 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002623 {
Jamie Madill437fa652016-05-03 15:13:24 -04002624 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002625 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002626 }
2627
Jamie Madill62d31cb2015-09-11 13:25:51 -04002628 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002629 return true;
2630}
2631
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002632bool ValidateProgramUniform(gl::Context *context,
2633 GLenum uniformType,
2634 GLuint program,
2635 GLint location,
2636 GLsizei count)
2637{
2638 // Check for ES31 program uniform entry points
2639 if (context->getClientVersion() < Version(3, 1))
2640 {
2641 context->handleError(Error(GL_INVALID_OPERATION));
2642 return false;
2643 }
2644
2645 const LinkedUniform *uniform = nullptr;
2646 gl::Program *programObject = GetValidProgram(context, program);
2647 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2648 {
2649 return false;
2650 }
2651
2652 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2653 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2654 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2655 {
2656 context->handleError(Error(GL_INVALID_OPERATION));
2657 return false;
2658 }
2659
2660 return true;
2661}
2662
2663bool ValidateProgramUniformMatrix(gl::Context *context,
2664 GLenum matrixType,
2665 GLuint program,
2666 GLint location,
2667 GLsizei count,
2668 GLboolean transpose)
2669{
2670 // Check for ES31 program uniform entry points
2671 if (context->getClientVersion() < Version(3, 1))
2672 {
2673 context->handleError(Error(GL_INVALID_OPERATION));
2674 return false;
2675 }
2676
2677 const LinkedUniform *uniform = nullptr;
2678 gl::Program *programObject = GetValidProgram(context, program);
2679 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2680 {
2681 return false;
2682 }
2683
2684 if (uniform->type != matrixType)
2685 {
2686 context->handleError(Error(GL_INVALID_OPERATION));
2687 return false;
2688 }
2689
2690 return true;
2691}
2692
Jamie Madillaa981bd2014-05-20 10:55:55 -04002693bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2694{
2695 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002696 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2697 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002698 {
Jamie Madill437fa652016-05-03 15:13:24 -04002699 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002701 }
2702
Jamie Madill62d31cb2015-09-11 13:25:51 -04002703 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002704 gl::Program *program = context->getGLState().getProgram();
2705 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002706 {
2707 return false;
2708 }
2709
He Yunchaoced53ae2016-11-29 15:00:51 +08002710 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002711 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002712 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2713 {
Jamie Madill437fa652016-05-03 15:13:24 -04002714 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002715 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002716 }
2717
2718 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002719}
2720
He Yunchaoced53ae2016-11-29 15:00:51 +08002721bool ValidateUniformMatrix(gl::Context *context,
2722 GLenum matrixType,
2723 GLint location,
2724 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002725 GLboolean transpose)
2726{
2727 // Check for ES3 uniform entry points
2728 int rows = VariableRowCount(matrixType);
2729 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002730 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002731 {
Jamie Madill437fa652016-05-03 15:13:24 -04002732 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002733 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002734 }
2735
Martin Radev1be913c2016-07-11 17:59:16 +03002736 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002737 {
Jamie Madill437fa652016-05-03 15:13:24 -04002738 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002739 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002740 }
2741
Jamie Madill62d31cb2015-09-11 13:25:51 -04002742 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002743 gl::Program *program = context->getGLState().getProgram();
2744 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002745 {
2746 return false;
2747 }
2748
2749 if (uniform->type != matrixType)
2750 {
Jamie Madill437fa652016-05-03 15:13:24 -04002751 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002753 }
2754
2755 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002756}
2757
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002758bool ValidateStateQuery(ValidationContext *context,
2759 GLenum pname,
2760 GLenum *nativeType,
2761 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002762{
2763 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2764 {
Jamie Madill437fa652016-05-03 15:13:24 -04002765 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002766 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002767 }
2768
Jamie Madill0af26e12015-03-05 19:54:33 -05002769 const Caps &caps = context->getCaps();
2770
Jamie Madill893ab082014-05-16 16:56:10 -04002771 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2772 {
2773 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2774
Jamie Madill0af26e12015-03-05 19:54:33 -05002775 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002776 {
Jamie Madill437fa652016-05-03 15:13:24 -04002777 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002778 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002779 }
2780 }
2781
2782 switch (pname)
2783 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002784 case GL_TEXTURE_BINDING_2D:
2785 case GL_TEXTURE_BINDING_CUBE_MAP:
2786 case GL_TEXTURE_BINDING_3D:
2787 case GL_TEXTURE_BINDING_2D_ARRAY:
2788 break;
2789 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2790 if (!context->getExtensions().eglStreamConsumerExternal &&
2791 !context->getExtensions().eglImageExternal)
2792 {
2793 context->handleError(Error(GL_INVALID_ENUM,
2794 "Neither NV_EGL_stream_consumer_external nor "
2795 "GL_OES_EGL_image_external extensions enabled"));
2796 return false;
2797 }
2798 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002799
He Yunchaoced53ae2016-11-29 15:00:51 +08002800 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2801 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002802 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002803 if (context->getGLState().getReadFramebuffer()->checkStatus(
2804 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002805 {
Jamie Madill437fa652016-05-03 15:13:24 -04002806 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002807 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002808 }
2809
Jamie Madill51f40ec2016-06-15 14:06:00 -04002810 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2811 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002812
2813 if (framebuffer->getReadBufferState() == GL_NONE)
2814 {
2815 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2816 return false;
2817 }
2818
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002819 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002820 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002821 {
Jamie Madill437fa652016-05-03 15:13:24 -04002822 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002823 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002824 }
2825 }
2826 break;
2827
He Yunchaoced53ae2016-11-29 15:00:51 +08002828 default:
2829 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002830 }
2831
2832 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002833 if (*numParams == 0)
2834 {
2835 return false;
2836 }
2837
2838 return true;
2839}
2840
2841bool ValidateRobustStateQuery(ValidationContext *context,
2842 GLenum pname,
2843 GLsizei bufSize,
2844 GLenum *nativeType,
2845 unsigned int *numParams)
2846{
2847 if (!ValidateRobustEntryPoint(context, bufSize))
2848 {
2849 return false;
2850 }
2851
2852 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2853 {
2854 return false;
2855 }
2856
2857 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002858 {
2859 return false;
2860 }
2861
2862 return true;
2863}
2864
Jamie Madillc29968b2016-01-20 11:17:23 -05002865bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2866 GLenum target,
2867 GLint level,
2868 GLenum internalformat,
2869 bool isSubImage,
2870 GLint xoffset,
2871 GLint yoffset,
2872 GLint zoffset,
2873 GLint x,
2874 GLint y,
2875 GLsizei width,
2876 GLsizei height,
2877 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002878 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002879{
Jamie Madill560a8d82014-05-21 13:06:20 -04002880 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2881 {
Jamie Madill437fa652016-05-03 15:13:24 -04002882 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002883 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002884 }
2885
He Yunchaoced53ae2016-11-29 15:00:51 +08002886 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2887 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002888 {
Jamie Madill437fa652016-05-03 15:13:24 -04002889 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002890 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002891 }
2892
2893 if (border != 0)
2894 {
Jamie Madill437fa652016-05-03 15:13:24 -04002895 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002896 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002897 }
2898
2899 if (!ValidMipLevel(context, target, level))
2900 {
Jamie Madill437fa652016-05-03 15:13:24 -04002901 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002902 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002903 }
2904
Jamie Madill51f40ec2016-06-15 14:06:00 -04002905 const auto &state = context->getGLState();
2906 auto readFramebuffer = state.getReadFramebuffer();
2907 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002908 {
Jamie Madill437fa652016-05-03 15:13:24 -04002909 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002910 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002911 }
2912
Jamie Madill51f40ec2016-06-15 14:06:00 -04002913 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002914 {
Jamie Madill437fa652016-05-03 15:13:24 -04002915 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002916 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002917 }
2918
Martin Radev138064f2016-07-15 12:03:41 +03002919 if (readFramebuffer->getReadBufferState() == GL_NONE)
2920 {
2921 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2922 return false;
2923 }
2924
Geoff Langaae65a42014-05-26 12:43:44 -04002925 const gl::Caps &caps = context->getCaps();
2926
Geoff Langaae65a42014-05-26 12:43:44 -04002927 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002928 switch (target)
2929 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002930 case GL_TEXTURE_2D:
2931 maxDimension = caps.max2DTextureSize;
2932 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002933
He Yunchaoced53ae2016-11-29 15:00:51 +08002934 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2935 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2936 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2937 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2938 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2939 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2940 maxDimension = caps.maxCubeMapTextureSize;
2941 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002942
He Yunchaoced53ae2016-11-29 15:00:51 +08002943 case GL_TEXTURE_2D_ARRAY:
2944 maxDimension = caps.max2DTextureSize;
2945 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002946
He Yunchaoced53ae2016-11-29 15:00:51 +08002947 case GL_TEXTURE_3D:
2948 maxDimension = caps.max3DTextureSize;
2949 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002950
He Yunchaoced53ae2016-11-29 15:00:51 +08002951 default:
2952 context->handleError(Error(GL_INVALID_ENUM));
2953 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002954 }
2955
Jamie Madillc29968b2016-01-20 11:17:23 -05002956 gl::Texture *texture =
2957 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002958 if (!texture)
2959 {
Jamie Madill437fa652016-05-03 15:13:24 -04002960 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002961 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002962 }
2963
Geoff Lang69cce582015-09-17 13:20:36 -04002964 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002965 {
Jamie Madill437fa652016-05-03 15:13:24 -04002966 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002968 }
2969
Geoff Lang5d601382014-07-22 15:14:06 -04002970 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2971
2972 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002973 {
Jamie Madill437fa652016-05-03 15:13:24 -04002974 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002975 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002976 }
2977
Geoff Langa9be0dc2014-12-17 12:34:40 -05002978 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002979 {
Jamie Madill437fa652016-05-03 15:13:24 -04002980 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002981 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002982 }
2983
2984 if (isSubImage)
2985 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002986 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2987 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2988 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002989 {
Jamie Madill437fa652016-05-03 15:13:24 -04002990 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002992 }
2993 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002994 else
2995 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002996 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002997 {
Jamie Madill437fa652016-05-03 15:13:24 -04002998 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002999 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003000 }
3001
Geoff Langeb66a6e2016-10-31 13:06:12 -04003002 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003003 {
Jamie Madill437fa652016-05-03 15:13:24 -04003004 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003005 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003006 }
3007
3008 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003009 if (static_cast<int>(width) > maxLevelDimension ||
3010 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003011 {
Jamie Madill437fa652016-05-03 15:13:24 -04003012 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003013 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003014 }
3015 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003016
Jamie Madill0c8abca2016-07-22 20:21:26 -04003017 if (textureFormatOut)
3018 {
3019 *textureFormatOut = texture->getFormat(target, level);
3020 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003021 return true;
3022}
3023
Jamie Madillf25855c2015-11-03 11:06:18 -05003024static bool ValidateDrawBase(ValidationContext *context,
3025 GLenum mode,
3026 GLsizei count,
3027 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003028{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003029 switch (mode)
3030 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003031 case GL_POINTS:
3032 case GL_LINES:
3033 case GL_LINE_LOOP:
3034 case GL_LINE_STRIP:
3035 case GL_TRIANGLES:
3036 case GL_TRIANGLE_STRIP:
3037 case GL_TRIANGLE_FAN:
3038 break;
3039 default:
3040 context->handleError(Error(GL_INVALID_ENUM));
3041 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003042 }
3043
Jamie Madill250d33f2014-06-06 17:09:03 -04003044 if (count < 0)
3045 {
Jamie Madill437fa652016-05-03 15:13:24 -04003046 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003047 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003048 }
3049
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003050 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003051
Jamie Madill250d33f2014-06-06 17:09:03 -04003052 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003053 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003054 {
Jamie Madill437fa652016-05-03 15:13:24 -04003055 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003056 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003057 }
3058
Jamie Madill51f40ec2016-06-15 14:06:00 -04003059 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003060 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003061 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003062 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003063 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3064 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003065 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3066 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3067 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003068 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003069 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3070 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003071 {
3072 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3073 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003074 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003075 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003076 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003077 return false;
3078 }
Jamie Madillac528012014-06-20 13:21:23 -04003079 }
3080
Jamie Madill51f40ec2016-06-15 14:06:00 -04003081 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003082 {
Jamie Madill437fa652016-05-03 15:13:24 -04003083 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003084 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003085 }
3086
Geoff Lang7dd2e102014-11-10 15:19:26 -05003087 gl::Program *program = state.getProgram();
3088 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003089 {
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003091 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003092 }
3093
Geoff Lang7dd2e102014-11-10 15:19:26 -05003094 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003098 }
3099
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003100 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003101 for (unsigned int uniformBlockIndex = 0;
3102 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003103 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003104 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003105 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003106 const OffsetBindingPointer<Buffer> &uniformBuffer =
3107 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003108
Geoff Lang5d124a62015-09-15 13:03:27 -04003109 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003110 {
3111 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003112 context->handleError(
3113 Error(GL_INVALID_OPERATION,
3114 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003115 return false;
3116 }
3117
Geoff Lang5d124a62015-09-15 13:03:27 -04003118 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003119 if (uniformBufferSize == 0)
3120 {
3121 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003122 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003123 }
3124
Jamie Madill62d31cb2015-09-11 13:25:51 -04003125 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003126 {
3127 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003128 context->handleError(
3129 Error(GL_INVALID_OPERATION,
3130 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003131 return false;
3132 }
3133 }
3134
Jamie Madill250d33f2014-06-06 17:09:03 -04003135 // No-op if zero count
3136 return (count > 0);
3137}
3138
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003139bool ValidateDrawArrays(ValidationContext *context,
3140 GLenum mode,
3141 GLint first,
3142 GLsizei count,
3143 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003144{
Jamie Madillfd716582014-06-06 17:09:04 -04003145 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003146 {
Jamie Madill437fa652016-05-03 15:13:24 -04003147 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003148 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003149 }
3150
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003151 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003152 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003153 if (curTransformFeedback && curTransformFeedback->isActive() &&
3154 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003155 {
3156 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003157 // that does not match the current transform feedback object's draw mode (if transform
3158 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003159 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003160 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003161 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003162 }
3163
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003164 if (!ValidateDrawBase(context, mode, count, primcount))
3165 {
3166 return false;
3167 }
3168
3169 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003170 {
3171 return false;
3172 }
3173
3174 return true;
3175}
3176
He Yunchaoced53ae2016-11-29 15:00:51 +08003177bool ValidateDrawArraysInstanced(Context *context,
3178 GLenum mode,
3179 GLint first,
3180 GLsizei count,
3181 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003182{
3183 if (primcount < 0)
3184 {
Jamie Madill437fa652016-05-03 15:13:24 -04003185 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003187 }
3188
Jamie Madill2b976812014-08-25 15:47:49 -04003189 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003190 {
3191 return false;
3192 }
3193
3194 // No-op if zero primitive count
3195 return (primcount > 0);
3196}
3197
Geoff Lang87a93302014-09-16 13:29:43 -04003198static bool ValidateDrawInstancedANGLE(Context *context)
3199{
3200 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003201 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003202
Geoff Lang7dd2e102014-11-10 15:19:26 -05003203 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003204
3205 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003206 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003207 {
3208 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003209 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003210 {
3211 return true;
3212 }
3213 }
3214
Jamie Madill437fa652016-05-03 15:13:24 -04003215 context->handleError(Error(GL_INVALID_OPERATION,
3216 "ANGLE_instanced_arrays requires that at least one active attribute"
3217 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003218 return false;
3219}
3220
He Yunchaoced53ae2016-11-29 15:00:51 +08003221bool ValidateDrawArraysInstancedANGLE(Context *context,
3222 GLenum mode,
3223 GLint first,
3224 GLsizei count,
3225 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003226{
3227 if (!ValidateDrawInstancedANGLE(context))
3228 {
3229 return false;
3230 }
3231
3232 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3233}
3234
Jamie Madillf25855c2015-11-03 11:06:18 -05003235bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003236 GLenum mode,
3237 GLsizei count,
3238 GLenum type,
3239 const GLvoid *indices,
3240 GLsizei primcount,
3241 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003242{
Jamie Madill250d33f2014-06-06 17:09:03 -04003243 switch (type)
3244 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003245 case GL_UNSIGNED_BYTE:
3246 case GL_UNSIGNED_SHORT:
3247 break;
3248 case GL_UNSIGNED_INT:
3249 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3250 {
3251 context->handleError(Error(GL_INVALID_ENUM));
3252 return false;
3253 }
3254 break;
3255 default:
3256 context->handleError(Error(GL_INVALID_ENUM));
3257 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003258 }
3259
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003260 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003261
3262 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003263 if (curTransformFeedback && curTransformFeedback->isActive() &&
3264 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003265 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003266 // It is an invalid operation to call DrawElements, DrawRangeElements or
3267 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003268 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003269 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003270 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003271 }
3272
3273 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003274 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003275 {
Jamie Madill437fa652016-05-03 15:13:24 -04003276 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003277 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003278 }
3279
He Yunchaoced53ae2016-11-29 15:00:51 +08003280 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003281 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003282 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003283 {
Jamie Madill437fa652016-05-03 15:13:24 -04003284 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003285 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003286 }
3287
Jamie Madillae3000b2014-08-25 15:47:51 -04003288 if (elementArrayBuffer)
3289 {
3290 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3291
3292 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003293 GLint64 byteCount =
3294 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003295
3296 // check for integer overflows
3297 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3298 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3299 {
Jamie Madill437fa652016-05-03 15:13:24 -04003300 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003301 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003302 }
3303
3304 // Check for reading past the end of the bound buffer object
3305 if (byteCount > elementArrayBuffer->getSize())
3306 {
Jamie Madill437fa652016-05-03 15:13:24 -04003307 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003308 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003309 }
3310 }
3311 else if (!indices)
3312 {
3313 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003315 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003316 }
3317
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003318 if (!ValidateDrawBase(context, mode, count, primcount))
3319 {
3320 return false;
3321 }
3322
Jamie Madill2b976812014-08-25 15:47:49 -04003323 // Use max index to validate if our vertex buffers are large enough for the pull.
3324 // TODO: offer fast path, with disabled index validation.
3325 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3326 if (elementArrayBuffer)
3327 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003328 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003329 Error error =
3330 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3331 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003332 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003333 {
Jamie Madill437fa652016-05-03 15:13:24 -04003334 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003335 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003336 }
3337 }
3338 else
3339 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003340 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003341 }
3342
Jamie Madille79b1e12015-11-04 16:36:37 -05003343 // If we use an index greater than our maximum supported index range, return an error.
3344 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3345 // return an error if possible here.
3346 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3347 {
Jamie Madill437fa652016-05-03 15:13:24 -04003348 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003349 return false;
3350 }
3351
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003352 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003353 {
3354 return false;
3355 }
3356
Geoff Lang3edfe032015-09-04 16:38:24 -04003357 // No op if there are no real indices in the index data (all are primitive restart).
3358 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003359}
3360
Geoff Langb1196682014-07-23 13:47:29 -04003361bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003362 GLenum mode,
3363 GLsizei count,
3364 GLenum type,
3365 const GLvoid *indices,
3366 GLsizei primcount,
3367 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003368{
3369 if (primcount < 0)
3370 {
Jamie Madill437fa652016-05-03 15:13:24 -04003371 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003372 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003373 }
3374
Jamie Madill2b976812014-08-25 15:47:49 -04003375 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003376 {
3377 return false;
3378 }
3379
3380 // No-op zero primitive count
3381 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003382}
3383
Geoff Lang3edfe032015-09-04 16:38:24 -04003384bool ValidateDrawElementsInstancedANGLE(Context *context,
3385 GLenum mode,
3386 GLsizei count,
3387 GLenum type,
3388 const GLvoid *indices,
3389 GLsizei primcount,
3390 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003391{
3392 if (!ValidateDrawInstancedANGLE(context))
3393 {
3394 return false;
3395 }
3396
He Yunchaoced53ae2016-11-29 15:00:51 +08003397 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3398 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003399}
3400
He Yunchaoced53ae2016-11-29 15:00:51 +08003401bool ValidateFramebufferTextureBase(Context *context,
3402 GLenum target,
3403 GLenum attachment,
3404 GLuint texture,
3405 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003406{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003407 if (!ValidFramebufferTarget(target))
3408 {
Jamie Madill437fa652016-05-03 15:13:24 -04003409 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003410 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003411 }
3412
3413 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003414 {
3415 return false;
3416 }
3417
Jamie Madill55ec3b12014-07-03 10:38:57 -04003418 if (texture != 0)
3419 {
3420 gl::Texture *tex = context->getTexture(texture);
3421
3422 if (tex == NULL)
3423 {
Jamie Madill437fa652016-05-03 15:13:24 -04003424 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003425 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003426 }
3427
3428 if (level < 0)
3429 {
Jamie Madill437fa652016-05-03 15:13:24 -04003430 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003431 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003432 }
3433 }
3434
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003435 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003436 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003437
Jamie Madill84115c92015-04-23 15:00:07 -04003438 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003439 {
Jamie Madill437fa652016-05-03 15:13:24 -04003440 context->handleError(
3441 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003442 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003443 }
3444
3445 return true;
3446}
3447
He Yunchaoced53ae2016-11-29 15:00:51 +08003448bool ValidateFramebufferTexture2D(Context *context,
3449 GLenum target,
3450 GLenum attachment,
3451 GLenum textarget,
3452 GLuint texture,
3453 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003454{
He Yunchaoced53ae2016-11-29 15:00:51 +08003455 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3456 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003457 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3458 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003459 {
Jamie Madill437fa652016-05-03 15:13:24 -04003460 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003461 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003462 }
3463
3464 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003465 {
3466 return false;
3467 }
3468
Jamie Madill55ec3b12014-07-03 10:38:57 -04003469 if (texture != 0)
3470 {
3471 gl::Texture *tex = context->getTexture(texture);
3472 ASSERT(tex);
3473
Jamie Madill2a6564e2014-07-11 09:53:19 -04003474 const gl::Caps &caps = context->getCaps();
3475
Jamie Madill55ec3b12014-07-03 10:38:57 -04003476 switch (textarget)
3477 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003478 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003479 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003480 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003481 {
Jamie Madill437fa652016-05-03 15:13:24 -04003482 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003483 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003484 }
3485 if (tex->getTarget() != GL_TEXTURE_2D)
3486 {
Jamie Madill437fa652016-05-03 15:13:24 -04003487 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003488 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003489 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003490 }
3491 break;
3492
He Yunchaoced53ae2016-11-29 15:00:51 +08003493 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3494 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3495 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3496 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3497 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3498 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003499 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003500 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003501 {
Jamie Madill437fa652016-05-03 15:13:24 -04003502 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003503 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003504 }
3505 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3506 {
Jamie Madill437fa652016-05-03 15:13:24 -04003507 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003508 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003509 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003510 }
3511 break;
3512
He Yunchaoced53ae2016-11-29 15:00:51 +08003513 default:
3514 context->handleError(Error(GL_INVALID_ENUM));
3515 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003516 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003517
Jamie Madilla3944d42016-07-22 22:13:26 -04003518 const Format &format = tex->getFormat(textarget, level);
3519 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003520 {
Jamie Madill437fa652016-05-03 15:13:24 -04003521 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003522 return false;
3523 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003524 }
3525
Jamie Madill570f7c82014-07-03 10:38:54 -04003526 return true;
3527}
3528
Geoff Langb1196682014-07-23 13:47:29 -04003529bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003530{
3531 if (program == 0)
3532 {
Jamie Madill437fa652016-05-03 15:13:24 -04003533 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003534 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003535 }
3536
Dian Xiang769769a2015-09-09 15:20:08 -07003537 gl::Program *programObject = GetValidProgram(context, program);
3538 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003539 {
3540 return false;
3541 }
3542
Jamie Madill0063c512014-08-25 15:47:53 -04003543 if (!programObject || !programObject->isLinked())
3544 {
Jamie Madill437fa652016-05-03 15:13:24 -04003545 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003546 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003547 }
3548
Geoff Lang7dd2e102014-11-10 15:19:26 -05003549 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003550 {
Jamie Madill437fa652016-05-03 15:13:24 -04003551 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003552 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003553 }
3554
Jamie Madill0063c512014-08-25 15:47:53 -04003555 return true;
3556}
3557
He Yunchaoced53ae2016-11-29 15:00:51 +08003558bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003559{
3560 return ValidateGetUniformBase(context, program, location);
3561}
3562
He Yunchaoced53ae2016-11-29 15:00:51 +08003563bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003564{
Jamie Madill78f41802014-08-25 15:47:55 -04003565 return ValidateGetUniformBase(context, program, location);
3566}
3567
Geoff Langf41d0ee2016-10-07 13:04:23 -04003568static bool ValidateSizedGetUniform(Context *context,
3569 GLuint program,
3570 GLint location,
3571 GLsizei bufSize,
3572 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003573{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003574 if (length)
3575 {
3576 *length = 0;
3577 }
3578
Jamie Madill78f41802014-08-25 15:47:55 -04003579 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003580 {
Jamie Madill78f41802014-08-25 15:47:55 -04003581 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003582 }
3583
Geoff Langf41d0ee2016-10-07 13:04:23 -04003584 if (bufSize < 0)
3585 {
3586 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3587 return false;
3588 }
3589
Jamie Madilla502c742014-08-28 17:19:13 -04003590 gl::Program *programObject = context->getProgram(program);
3591 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003592
Jamie Madill78f41802014-08-25 15:47:55 -04003593 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003594 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003595 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003596 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003597 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003598 context->handleError(
3599 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003600 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003601 }
3602
Geoff Langf41d0ee2016-10-07 13:04:23 -04003603 if (length)
3604 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003605 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003606 }
3607
Jamie Madill0063c512014-08-25 15:47:53 -04003608 return true;
3609}
3610
He Yunchaoced53ae2016-11-29 15:00:51 +08003611bool ValidateGetnUniformfvEXT(Context *context,
3612 GLuint program,
3613 GLint location,
3614 GLsizei bufSize,
3615 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003616{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003617 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003618}
3619
He Yunchaoced53ae2016-11-29 15:00:51 +08003620bool ValidateGetnUniformivEXT(Context *context,
3621 GLuint program,
3622 GLint location,
3623 GLsizei bufSize,
3624 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003625{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003626 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3627}
3628
3629bool ValidateGetUniformfvRobustANGLE(Context *context,
3630 GLuint program,
3631 GLint location,
3632 GLsizei bufSize,
3633 GLsizei *length,
3634 GLfloat *params)
3635{
3636 if (!ValidateRobustEntryPoint(context, bufSize))
3637 {
3638 return false;
3639 }
3640
3641 // bufSize is validated in ValidateSizedGetUniform
3642 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3643}
3644
3645bool ValidateGetUniformivRobustANGLE(Context *context,
3646 GLuint program,
3647 GLint location,
3648 GLsizei bufSize,
3649 GLsizei *length,
3650 GLint *params)
3651{
3652 if (!ValidateRobustEntryPoint(context, bufSize))
3653 {
3654 return false;
3655 }
3656
3657 // bufSize is validated in ValidateSizedGetUniform
3658 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3659}
3660
3661bool ValidateGetUniformuivRobustANGLE(Context *context,
3662 GLuint program,
3663 GLint location,
3664 GLsizei bufSize,
3665 GLsizei *length,
3666 GLuint *params)
3667{
3668 if (!ValidateRobustEntryPoint(context, bufSize))
3669 {
3670 return false;
3671 }
3672
3673 if (context->getClientMajorVersion() < 3)
3674 {
3675 context->handleError(
3676 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3677 return false;
3678 }
3679
3680 // bufSize is validated in ValidateSizedGetUniform
3681 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003682}
3683
He Yunchaoced53ae2016-11-29 15:00:51 +08003684bool ValidateDiscardFramebufferBase(Context *context,
3685 GLenum target,
3686 GLsizei numAttachments,
3687 const GLenum *attachments,
3688 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003689{
3690 if (numAttachments < 0)
3691 {
Jamie Madill437fa652016-05-03 15:13:24 -04003692 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003693 return false;
3694 }
3695
3696 for (GLsizei i = 0; i < numAttachments; ++i)
3697 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003698 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003699 {
3700 if (defaultFramebuffer)
3701 {
Jamie Madill437fa652016-05-03 15:13:24 -04003702 context->handleError(Error(
3703 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003704 return false;
3705 }
3706
3707 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3708 {
Jamie Madill437fa652016-05-03 15:13:24 -04003709 context->handleError(Error(GL_INVALID_OPERATION,
3710 "Requested color attachment is greater than the maximum "
3711 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003712 return false;
3713 }
3714 }
3715 else
3716 {
3717 switch (attachments[i])
3718 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003719 case GL_DEPTH_ATTACHMENT:
3720 case GL_STENCIL_ATTACHMENT:
3721 case GL_DEPTH_STENCIL_ATTACHMENT:
3722 if (defaultFramebuffer)
3723 {
3724 context->handleError(
3725 Error(GL_INVALID_ENUM,
3726 "Invalid attachment when the default framebuffer is bound"));
3727 return false;
3728 }
3729 break;
3730 case GL_COLOR:
3731 case GL_DEPTH:
3732 case GL_STENCIL:
3733 if (!defaultFramebuffer)
3734 {
3735 context->handleError(
3736 Error(GL_INVALID_ENUM,
3737 "Invalid attachment when the default framebuffer is not bound"));
3738 return false;
3739 }
3740 break;
3741 default:
3742 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003743 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003744 }
3745 }
3746 }
3747
3748 return true;
3749}
3750
Austin Kinross6ee1e782015-05-29 17:05:37 -07003751bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3752{
3753 // Note that debug marker calls must not set error state
3754
3755 if (length < 0)
3756 {
3757 return false;
3758 }
3759
3760 if (marker == nullptr)
3761 {
3762 return false;
3763 }
3764
3765 return true;
3766}
3767
3768bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3769{
3770 // Note that debug marker calls must not set error state
3771
3772 if (length < 0)
3773 {
3774 return false;
3775 }
3776
3777 if (length > 0 && marker == nullptr)
3778 {
3779 return false;
3780 }
3781
3782 return true;
3783}
3784
Geoff Langdcab33b2015-07-21 13:03:16 -04003785bool ValidateEGLImageTargetTexture2DOES(Context *context,
3786 egl::Display *display,
3787 GLenum target,
3788 egl::Image *image)
3789{
Geoff Langa8406172015-07-21 16:53:39 -04003790 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3791 {
Jamie Madill437fa652016-05-03 15:13:24 -04003792 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003793 return false;
3794 }
3795
3796 switch (target)
3797 {
3798 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003799 if (!context->getExtensions().eglImage)
3800 {
3801 context->handleError(Error(
3802 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3803 }
3804 break;
3805
3806 case GL_TEXTURE_EXTERNAL_OES:
3807 if (!context->getExtensions().eglImageExternal)
3808 {
3809 context->handleError(Error(
3810 GL_INVALID_ENUM,
3811 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3812 }
Geoff Langa8406172015-07-21 16:53:39 -04003813 break;
3814
3815 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003816 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003817 return false;
3818 }
3819
3820 if (!display->isValidImage(image))
3821 {
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003823 return false;
3824 }
3825
3826 if (image->getSamples() > 0)
3827 {
Jamie Madill437fa652016-05-03 15:13:24 -04003828 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003829 "cannot create a 2D texture from a multisampled EGL image."));
3830 return false;
3831 }
3832
Jamie Madilla3944d42016-07-22 22:13:26 -04003833 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003834 if (!textureCaps.texturable)
3835 {
Jamie Madill437fa652016-05-03 15:13:24 -04003836 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003837 "EGL image internal format is not supported as a texture."));
3838 return false;
3839 }
3840
Geoff Langdcab33b2015-07-21 13:03:16 -04003841 return true;
3842}
3843
3844bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3845 egl::Display *display,
3846 GLenum target,
3847 egl::Image *image)
3848{
Geoff Langa8406172015-07-21 16:53:39 -04003849 if (!context->getExtensions().eglImage)
3850 {
Jamie Madill437fa652016-05-03 15:13:24 -04003851 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003852 return false;
3853 }
3854
3855 switch (target)
3856 {
3857 case GL_RENDERBUFFER:
3858 break;
3859
3860 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003861 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003862 return false;
3863 }
3864
3865 if (!display->isValidImage(image))
3866 {
Jamie Madill437fa652016-05-03 15:13:24 -04003867 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003868 return false;
3869 }
3870
Jamie Madilla3944d42016-07-22 22:13:26 -04003871 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003872 if (!textureCaps.renderable)
3873 {
Jamie Madill437fa652016-05-03 15:13:24 -04003874 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003875 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3876 return false;
3877 }
3878
Geoff Langdcab33b2015-07-21 13:03:16 -04003879 return true;
3880}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003881
3882bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3883{
Geoff Lang36167ab2015-12-07 10:27:14 -05003884 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003885 {
3886 // The default VAO should always exist
3887 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003888 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003889 return false;
3890 }
3891
3892 return true;
3893}
3894
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003895bool ValidateLinkProgram(Context *context, GLuint program)
3896{
3897 if (context->hasActiveTransformFeedback(program))
3898 {
3899 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003900 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003901 "Cannot link program while program is associated with an active "
3902 "transform feedback object."));
3903 return false;
3904 }
3905 return true;
3906}
3907
Geoff Langc5629752015-12-07 16:29:04 -05003908bool ValidateProgramBinaryBase(Context *context,
3909 GLuint program,
3910 GLenum binaryFormat,
3911 const void *binary,
3912 GLint length)
3913{
3914 Program *programObject = GetValidProgram(context, program);
3915 if (programObject == nullptr)
3916 {
3917 return false;
3918 }
3919
3920 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3921 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3922 programBinaryFormats.end())
3923 {
Jamie Madill437fa652016-05-03 15:13:24 -04003924 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003925 return false;
3926 }
3927
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003928 if (context->hasActiveTransformFeedback(program))
3929 {
3930 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003931 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003932 "Cannot change program binary while program is associated with "
3933 "an active transform feedback object."));
3934 return false;
3935 }
3936
Geoff Langc5629752015-12-07 16:29:04 -05003937 return true;
3938}
3939
3940bool ValidateGetProgramBinaryBase(Context *context,
3941 GLuint program,
3942 GLsizei bufSize,
3943 GLsizei *length,
3944 GLenum *binaryFormat,
3945 void *binary)
3946{
3947 Program *programObject = GetValidProgram(context, program);
3948 if (programObject == nullptr)
3949 {
3950 return false;
3951 }
3952
3953 if (!programObject->isLinked())
3954 {
Jamie Madill437fa652016-05-03 15:13:24 -04003955 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003956 return false;
3957 }
3958
3959 return true;
3960}
Jamie Madillc29968b2016-01-20 11:17:23 -05003961
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003962bool ValidateUseProgram(Context *context, GLuint program)
3963{
3964 if (program != 0)
3965 {
3966 Program *programObject = context->getProgram(program);
3967 if (!programObject)
3968 {
3969 // ES 3.1.0 section 7.3 page 72
3970 if (context->getShader(program))
3971 {
Jamie Madill437fa652016-05-03 15:13:24 -04003972 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003973 Error(GL_INVALID_OPERATION,
3974 "Attempted to use a single shader instead of a shader program."));
3975 return false;
3976 }
3977 else
3978 {
Jamie Madill437fa652016-05-03 15:13:24 -04003979 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003980 return false;
3981 }
3982 }
3983 if (!programObject->isLinked())
3984 {
Jamie Madill437fa652016-05-03 15:13:24 -04003985 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003986 return false;
3987 }
3988 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003989 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003990 {
3991 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003992 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003993 Error(GL_INVALID_OPERATION,
3994 "Cannot change active program while transform feedback is unpaused."));
3995 return false;
3996 }
3997
3998 return true;
3999}
4000
Jamie Madillc29968b2016-01-20 11:17:23 -05004001bool ValidateCopyTexImage2D(ValidationContext *context,
4002 GLenum target,
4003 GLint level,
4004 GLenum internalformat,
4005 GLint x,
4006 GLint y,
4007 GLsizei width,
4008 GLsizei height,
4009 GLint border)
4010{
Martin Radev1be913c2016-07-11 17:59:16 +03004011 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004012 {
4013 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4014 0, x, y, width, height, border);
4015 }
4016
Martin Radev1be913c2016-07-11 17:59:16 +03004017 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004018 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4019 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004020}
Jamie Madillc29968b2016-01-20 11:17:23 -05004021
4022bool ValidateFramebufferRenderbuffer(Context *context,
4023 GLenum target,
4024 GLenum attachment,
4025 GLenum renderbuffertarget,
4026 GLuint renderbuffer)
4027{
4028 if (!ValidFramebufferTarget(target) ||
4029 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4030 {
Jamie Madill437fa652016-05-03 15:13:24 -04004031 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004032 return false;
4033 }
4034
4035 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4036 renderbuffertarget, renderbuffer);
4037}
4038
4039bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4040{
4041 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4042 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4043 {
Jamie Madill437fa652016-05-03 15:13:24 -04004044 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004045 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4046 return false;
4047 }
4048
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004049 ASSERT(context->getGLState().getDrawFramebuffer());
4050 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004051 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4052
4053 // This should come first before the check for the default frame buffer
4054 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4055 // rather than INVALID_OPERATION
4056 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4057 {
4058 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4059
4060 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004061 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4062 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004063 {
4064 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004065 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4066 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4067 // 3.1 is still a bit ambiguous about the error, but future specs are
4068 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004069 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004070 return false;
4071 }
4072 else if (bufs[colorAttachment] >= maxColorAttachment)
4073 {
Jamie Madill437fa652016-05-03 15:13:24 -04004074 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004075 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004076 return false;
4077 }
4078 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4079 frameBufferId != 0)
4080 {
4081 // INVALID_OPERATION-GL is bound to buffer and ith argument
4082 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004083 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004084 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4085 return false;
4086 }
4087 }
4088
4089 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4090 // and n is not 1 or bufs is bound to value other than BACK and NONE
4091 if (frameBufferId == 0)
4092 {
4093 if (n != 1)
4094 {
Jamie Madill437fa652016-05-03 15:13:24 -04004095 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004096 "n must be 1 when GL is bound to the default framebuffer"));
4097 return false;
4098 }
4099
4100 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4101 {
Jamie Madill437fa652016-05-03 15:13:24 -04004102 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004103 GL_INVALID_OPERATION,
4104 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4105 return false;
4106 }
4107 }
4108
4109 return true;
4110}
4111
4112bool ValidateCopyTexSubImage2D(Context *context,
4113 GLenum target,
4114 GLint level,
4115 GLint xoffset,
4116 GLint yoffset,
4117 GLint x,
4118 GLint y,
4119 GLsizei width,
4120 GLsizei height)
4121{
Martin Radev1be913c2016-07-11 17:59:16 +03004122 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004123 {
4124 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4125 yoffset, x, y, width, height, 0);
4126 }
4127
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004128 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4129 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004130}
4131
Geoff Lang496c02d2016-10-20 11:38:11 -07004132bool ValidateGetBufferPointervBase(Context *context,
4133 GLenum target,
4134 GLenum pname,
4135 GLsizei *length,
4136 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004137{
Geoff Lang496c02d2016-10-20 11:38:11 -07004138 if (length)
4139 {
4140 *length = 0;
4141 }
4142
4143 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4144 {
4145 context->handleError(
4146 Error(GL_INVALID_OPERATION,
4147 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4148 return false;
4149 }
4150
Olli Etuaho4f667482016-03-30 15:56:35 +03004151 if (!ValidBufferTarget(context, target))
4152 {
Jamie Madill437fa652016-05-03 15:13:24 -04004153 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004154 return false;
4155 }
4156
Geoff Lang496c02d2016-10-20 11:38:11 -07004157 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004158 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004159 case GL_BUFFER_MAP_POINTER:
4160 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004161
Geoff Lang496c02d2016-10-20 11:38:11 -07004162 default:
4163 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4164 return false;
4165 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004166
4167 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4168 // target bound to zero generate an INVALID_OPERATION error."
4169 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004170 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004171 {
Jamie Madill437fa652016-05-03 15:13:24 -04004172 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004173 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4174 return false;
4175 }
4176
Geoff Lang496c02d2016-10-20 11:38:11 -07004177 if (length)
4178 {
4179 *length = 1;
4180 }
4181
Olli Etuaho4f667482016-03-30 15:56:35 +03004182 return true;
4183}
4184
4185bool ValidateUnmapBufferBase(Context *context, GLenum target)
4186{
4187 if (!ValidBufferTarget(context, target))
4188 {
Jamie Madill437fa652016-05-03 15:13:24 -04004189 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004190 return false;
4191 }
4192
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004193 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004194
4195 if (buffer == nullptr || !buffer->isMapped())
4196 {
Jamie Madill437fa652016-05-03 15:13:24 -04004197 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004198 return false;
4199 }
4200
4201 return true;
4202}
4203
4204bool ValidateMapBufferRangeBase(Context *context,
4205 GLenum target,
4206 GLintptr offset,
4207 GLsizeiptr length,
4208 GLbitfield access)
4209{
4210 if (!ValidBufferTarget(context, target))
4211 {
Jamie Madill437fa652016-05-03 15:13:24 -04004212 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004213 return false;
4214 }
4215
4216 if (offset < 0 || length < 0)
4217 {
Jamie Madill437fa652016-05-03 15:13:24 -04004218 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004219 return false;
4220 }
4221
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004222 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004223
4224 if (!buffer)
4225 {
Jamie Madill437fa652016-05-03 15:13:24 -04004226 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004227 return false;
4228 }
4229
4230 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004231 CheckedNumeric<size_t> checkedOffset(offset);
4232 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004233
Jamie Madille2e406c2016-06-02 13:04:10 -04004234 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004235 {
Jamie Madill437fa652016-05-03 15:13:24 -04004236 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004237 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4238 return false;
4239 }
4240
4241 // Check for invalid bits in the mask
4242 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4243 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4244 GL_MAP_UNSYNCHRONIZED_BIT;
4245
4246 if (access & ~(allAccessBits))
4247 {
Jamie Madill437fa652016-05-03 15:13:24 -04004248 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004249 return false;
4250 }
4251
4252 if (length == 0)
4253 {
Jamie Madill437fa652016-05-03 15:13:24 -04004254 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004255 return false;
4256 }
4257
4258 if (buffer->isMapped())
4259 {
Jamie Madill437fa652016-05-03 15:13:24 -04004260 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004261 return false;
4262 }
4263
4264 // Check for invalid bit combinations
4265 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4266 {
Jamie Madill437fa652016-05-03 15:13:24 -04004267 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004268 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4269 return false;
4270 }
4271
4272 GLbitfield writeOnlyBits =
4273 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4274
4275 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4276 {
Jamie Madill437fa652016-05-03 15:13:24 -04004277 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004278 "Invalid access bits when mapping buffer for reading: 0x%X.",
4279 access));
4280 return false;
4281 }
4282
4283 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4284 {
Jamie Madill437fa652016-05-03 15:13:24 -04004285 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004286 GL_INVALID_OPERATION,
4287 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4288 return false;
4289 }
4290 return true;
4291}
4292
4293bool ValidateFlushMappedBufferRangeBase(Context *context,
4294 GLenum target,
4295 GLintptr offset,
4296 GLsizeiptr length)
4297{
4298 if (offset < 0 || length < 0)
4299 {
Jamie Madill437fa652016-05-03 15:13:24 -04004300 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004301 return false;
4302 }
4303
4304 if (!ValidBufferTarget(context, target))
4305 {
Jamie Madill437fa652016-05-03 15:13:24 -04004306 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004307 return false;
4308 }
4309
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004310 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004311
4312 if (buffer == nullptr)
4313 {
Jamie Madill437fa652016-05-03 15:13:24 -04004314 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004315 return false;
4316 }
4317
4318 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4319 {
Jamie Madill437fa652016-05-03 15:13:24 -04004320 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004321 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4322 return false;
4323 }
4324
4325 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004326 CheckedNumeric<size_t> checkedOffset(offset);
4327 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004328
Jamie Madille2e406c2016-06-02 13:04:10 -04004329 if (!checkedSize.IsValid() ||
4330 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004331 {
Jamie Madill437fa652016-05-03 15:13:24 -04004332 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004333 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4334 return false;
4335 }
4336
4337 return true;
4338}
4339
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004340bool ValidateGenerateMipmap(Context *context, GLenum target)
4341{
4342 if (!ValidTextureTarget(context, target))
4343 {
4344 context->handleError(Error(GL_INVALID_ENUM));
4345 return false;
4346 }
4347
4348 Texture *texture = context->getTargetTexture(target);
4349
4350 if (texture == nullptr)
4351 {
4352 context->handleError(Error(GL_INVALID_OPERATION));
4353 return false;
4354 }
4355
4356 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4357
4358 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4359 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4360 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4361 {
4362 context->handleError(Error(GL_INVALID_OPERATION));
4363 return false;
4364 }
4365
Jamie Madilla3944d42016-07-22 22:13:26 -04004366 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4367 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4368 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004369
4370 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4371 // unsized formats or that are color renderable and filterable. Since we do not track if
4372 // the texture was created with sized or unsized format (only sized formats are stored),
4373 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4374 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4375 // textures since they're the only texture format that can be created with unsized formats
4376 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4377 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004378 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4379 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004380 {
4381 context->handleError(Error(GL_INVALID_OPERATION));
4382 return false;
4383 }
4384
4385 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004386 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004387 {
4388 context->handleError(Error(GL_INVALID_OPERATION));
4389 return false;
4390 }
4391
4392 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004393 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004394 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4395 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4396 {
Geoff Lang55482a12016-11-21 16:54:01 -05004397 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004398 context->handleError(Error(GL_INVALID_OPERATION));
4399 return false;
4400 }
4401
4402 // Cube completeness check
4403 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4404 {
4405 context->handleError(Error(GL_INVALID_OPERATION));
4406 return false;
4407 }
4408
4409 return true;
4410}
4411
Olli Etuaho41997e72016-03-10 13:38:39 +02004412bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4413{
4414 return ValidateGenOrDelete(context, n);
4415}
4416
4417bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4418{
4419 return ValidateGenOrDelete(context, n);
4420}
4421
4422bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4423{
4424 return ValidateGenOrDelete(context, n);
4425}
4426
4427bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4428{
4429 return ValidateGenOrDelete(context, n);
4430}
4431
4432bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4433{
4434 return ValidateGenOrDelete(context, n);
4435}
4436
4437bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4438{
4439 return ValidateGenOrDelete(context, n);
4440}
4441
4442bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4443{
4444 return ValidateGenOrDelete(context, n);
4445}
4446
4447bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4448{
4449 return ValidateGenOrDelete(context, n);
4450}
4451
4452bool ValidateGenOrDelete(Context *context, GLint n)
4453{
4454 if (n < 0)
4455 {
Jamie Madill437fa652016-05-03 15:13:24 -04004456 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004457 return false;
4458 }
4459 return true;
4460}
4461
Geoff Langf41a7152016-09-19 15:11:17 -04004462bool ValidateEnable(Context *context, GLenum cap)
4463{
4464 if (!ValidCap(context, cap, false))
4465 {
4466 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4467 return false;
4468 }
4469
4470 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4471 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4472 {
4473 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4474 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4475
4476 // We also output an error message to the debugger window if tracing is active, so that
4477 // developers can see the error message.
4478 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004479 return false;
4480 }
4481
4482 return true;
4483}
4484
4485bool ValidateDisable(Context *context, GLenum cap)
4486{
4487 if (!ValidCap(context, cap, false))
4488 {
4489 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4490 return false;
4491 }
4492
4493 return true;
4494}
4495
4496bool ValidateIsEnabled(Context *context, GLenum cap)
4497{
4498 if (!ValidCap(context, cap, true))
4499 {
4500 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4501 return false;
4502 }
4503
4504 return true;
4505}
4506
Geoff Langff5b2d52016-09-07 11:32:23 -04004507bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4508{
4509 if (!context->getExtensions().robustClientMemory)
4510 {
4511 context->handleError(
4512 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4513 return false;
4514 }
4515
4516 if (bufSize < 0)
4517 {
4518 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4519 return false;
4520 }
4521
4522 return true;
4523}
4524
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004525bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4526{
4527 if (bufSize < numParams)
4528 {
4529 context->handleError(Error(GL_INVALID_OPERATION,
4530 "%u parameters are required but %i were provided.", numParams,
4531 bufSize));
4532 return false;
4533 }
4534
4535 return true;
4536}
4537
Geoff Langff5b2d52016-09-07 11:32:23 -04004538bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4539 GLenum target,
4540 GLenum attachment,
4541 GLenum pname,
4542 GLsizei *numParams)
4543{
4544 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4545 *numParams = 1;
4546
4547 if (!ValidFramebufferTarget(target))
4548 {
4549 context->handleError(Error(GL_INVALID_ENUM));
4550 return false;
4551 }
4552
4553 int clientVersion = context->getClientMajorVersion();
4554
4555 switch (pname)
4556 {
4557 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4558 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4559 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4560 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4561 break;
4562
4563 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4564 if (clientVersion < 3 && !context->getExtensions().sRGB)
4565 {
4566 context->handleError(Error(GL_INVALID_ENUM));
4567 return false;
4568 }
4569 break;
4570
4571 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4572 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4573 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4574 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4575 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4576 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4577 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4578 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4579 if (clientVersion < 3)
4580 {
4581 context->handleError(Error(GL_INVALID_ENUM));
4582 return false;
4583 }
4584 break;
4585
4586 default:
4587 context->handleError(Error(GL_INVALID_ENUM));
4588 return false;
4589 }
4590
4591 // Determine if the attachment is a valid enum
4592 switch (attachment)
4593 {
4594 case GL_BACK:
4595 case GL_FRONT:
4596 case GL_DEPTH:
4597 case GL_STENCIL:
4598 case GL_DEPTH_STENCIL_ATTACHMENT:
4599 if (clientVersion < 3)
4600 {
4601 context->handleError(Error(GL_INVALID_ENUM));
4602 return false;
4603 }
4604 break;
4605
4606 case GL_DEPTH_ATTACHMENT:
4607 case GL_STENCIL_ATTACHMENT:
4608 break;
4609
4610 default:
4611 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4612 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4613 {
4614 context->handleError(Error(GL_INVALID_ENUM));
4615 return false;
4616 }
4617 break;
4618 }
4619
4620 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4621 ASSERT(framebuffer);
4622
4623 if (framebuffer->id() == 0)
4624 {
4625 if (clientVersion < 3)
4626 {
4627 context->handleError(Error(GL_INVALID_OPERATION));
4628 return false;
4629 }
4630
4631 switch (attachment)
4632 {
4633 case GL_BACK:
4634 case GL_DEPTH:
4635 case GL_STENCIL:
4636 break;
4637
4638 default:
4639 context->handleError(Error(GL_INVALID_OPERATION));
4640 return false;
4641 }
4642 }
4643 else
4644 {
4645 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4646 {
4647 // Valid attachment query
4648 }
4649 else
4650 {
4651 switch (attachment)
4652 {
4653 case GL_DEPTH_ATTACHMENT:
4654 case GL_STENCIL_ATTACHMENT:
4655 break;
4656
4657 case GL_DEPTH_STENCIL_ATTACHMENT:
4658 if (!framebuffer->hasValidDepthStencil())
4659 {
4660 context->handleError(Error(GL_INVALID_OPERATION));
4661 return false;
4662 }
4663 break;
4664
4665 default:
4666 context->handleError(Error(GL_INVALID_OPERATION));
4667 return false;
4668 }
4669 }
4670 }
4671
4672 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4673 if (attachmentObject)
4674 {
4675 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4676 attachmentObject->type() == GL_TEXTURE ||
4677 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4678
4679 switch (pname)
4680 {
4681 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4682 if (attachmentObject->type() != GL_RENDERBUFFER &&
4683 attachmentObject->type() != GL_TEXTURE)
4684 {
4685 context->handleError(Error(GL_INVALID_ENUM));
4686 return false;
4687 }
4688 break;
4689
4690 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4691 if (attachmentObject->type() != GL_TEXTURE)
4692 {
4693 context->handleError(Error(GL_INVALID_ENUM));
4694 return false;
4695 }
4696 break;
4697
4698 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4699 if (attachmentObject->type() != GL_TEXTURE)
4700 {
4701 context->handleError(Error(GL_INVALID_ENUM));
4702 return false;
4703 }
4704 break;
4705
4706 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4707 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4708 {
4709 context->handleError(Error(GL_INVALID_OPERATION));
4710 return false;
4711 }
4712 break;
4713
4714 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4715 if (attachmentObject->type() != GL_TEXTURE)
4716 {
4717 context->handleError(Error(GL_INVALID_ENUM));
4718 return false;
4719 }
4720 break;
4721
4722 default:
4723 break;
4724 }
4725 }
4726 else
4727 {
4728 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4729 // is NONE, then querying any other pname will generate INVALID_ENUM.
4730
4731 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4732 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4733 // INVALID_OPERATION for all other pnames
4734
4735 switch (pname)
4736 {
4737 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4738 break;
4739
4740 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4741 if (clientVersion < 3)
4742 {
4743 context->handleError(Error(GL_INVALID_ENUM));
4744 return false;
4745 }
4746 break;
4747
4748 default:
4749 if (clientVersion < 3)
4750 {
4751 context->handleError(Error(GL_INVALID_ENUM));
4752 return false;
4753 }
4754 else
4755 {
4756 context->handleError(Error(GL_INVALID_OPERATION));
4757 return false;
4758 }
4759 }
4760 }
4761
4762 return true;
4763}
4764
4765bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4766 GLenum target,
4767 GLenum attachment,
4768 GLenum pname,
4769 GLsizei bufSize,
4770 GLsizei *numParams)
4771{
4772 if (!ValidateRobustEntryPoint(context, bufSize))
4773 {
4774 return false;
4775 }
4776
4777 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4778 {
4779 return false;
4780 }
4781
4782 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4783 {
4784 return false;
4785 }
4786
4787 return true;
4788}
4789
4790bool ValidateGetBufferParameteriv(ValidationContext *context,
4791 GLenum target,
4792 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004793 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004794{
Geoff Langebebe1c2016-10-14 12:01:31 -04004795 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004796}
4797
4798bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4799 GLenum target,
4800 GLenum pname,
4801 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004802 GLsizei *length,
4803 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004804{
4805 if (!ValidateRobustEntryPoint(context, bufSize))
4806 {
4807 return false;
4808 }
4809
Geoff Langebebe1c2016-10-14 12:01:31 -04004810 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004811 {
4812 return false;
4813 }
4814
Geoff Langebebe1c2016-10-14 12:01:31 -04004815 if (!ValidateRobustBufferSize(context, bufSize, *length))
4816 {
4817 return false;
4818 }
4819
4820 return true;
4821}
4822
4823bool ValidateGetBufferParameteri64v(ValidationContext *context,
4824 GLenum target,
4825 GLenum pname,
4826 GLint64 *params)
4827{
4828 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4829}
4830
4831bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4832 GLenum target,
4833 GLenum pname,
4834 GLsizei bufSize,
4835 GLsizei *length,
4836 GLint64 *params)
4837{
4838 if (!ValidateRobustEntryPoint(context, bufSize))
4839 {
4840 return false;
4841 }
4842
4843 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4844 {
4845 return false;
4846 }
4847
4848 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004849 {
4850 return false;
4851 }
4852
4853 return true;
4854}
4855
4856bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4857{
4858 // Currently, all GetProgramiv queries return 1 parameter
4859 *numParams = 1;
4860
4861 Program *programObject = GetValidProgram(context, program);
4862 if (!programObject)
4863 {
4864 return false;
4865 }
4866
4867 switch (pname)
4868 {
4869 case GL_DELETE_STATUS:
4870 case GL_LINK_STATUS:
4871 case GL_VALIDATE_STATUS:
4872 case GL_INFO_LOG_LENGTH:
4873 case GL_ATTACHED_SHADERS:
4874 case GL_ACTIVE_ATTRIBUTES:
4875 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4876 case GL_ACTIVE_UNIFORMS:
4877 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4878 break;
4879
4880 case GL_PROGRAM_BINARY_LENGTH:
4881 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4882 {
4883 context->handleError(Error(GL_INVALID_ENUM,
4884 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4885 "GL_OES_get_program_binary or ES 3.0."));
4886 return false;
4887 }
4888 break;
4889
4890 case GL_ACTIVE_UNIFORM_BLOCKS:
4891 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4892 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4893 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4894 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4895 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4896 if (context->getClientMajorVersion() < 3)
4897 {
4898 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4899 return false;
4900 }
4901 break;
4902
4903 default:
4904 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4905 return false;
4906 }
4907
4908 return true;
4909}
4910
4911bool ValidateGetProgramivRobustANGLE(Context *context,
4912 GLuint program,
4913 GLenum pname,
4914 GLsizei bufSize,
4915 GLsizei *numParams)
4916{
4917 if (!ValidateRobustEntryPoint(context, bufSize))
4918 {
4919 return false;
4920 }
4921
4922 if (!ValidateGetProgramiv(context, program, pname, numParams))
4923 {
4924 return false;
4925 }
4926
4927 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4928 {
4929 return false;
4930 }
4931
4932 return true;
4933}
4934
Geoff Lang740d9022016-10-07 11:20:52 -04004935bool ValidateGetRenderbufferParameteriv(Context *context,
4936 GLenum target,
4937 GLenum pname,
4938 GLint *params)
4939{
4940 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4941}
4942
4943bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4944 GLenum target,
4945 GLenum pname,
4946 GLsizei bufSize,
4947 GLsizei *length,
4948 GLint *params)
4949{
4950 if (!ValidateRobustEntryPoint(context, bufSize))
4951 {
4952 return false;
4953 }
4954
4955 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4956 {
4957 return false;
4958 }
4959
4960 if (!ValidateRobustBufferSize(context, bufSize, *length))
4961 {
4962 return false;
4963 }
4964
4965 return true;
4966}
4967
Geoff Langd7d0ed32016-10-07 11:33:51 -04004968bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4969{
4970 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4971}
4972
4973bool ValidateGetShaderivRobustANGLE(Context *context,
4974 GLuint shader,
4975 GLenum pname,
4976 GLsizei bufSize,
4977 GLsizei *length,
4978 GLint *params)
4979{
4980 if (!ValidateRobustEntryPoint(context, bufSize))
4981 {
4982 return false;
4983 }
4984
4985 if (!ValidateGetShaderivBase(context, shader, pname, length))
4986 {
4987 return false;
4988 }
4989
4990 if (!ValidateRobustBufferSize(context, bufSize, *length))
4991 {
4992 return false;
4993 }
4994
4995 return true;
4996}
4997
Geoff Langc1984ed2016-10-07 12:41:00 -04004998bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4999{
5000 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5001}
5002
5003bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5004 GLenum target,
5005 GLenum pname,
5006 GLsizei bufSize,
5007 GLsizei *length,
5008 GLfloat *params)
5009{
5010 if (!ValidateRobustEntryPoint(context, bufSize))
5011 {
5012 return false;
5013 }
5014
5015 if (!ValidateGetTexParameterBase(context, target, pname, length))
5016 {
5017 return false;
5018 }
5019
5020 if (!ValidateRobustBufferSize(context, bufSize, *length))
5021 {
5022 return false;
5023 }
5024
5025 return true;
5026}
5027
5028bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5029{
5030 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5031}
5032
5033bool ValidateGetTexParameterivRobustANGLE(Context *context,
5034 GLenum target,
5035 GLenum pname,
5036 GLsizei bufSize,
5037 GLsizei *length,
5038 GLint *params)
5039{
5040 if (!ValidateRobustEntryPoint(context, bufSize))
5041 {
5042 return false;
5043 }
5044
5045 if (!ValidateGetTexParameterBase(context, target, pname, length))
5046 {
5047 return false;
5048 }
5049
5050 if (!ValidateRobustBufferSize(context, bufSize, *length))
5051 {
5052 return false;
5053 }
5054
5055 return true;
5056}
5057
5058bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5059{
5060 return ValidateTexParameterBase(context, target, pname, -1, &param);
5061}
5062
5063bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5064{
5065 return ValidateTexParameterBase(context, target, pname, -1, params);
5066}
5067
5068bool ValidateTexParameterfvRobustANGLE(Context *context,
5069 GLenum target,
5070 GLenum pname,
5071 GLsizei bufSize,
5072 const GLfloat *params)
5073{
5074 if (!ValidateRobustEntryPoint(context, bufSize))
5075 {
5076 return false;
5077 }
5078
5079 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5080}
5081
5082bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5083{
5084 return ValidateTexParameterBase(context, target, pname, -1, &param);
5085}
5086
5087bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5088{
5089 return ValidateTexParameterBase(context, target, pname, -1, params);
5090}
5091
5092bool ValidateTexParameterivRobustANGLE(Context *context,
5093 GLenum target,
5094 GLenum pname,
5095 GLsizei bufSize,
5096 const GLint *params)
5097{
5098 if (!ValidateRobustEntryPoint(context, bufSize))
5099 {
5100 return false;
5101 }
5102
5103 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5104}
5105
5106bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5107{
5108 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5109}
5110
5111bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5112 GLuint sampler,
5113 GLenum pname,
5114 GLuint bufSize,
5115 GLsizei *length,
5116 GLfloat *params)
5117{
5118 if (!ValidateRobustEntryPoint(context, bufSize))
5119 {
5120 return false;
5121 }
5122
5123 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5124 {
5125 return false;
5126 }
5127
5128 if (!ValidateRobustBufferSize(context, bufSize, *length))
5129 {
5130 return false;
5131 }
5132
5133 return true;
5134}
5135
5136bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5137{
5138 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5139}
5140
5141bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5142 GLuint sampler,
5143 GLenum pname,
5144 GLuint bufSize,
5145 GLsizei *length,
5146 GLint *params)
5147{
5148 if (!ValidateRobustEntryPoint(context, bufSize))
5149 {
5150 return false;
5151 }
5152
5153 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5154 {
5155 return false;
5156 }
5157
5158 if (!ValidateRobustBufferSize(context, bufSize, *length))
5159 {
5160 return false;
5161 }
5162
5163 return true;
5164}
5165
5166bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5167{
5168 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5169}
5170
5171bool ValidateSamplerParameterfv(Context *context,
5172 GLuint sampler,
5173 GLenum pname,
5174 const GLfloat *params)
5175{
5176 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5177}
5178
5179bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5180 GLuint sampler,
5181 GLenum pname,
5182 GLsizei bufSize,
5183 const GLfloat *params)
5184{
5185 if (!ValidateRobustEntryPoint(context, bufSize))
5186 {
5187 return false;
5188 }
5189
5190 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5191}
5192
5193bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5194{
5195 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5196}
5197
5198bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5199{
5200 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5201}
5202
5203bool ValidateSamplerParameterivRobustANGLE(Context *context,
5204 GLuint sampler,
5205 GLenum pname,
5206 GLsizei bufSize,
5207 const GLint *params)
5208{
5209 if (!ValidateRobustEntryPoint(context, bufSize))
5210 {
5211 return false;
5212 }
5213
5214 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5215}
5216
Geoff Lang0b031062016-10-13 14:30:04 -04005217bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5218{
5219 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5220}
5221
5222bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5223 GLuint index,
5224 GLenum pname,
5225 GLsizei bufSize,
5226 GLsizei *length,
5227 GLfloat *params)
5228{
5229 if (!ValidateRobustEntryPoint(context, bufSize))
5230 {
5231 return false;
5232 }
5233
5234 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5235 {
5236 return false;
5237 }
5238
5239 if (!ValidateRobustBufferSize(context, bufSize, *length))
5240 {
5241 return false;
5242 }
5243
5244 return true;
5245}
5246
5247bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5248{
5249 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5250}
5251
5252bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5253 GLuint index,
5254 GLenum pname,
5255 GLsizei bufSize,
5256 GLsizei *length,
5257 GLint *params)
5258{
5259 if (!ValidateRobustEntryPoint(context, bufSize))
5260 {
5261 return false;
5262 }
5263
5264 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5265 {
5266 return false;
5267 }
5268
5269 if (!ValidateRobustBufferSize(context, bufSize, *length))
5270 {
5271 return false;
5272 }
5273
5274 return true;
5275}
5276
5277bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5278{
5279 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5280}
5281
5282bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5283 GLuint index,
5284 GLenum pname,
5285 GLsizei bufSize,
5286 GLsizei *length,
5287 void **pointer)
5288{
5289 if (!ValidateRobustEntryPoint(context, bufSize))
5290 {
5291 return false;
5292 }
5293
5294 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5295 {
5296 return false;
5297 }
5298
5299 if (!ValidateRobustBufferSize(context, bufSize, *length))
5300 {
5301 return false;
5302 }
5303
5304 return true;
5305}
5306
5307bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5308{
5309 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5310}
5311
5312bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5313 GLuint index,
5314 GLenum pname,
5315 GLsizei bufSize,
5316 GLsizei *length,
5317 GLint *params)
5318{
5319 if (!ValidateRobustEntryPoint(context, bufSize))
5320 {
5321 return false;
5322 }
5323
5324 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5325 {
5326 return false;
5327 }
5328
5329 if (!ValidateRobustBufferSize(context, bufSize, *length))
5330 {
5331 return false;
5332 }
5333
5334 return true;
5335}
5336
5337bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5338{
5339 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5340}
5341
5342bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5343 GLuint index,
5344 GLenum pname,
5345 GLsizei bufSize,
5346 GLsizei *length,
5347 GLuint *params)
5348{
5349 if (!ValidateRobustEntryPoint(context, bufSize))
5350 {
5351 return false;
5352 }
5353
5354 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5355 {
5356 return false;
5357 }
5358
5359 if (!ValidateRobustBufferSize(context, bufSize, *length))
5360 {
5361 return false;
5362 }
5363
5364 return true;
5365}
5366
Geoff Lang6899b872016-10-14 11:30:13 -04005367bool ValidateGetActiveUniformBlockiv(Context *context,
5368 GLuint program,
5369 GLuint uniformBlockIndex,
5370 GLenum pname,
5371 GLint *params)
5372{
5373 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5374}
5375
5376bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5377 GLuint program,
5378 GLuint uniformBlockIndex,
5379 GLenum pname,
5380 GLsizei bufSize,
5381 GLsizei *length,
5382 GLint *params)
5383{
5384 if (!ValidateRobustEntryPoint(context, bufSize))
5385 {
5386 return false;
5387 }
5388
5389 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5390 {
5391 return false;
5392 }
5393
5394 if (!ValidateRobustBufferSize(context, bufSize, *length))
5395 {
5396 return false;
5397 }
5398
5399 return true;
5400}
5401
Geoff Lang0a9661f2016-10-20 10:59:20 -07005402bool ValidateGetInternalFormativ(Context *context,
5403 GLenum target,
5404 GLenum internalformat,
5405 GLenum pname,
5406 GLsizei bufSize,
5407 GLint *params)
5408{
5409 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5410 nullptr);
5411}
5412
5413bool ValidateGetInternalFormativRobustANGLE(Context *context,
5414 GLenum target,
5415 GLenum internalformat,
5416 GLenum pname,
5417 GLsizei bufSize,
5418 GLsizei *length,
5419 GLint *params)
5420{
5421 if (!ValidateRobustEntryPoint(context, bufSize))
5422 {
5423 return false;
5424 }
5425
5426 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5427 {
5428 return false;
5429 }
5430
5431 if (!ValidateRobustBufferSize(context, bufSize, *length))
5432 {
5433 return false;
5434 }
5435
5436 return true;
5437}
5438
Jamie Madillc29968b2016-01-20 11:17:23 -05005439} // namespace gl