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