blob: 06b0bb54cbf5b1b331726ce43b3d607239a02de0 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
165 default:
166 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500167 }
168}
169
Geoff Lang62fce5b2016-09-30 10:46:35 -0400170bool ValidateReadPixelsBase(ValidationContext *context,
171 GLint x,
172 GLint y,
173 GLsizei width,
174 GLsizei height,
175 GLenum format,
176 GLenum type,
177 GLsizei bufSize,
178 GLsizei *length,
179 GLvoid *pixels)
180{
181 if (length != nullptr)
182 {
183 *length = 0;
184 }
185
186 if (width < 0 || height < 0)
187 {
188 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
189 return false;
190 }
191
192 auto readFramebuffer = context->getGLState().getReadFramebuffer();
193
194 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
195 {
196 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
197 return false;
198 }
199
200 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
201 {
202 context->handleError(Error(GL_INVALID_OPERATION));
203 return false;
204 }
205
206 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
207 ASSERT(framebuffer);
208
209 if (framebuffer->getReadBufferState() == GL_NONE)
210 {
211 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
212 return false;
213 }
214
215 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
216 if (!readBuffer)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION));
219 return false;
220 }
221
222 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
223 GLenum currentType = framebuffer->getImplementationColorReadType();
224 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
225
226 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
227 bool validFormatTypeCombination =
228 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
229
230 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
231 {
232 context->handleError(Error(GL_INVALID_OPERATION));
233 return false;
234 }
235
236 // Check for pixel pack buffer related API errors
237 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
238 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
239 {
240 // ...the buffer object's data store is currently mapped.
241 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
242 return false;
243 }
244
245 // .. the data would be packed to the buffer object such that the memory writes required
246 // would exceed the data store size.
247 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
248 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
249 const gl::Extents size(width, height, 1);
250 const auto &pack = context->getGLState().getPackState();
251
252 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
253 if (endByteOrErr.isError())
254 {
255 context->handleError(endByteOrErr.getError());
256 return false;
257 }
258
259 size_t endByte = endByteOrErr.getResult();
260 if (bufSize >= 0)
261 {
262
263 if (static_cast<size_t>(bufSize) < endByte)
264 {
265 context->handleError(
266 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
267 return false;
268 }
269 }
270
271 if (pixelPackBuffer != nullptr)
272 {
273 CheckedNumeric<size_t> checkedEndByte(endByte);
274 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
275 checkedEndByte += checkedOffset;
276
277 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
278 {
279 // Overflow past the end of the buffer
280 context->handleError(
281 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
282 return false;
283 }
284 }
285
286 if (length != nullptr)
287 {
288 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
289 {
290 context->handleError(
291 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
292 return false;
293 }
294
295 *length = static_cast<GLsizei>(endByte);
296 }
297
298 return true;
299}
300
Geoff Lang740d9022016-10-07 11:20:52 -0400301bool ValidateGetRenderbufferParameterivBase(Context *context,
302 GLenum target,
303 GLenum pname,
304 GLsizei *length)
305{
306 if (length)
307 {
308 *length = 0;
309 }
310
311 if (target != GL_RENDERBUFFER)
312 {
313 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
314 return false;
315 }
316
317 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
318 if (renderbuffer == nullptr)
319 {
320 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
321 return false;
322 }
323
324 switch (pname)
325 {
326 case GL_RENDERBUFFER_WIDTH:
327 case GL_RENDERBUFFER_HEIGHT:
328 case GL_RENDERBUFFER_INTERNAL_FORMAT:
329 case GL_RENDERBUFFER_RED_SIZE:
330 case GL_RENDERBUFFER_GREEN_SIZE:
331 case GL_RENDERBUFFER_BLUE_SIZE:
332 case GL_RENDERBUFFER_ALPHA_SIZE:
333 case GL_RENDERBUFFER_DEPTH_SIZE:
334 case GL_RENDERBUFFER_STENCIL_SIZE:
335 break;
336
337 case GL_RENDERBUFFER_SAMPLES_ANGLE:
338 if (!context->getExtensions().framebufferMultisample)
339 {
340 context->handleError(
341 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
342 return false;
343 }
344 break;
345
346 default:
347 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
348 return false;
349 }
350
351 if (length)
352 {
353 *length = 1;
354 }
355 return true;
356}
357
Geoff Langd7d0ed32016-10-07 11:33:51 -0400358bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
359{
360 if (length)
361 {
362 *length = 0;
363 }
364
365 if (GetValidShader(context, shader) == nullptr)
366 {
367 return false;
368 }
369
370 switch (pname)
371 {
372 case GL_SHADER_TYPE:
373 case GL_DELETE_STATUS:
374 case GL_COMPILE_STATUS:
375 case GL_INFO_LOG_LENGTH:
376 case GL_SHADER_SOURCE_LENGTH:
377 break;
378
379 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
380 if (!context->getExtensions().translatedShaderSource)
381 {
382 context->handleError(
383 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
384 return false;
385 }
386 break;
387
388 default:
389 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
390 return false;
391 }
392
393 if (length)
394 {
395 *length = 1;
396 }
397 return true;
398}
399
Geoff Langc1984ed2016-10-07 12:41:00 -0400400bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
401{
402 if (length)
403 {
404 *length = 0;
405 }
406
407 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
408 {
409 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
410 return false;
411 }
412
413 if (context->getTargetTexture(target) == nullptr)
414 {
415 // Should only be possible for external textures
416 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
417 return false;
418 }
419
420 switch (pname)
421 {
422 case GL_TEXTURE_MAG_FILTER:
423 case GL_TEXTURE_MIN_FILTER:
424 case GL_TEXTURE_WRAP_S:
425 case GL_TEXTURE_WRAP_T:
426 break;
427
428 case GL_TEXTURE_USAGE_ANGLE:
429 if (!context->getExtensions().textureUsage)
430 {
431 context->handleError(
432 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
438 if (!context->getExtensions().textureFilterAnisotropic)
439 {
440 context->handleError(
441 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
442 return false;
443 }
444 break;
445
446 case GL_TEXTURE_IMMUTABLE_FORMAT:
447 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
448 {
449 context->handleError(
450 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
451 return false;
452 }
453 break;
454
455 case GL_TEXTURE_WRAP_R:
456 case GL_TEXTURE_IMMUTABLE_LEVELS:
457 case GL_TEXTURE_SWIZZLE_R:
458 case GL_TEXTURE_SWIZZLE_G:
459 case GL_TEXTURE_SWIZZLE_B:
460 case GL_TEXTURE_SWIZZLE_A:
461 case GL_TEXTURE_BASE_LEVEL:
462 case GL_TEXTURE_MAX_LEVEL:
463 case GL_TEXTURE_MIN_LOD:
464 case GL_TEXTURE_MAX_LOD:
465 case GL_TEXTURE_COMPARE_MODE:
466 case GL_TEXTURE_COMPARE_FUNC:
467 if (context->getClientMajorVersion() < 3)
468 {
469 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
470 return false;
471 }
472 break;
473
474 default:
475 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
476 return false;
477 }
478
479 if (length)
480 {
481 *length = 1;
482 }
483 return true;
484}
485
486template <typename ParamType>
487bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
488{
489 switch (ConvertToGLenum(params[0]))
490 {
491 case GL_CLAMP_TO_EDGE:
492 break;
493
494 case GL_REPEAT:
495 case GL_MIRRORED_REPEAT:
496 if (isExternalTextureTarget)
497 {
498 // OES_EGL_image_external specifies this error.
499 context->handleError(Error(
500 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
501 return false;
502 }
503 break;
504
505 default:
506 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
507 return false;
508 }
509
510 return true;
511}
512
513template <typename ParamType>
514bool ValidateTextureMinFilterValue(Context *context,
515 ParamType *params,
516 bool isExternalTextureTarget)
517{
518 switch (ConvertToGLenum(params[0]))
519 {
520 case GL_NEAREST:
521 case GL_LINEAR:
522 break;
523
524 case GL_NEAREST_MIPMAP_NEAREST:
525 case GL_LINEAR_MIPMAP_NEAREST:
526 case GL_NEAREST_MIPMAP_LINEAR:
527 case GL_LINEAR_MIPMAP_LINEAR:
528 if (isExternalTextureTarget)
529 {
530 // OES_EGL_image_external specifies this error.
531 context->handleError(
532 Error(GL_INVALID_ENUM,
533 "external textures only support NEAREST and LINEAR filtering"));
534 return false;
535 }
536 break;
537
538 default:
539 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
540 return false;
541 }
542
543 return true;
544}
545
546template <typename ParamType>
547bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
548{
549 switch (ConvertToGLenum(params[0]))
550 {
551 case GL_NEAREST:
552 case GL_LINEAR:
553 break;
554
555 default:
556 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
557 return false;
558 }
559
560 return true;
561}
562
563template <typename ParamType>
564bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
565{
566 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
567 switch (ConvertToGLenum(params[0]))
568 {
569 case GL_NONE:
570 case GL_COMPARE_REF_TO_TEXTURE:
571 break;
572
573 default:
574 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
575 return false;
576 }
577
578 return true;
579}
580
581template <typename ParamType>
582bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
583{
584 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
585 switch (ConvertToGLenum(params[0]))
586 {
587 case GL_LEQUAL:
588 case GL_GEQUAL:
589 case GL_LESS:
590 case GL_GREATER:
591 case GL_EQUAL:
592 case GL_NOTEQUAL:
593 case GL_ALWAYS:
594 case GL_NEVER:
595 break;
596
597 default:
598 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
599 return false;
600 }
601
602 return true;
603}
604
605template <typename ParamType>
606bool ValidateTexParameterBase(Context *context,
607 GLenum target,
608 GLenum pname,
609 GLsizei bufSize,
610 ParamType *params)
611{
612 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
613 {
614 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
615 return false;
616 }
617
618 if (context->getTargetTexture(target) == nullptr)
619 {
620 // Should only be possible for external textures
621 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
622 return false;
623 }
624
625 const GLsizei minBufSize = 1;
626 if (bufSize >= 0 && bufSize < minBufSize)
627 {
628 context->handleError(
629 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
630 return false;
631 }
632
633 switch (pname)
634 {
635 case GL_TEXTURE_WRAP_R:
636 case GL_TEXTURE_SWIZZLE_R:
637 case GL_TEXTURE_SWIZZLE_G:
638 case GL_TEXTURE_SWIZZLE_B:
639 case GL_TEXTURE_SWIZZLE_A:
640 case GL_TEXTURE_BASE_LEVEL:
641 case GL_TEXTURE_MAX_LEVEL:
642 case GL_TEXTURE_COMPARE_MODE:
643 case GL_TEXTURE_COMPARE_FUNC:
644 case GL_TEXTURE_MIN_LOD:
645 case GL_TEXTURE_MAX_LOD:
646 if (context->getClientMajorVersion() < 3)
647 {
648 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
649 return false;
650 }
651 if (target == GL_TEXTURE_EXTERNAL_OES &&
652 !context->getExtensions().eglImageExternalEssl3)
653 {
654 context->handleError(Error(GL_INVALID_ENUM,
655 "ES3 texture parameters are not available without "
656 "GL_OES_EGL_image_external_essl3."));
657 return false;
658 }
659 break;
660
661 default:
662 break;
663 }
664
665 switch (pname)
666 {
667 case GL_TEXTURE_WRAP_S:
668 case GL_TEXTURE_WRAP_T:
669 case GL_TEXTURE_WRAP_R:
670 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
671 {
672 return false;
673 }
674 break;
675
676 case GL_TEXTURE_MIN_FILTER:
677 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
678 {
679 return false;
680 }
681 break;
682
683 case GL_TEXTURE_MAG_FILTER:
684 if (!ValidateTextureMagFilterValue(context, params))
685 {
686 return false;
687 }
688 break;
689
690 case GL_TEXTURE_USAGE_ANGLE:
691 switch (ConvertToGLenum(params[0]))
692 {
693 case GL_NONE:
694 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
695 break;
696
697 default:
698 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
699 return false;
700 }
701 break;
702
703 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
704 if (!context->getExtensions().textureFilterAnisotropic)
705 {
706 context->handleError(
707 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
708 return false;
709 }
710
711 // we assume the parameter passed to this validation method is truncated, not rounded
712 if (params[0] < 1)
713 {
714 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
715 return false;
716 }
717 break;
718
719 case GL_TEXTURE_MIN_LOD:
720 case GL_TEXTURE_MAX_LOD:
721 // any value is permissible
722 break;
723
724 case GL_TEXTURE_COMPARE_MODE:
725 if (!ValidateTextureCompareModeValue(context, params))
726 {
727 return false;
728 }
729 break;
730
731 case GL_TEXTURE_COMPARE_FUNC:
732 if (!ValidateTextureCompareFuncValue(context, params))
733 {
734 return false;
735 }
736 break;
737
738 case GL_TEXTURE_SWIZZLE_R:
739 case GL_TEXTURE_SWIZZLE_G:
740 case GL_TEXTURE_SWIZZLE_B:
741 case GL_TEXTURE_SWIZZLE_A:
742 switch (ConvertToGLenum(params[0]))
743 {
744 case GL_RED:
745 case GL_GREEN:
746 case GL_BLUE:
747 case GL_ALPHA:
748 case GL_ZERO:
749 case GL_ONE:
750 break;
751
752 default:
753 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
754 return false;
755 }
756 break;
757
758 case GL_TEXTURE_BASE_LEVEL:
759 if (params[0] < 0)
760 {
761 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
762 return false;
763 }
764 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
765 {
766 context->handleError(
767 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
768 return false;
769 }
770 break;
771
772 case GL_TEXTURE_MAX_LEVEL:
773 if (params[0] < 0)
774 {
775 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
776 return false;
777 }
778 break;
779
780 default:
781 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
782 return false;
783 }
784
785 return true;
786}
787
788template <typename ParamType>
789bool ValidateSamplerParameterBase(Context *context,
790 GLuint sampler,
791 GLenum pname,
792 GLsizei bufSize,
793 ParamType *params)
794{
795 if (context->getClientMajorVersion() < 3)
796 {
797 context->handleError(
798 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
799 return false;
800 }
801
802 if (!context->isSampler(sampler))
803 {
804 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
805 return false;
806 }
807
808 const GLsizei minBufSize = 1;
809 if (bufSize >= 0 && bufSize < minBufSize)
810 {
811 context->handleError(
812 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
813 return false;
814 }
815
816 switch (pname)
817 {
818 case GL_TEXTURE_WRAP_S:
819 case GL_TEXTURE_WRAP_T:
820 case GL_TEXTURE_WRAP_R:
821 if (!ValidateTextureWrapModeValue(context, params, false))
822 {
823 return false;
824 }
825 break;
826
827 case GL_TEXTURE_MIN_FILTER:
828 if (!ValidateTextureMinFilterValue(context, params, false))
829 {
830 return false;
831 }
832 break;
833
834 case GL_TEXTURE_MAG_FILTER:
835 if (!ValidateTextureMagFilterValue(context, params))
836 {
837 return false;
838 }
839 break;
840
841 case GL_TEXTURE_MIN_LOD:
842 case GL_TEXTURE_MAX_LOD:
843 // any value is permissible
844 break;
845
846 case GL_TEXTURE_COMPARE_MODE:
847 if (!ValidateTextureCompareModeValue(context, params))
848 {
849 return false;
850 }
851 break;
852
853 case GL_TEXTURE_COMPARE_FUNC:
854 if (!ValidateTextureCompareFuncValue(context, params))
855 {
856 return false;
857 }
858 break;
859
860 default:
861 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
862 return false;
863 }
864
865 return true;
866}
867
868bool ValidateGetSamplerParameterBase(Context *context,
869 GLuint sampler,
870 GLenum pname,
871 GLsizei *length)
872{
873 if (length)
874 {
875 *length = 0;
876 }
877
878 if (context->getClientMajorVersion() < 3)
879 {
880 context->handleError(
881 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
882 return false;
883 }
884
885 if (!context->isSampler(sampler))
886 {
887 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
888 return false;
889 }
890
891 switch (pname)
892 {
893 case GL_TEXTURE_WRAP_S:
894 case GL_TEXTURE_WRAP_T:
895 case GL_TEXTURE_WRAP_R:
896 case GL_TEXTURE_MIN_FILTER:
897 case GL_TEXTURE_MAG_FILTER:
898 case GL_TEXTURE_MIN_LOD:
899 case GL_TEXTURE_MAX_LOD:
900 case GL_TEXTURE_COMPARE_MODE:
901 case GL_TEXTURE_COMPARE_FUNC:
902 break;
903
904 default:
905 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
906 return false;
907 }
908
909 if (length)
910 {
911 *length = 1;
912 }
913 return true;
914}
915
Geoff Lang0b031062016-10-13 14:30:04 -0400916bool ValidateGetVertexAttribBase(Context *context,
917 GLuint index,
918 GLenum pname,
919 GLsizei *length,
920 bool pointer,
921 bool pureIntegerEntryPoint)
922{
923 if (length)
924 {
925 *length = 0;
926 }
927
928 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
929 {
930 context->handleError(
931 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
932 return false;
933 }
934
935 if (index >= context->getCaps().maxVertexAttributes)
936 {
937 context->handleError(Error(
938 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
939 return false;
940 }
941
942 if (pointer)
943 {
944 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
945 {
946 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
947 return false;
948 }
949 }
950 else
951 {
952 switch (pname)
953 {
954 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
955 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
956 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
957 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
958 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
959 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
960 case GL_CURRENT_VERTEX_ATTRIB:
961 break;
962
963 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
964 static_assert(
965 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
966 "ANGLE extension enums not equal to GL enums.");
967 if (context->getClientMajorVersion() < 3 &&
968 !context->getExtensions().instancedArrays)
969 {
970 context->handleError(Error(GL_INVALID_ENUM,
971 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
972 "3.0 or GL_ANGLE_instanced_arrays."));
973 return false;
974 }
975 break;
976
977 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
978 if (context->getClientMajorVersion() < 3)
979 {
980 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
981 return false;
982 }
983 break;
984
985 default:
986 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
987 return false;
988 }
989 }
990
991 if (length)
992 {
993 if (pname == GL_CURRENT_VERTEX_ATTRIB)
994 {
995 *length = 4;
996 }
997 else
998 {
999 *length = 1;
1000 }
1001 }
1002
1003 return true;
1004}
1005
Geoff Lang6899b872016-10-14 11:30:13 -04001006bool ValidateGetActiveUniformBlockivBase(Context *context,
1007 GLuint program,
1008 GLuint uniformBlockIndex,
1009 GLenum pname,
1010 GLsizei *length)
1011{
1012 if (length)
1013 {
1014 *length = 0;
1015 }
1016
1017 if (context->getClientMajorVersion() < 3)
1018 {
1019 context->handleError(
1020 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1021 return false;
1022 }
1023
1024 Program *programObject = GetValidProgram(context, program);
1025 if (!programObject)
1026 {
1027 return false;
1028 }
1029
1030 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1031 {
1032 context->handleError(
1033 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1034 return false;
1035 }
1036
1037 switch (pname)
1038 {
1039 case GL_UNIFORM_BLOCK_BINDING:
1040 case GL_UNIFORM_BLOCK_DATA_SIZE:
1041 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1042 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1043 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1044 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1045 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1046 break;
1047
1048 default:
1049 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1050 return false;
1051 }
1052
1053 if (length)
1054 {
1055 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1056 {
1057 const UniformBlock &uniformBlock =
1058 programObject->getUniformBlockByIndex(uniformBlockIndex);
1059 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1060 }
1061 else
1062 {
1063 *length = 1;
1064 }
1065 }
1066
1067 return true;
1068}
1069
Geoff Langebebe1c2016-10-14 12:01:31 -04001070bool ValidateGetBufferParameterBase(ValidationContext *context,
1071 GLenum target,
1072 GLenum pname,
1073 bool pointerVersion,
1074 GLsizei *numParams)
1075{
1076 if (numParams)
1077 {
1078 *numParams = 0;
1079 }
1080
1081 if (!ValidBufferTarget(context, target))
1082 {
1083 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1084 return false;
1085 }
1086
1087 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1088 if (!buffer)
1089 {
1090 // A null buffer means that "0" is bound to the requested buffer target
1091 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1092 return false;
1093 }
1094
1095 const Extensions &extensions = context->getExtensions();
1096
1097 switch (pname)
1098 {
1099 case GL_BUFFER_USAGE:
1100 case GL_BUFFER_SIZE:
1101 break;
1102
1103 case GL_BUFFER_ACCESS_OES:
1104 if (!extensions.mapBuffer)
1105 {
1106 context->handleError(
1107 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1108 return false;
1109 }
1110 break;
1111
1112 case GL_BUFFER_MAPPED:
1113 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1114 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1115 !extensions.mapBufferRange)
1116 {
1117 context->handleError(Error(
1118 GL_INVALID_ENUM,
1119 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1120 return false;
1121 }
1122 break;
1123
1124 case GL_BUFFER_MAP_POINTER:
1125 if (!pointerVersion)
1126 {
1127 context->handleError(
1128 Error(GL_INVALID_ENUM,
1129 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1130 return false;
1131 }
1132 break;
1133
1134 case GL_BUFFER_ACCESS_FLAGS:
1135 case GL_BUFFER_MAP_OFFSET:
1136 case GL_BUFFER_MAP_LENGTH:
1137 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1138 {
1139 context->handleError(Error(
1140 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1141 return false;
1142 }
1143 break;
1144
1145 default:
1146 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1147 return false;
1148 }
1149
1150 // All buffer parameter queries return one value.
1151 if (numParams)
1152 {
1153 *numParams = 1;
1154 }
1155
1156 return true;
1157}
1158
Geoff Langf41a7152016-09-19 15:11:17 -04001159} // anonymous namespace
1160
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001161bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001162{
Jamie Madilld7460c72014-01-21 16:38:14 -05001163 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001164 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001165 case GL_TEXTURE_2D:
1166 case GL_TEXTURE_CUBE_MAP:
1167 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001168
Jamie Madilld7460c72014-01-21 16:38:14 -05001169 case GL_TEXTURE_3D:
1170 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001171 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001172
1173 default:
1174 return false;
1175 }
Jamie Madill35d15012013-10-07 10:46:37 -04001176}
1177
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001178bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1179{
1180 switch (target)
1181 {
1182 case GL_TEXTURE_2D:
1183 case GL_TEXTURE_CUBE_MAP:
1184 return true;
1185
1186 default:
1187 return false;
1188 }
1189}
1190
1191bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1192{
1193 switch (target)
1194 {
1195 case GL_TEXTURE_3D:
1196 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001197 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001198
1199 default:
1200 return false;
1201 }
1202}
1203
Ian Ewellbda75592016-04-18 17:25:54 -04001204// Most texture GL calls are not compatible with external textures, so we have a separate validation
1205// function for use in the GL calls that do
1206bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1207{
1208 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1209 (context->getExtensions().eglImageExternal ||
1210 context->getExtensions().eglStreamConsumerExternal);
1211}
1212
Shannon Woods4dfed832014-03-17 20:03:39 -04001213// This function differs from ValidTextureTarget in that the target must be
1214// usable as the destination of a 2D operation-- so a cube face is valid, but
1215// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001216// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001217bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001218{
1219 switch (target)
1220 {
1221 case GL_TEXTURE_2D:
1222 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1223 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1224 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1225 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1226 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1227 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1228 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001229 default:
1230 return false;
1231 }
1232}
1233
1234bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1235{
1236 switch (target)
1237 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001238 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001239 case GL_TEXTURE_2D_ARRAY:
1240 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001241 default:
1242 return false;
1243 }
1244}
1245
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001246bool ValidFramebufferTarget(GLenum target)
1247{
Geoff Langd4475812015-03-18 10:53:05 -04001248 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1249 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001250
1251 switch (target)
1252 {
1253 case GL_FRAMEBUFFER: return true;
1254 case GL_READ_FRAMEBUFFER: return true;
1255 case GL_DRAW_FRAMEBUFFER: return true;
1256 default: return false;
1257 }
1258}
1259
Jamie Madill29639852016-09-02 15:00:09 -04001260bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001261{
1262 switch (target)
1263 {
1264 case GL_ARRAY_BUFFER:
1265 case GL_ELEMENT_ARRAY_BUFFER:
1266 return true;
1267
Jamie Madill8c96d582014-03-05 15:01:23 -05001268 case GL_PIXEL_PACK_BUFFER:
1269 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001270 return (context->getExtensions().pixelBufferObject ||
1271 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001272
Shannon Woodsb3801742014-03-27 14:59:19 -04001273 case GL_COPY_READ_BUFFER:
1274 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001275 case GL_TRANSFORM_FEEDBACK_BUFFER:
1276 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001277 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001278
1279 default:
1280 return false;
1281 }
1282}
1283
Jamie Madillc29968b2016-01-20 11:17:23 -05001284bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001285{
Jamie Madillc29968b2016-01-20 11:17:23 -05001286 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001287 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001288 switch (target)
1289 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001290 case GL_TEXTURE_2D:
1291 maxDimension = caps.max2DTextureSize;
1292 break;
Geoff Langce635692013-09-24 13:56:32 -04001293 case GL_TEXTURE_CUBE_MAP:
1294 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1295 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1296 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1297 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1298 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001299 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1300 maxDimension = caps.maxCubeMapTextureSize;
1301 break;
1302 case GL_TEXTURE_3D:
1303 maxDimension = caps.max3DTextureSize;
1304 break;
1305 case GL_TEXTURE_2D_ARRAY:
1306 maxDimension = caps.max2DTextureSize;
1307 break;
Geoff Langce635692013-09-24 13:56:32 -04001308 default: UNREACHABLE();
1309 }
1310
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001311 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001312}
1313
Austin Kinross08528e12015-10-07 16:24:40 -07001314bool ValidImageSizeParameters(const Context *context,
1315 GLenum target,
1316 GLint level,
1317 GLsizei width,
1318 GLsizei height,
1319 GLsizei depth,
1320 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001321{
1322 if (level < 0 || width < 0 || height < 0 || depth < 0)
1323 {
1324 return false;
1325 }
1326
Austin Kinross08528e12015-10-07 16:24:40 -07001327 // TexSubImage parameters can be NPOT without textureNPOT extension,
1328 // as long as the destination texture is POT.
1329 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001330 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001331 {
1332 return false;
1333 }
1334
1335 if (!ValidMipLevel(context, target, level))
1336 {
1337 return false;
1338 }
1339
1340 return true;
1341}
1342
Geoff Lang0d8b7242015-09-09 14:56:53 -04001343bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1344{
1345 // List of compressed format that require that the texture size is smaller than or a multiple of
1346 // the compressed block size.
1347 switch (internalFormat)
1348 {
1349 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1350 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1351 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1352 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001353 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001354 return true;
1355
1356 default:
1357 return false;
1358 }
1359}
1360
Jamie Madillc29968b2016-01-20 11:17:23 -05001361bool ValidCompressedImageSize(const ValidationContext *context,
1362 GLenum internalFormat,
1363 GLsizei width,
1364 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001365{
Geoff Lang5d601382014-07-22 15:14:06 -04001366 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1367 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001368 {
1369 return false;
1370 }
1371
Geoff Lang0d8b7242015-09-09 14:56:53 -04001372 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001373 {
1374 return false;
1375 }
1376
Geoff Lang0d8b7242015-09-09 14:56:53 -04001377 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1378 {
1379 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1380 width % formatInfo.compressedBlockWidth != 0) ||
1381 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1382 height % formatInfo.compressedBlockHeight != 0))
1383 {
1384 return false;
1385 }
1386 }
1387
Geoff Langd4f180b2013-09-24 13:57:44 -04001388 return true;
1389}
1390
Geoff Langff5b2d52016-09-07 11:32:23 -04001391bool ValidImageDataSize(ValidationContext *context,
1392 GLenum textureTarget,
1393 GLsizei width,
1394 GLsizei height,
1395 GLsizei depth,
1396 GLenum internalFormat,
1397 GLenum type,
1398 const GLvoid *pixels,
1399 GLsizei imageSize)
1400{
1401 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1402 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1403 {
1404 // Checks are not required
1405 return true;
1406 }
1407
1408 // ...the data would be unpacked from the buffer object such that the memory reads required
1409 // would exceed the data store size.
1410 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1411 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1412 const gl::Extents size(width, height, depth);
1413 const auto &unpack = context->getGLState().getUnpackState();
1414
1415 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1416 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1417 if (endByteOrErr.isError())
1418 {
1419 context->handleError(endByteOrErr.getError());
1420 return false;
1421 }
1422
1423 GLuint endByte = endByteOrErr.getResult();
1424
1425 if (pixelUnpackBuffer)
1426 {
1427 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1428 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1429 checkedEndByte += checkedOffset;
1430
1431 if (!checkedEndByte.IsValid() ||
1432 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1433 {
1434 // Overflow past the end of the buffer
1435 context->handleError(Error(GL_INVALID_OPERATION));
1436 return false;
1437 }
1438 }
1439 else
1440 {
1441 ASSERT(imageSize >= 0);
1442 if (pixels == nullptr && imageSize != 0)
1443 {
1444 context->handleError(
1445 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1446 }
1447
1448 if (endByte > static_cast<GLuint>(imageSize))
1449 {
1450 context->handleError(
1451 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1452 return false;
1453 }
1454 }
1455
1456 return true;
1457}
1458
Geoff Lang37dde692014-01-31 16:34:54 -05001459bool ValidQueryType(const Context *context, GLenum queryType)
1460{
Geoff Langd4475812015-03-18 10:53:05 -04001461 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1462 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 -05001463
1464 switch (queryType)
1465 {
1466 case GL_ANY_SAMPLES_PASSED:
1467 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1468 return true;
1469 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001470 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001471 case GL_TIME_ELAPSED_EXT:
1472 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001473 case GL_COMMANDS_COMPLETED_CHROMIUM:
1474 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001475 default:
1476 return false;
1477 }
1478}
1479
Jamie Madillef300b12016-10-07 15:12:09 -04001480Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001481{
1482 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1483 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1484 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1485
Dian Xiang769769a2015-09-09 15:20:08 -07001486 Program *validProgram = context->getProgram(id);
1487
1488 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001489 {
Dian Xiang769769a2015-09-09 15:20:08 -07001490 if (context->getShader(id))
1491 {
Jamie Madill437fa652016-05-03 15:13:24 -04001492 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001493 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1494 }
1495 else
1496 {
Jamie Madill437fa652016-05-03 15:13:24 -04001497 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001498 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001499 }
Dian Xiang769769a2015-09-09 15:20:08 -07001500
1501 return validProgram;
1502}
1503
Jamie Madillef300b12016-10-07 15:12:09 -04001504Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001505{
1506 // See ValidProgram for spec details.
1507
1508 Shader *validShader = context->getShader(id);
1509
1510 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001511 {
Dian Xiang769769a2015-09-09 15:20:08 -07001512 if (context->getProgram(id))
1513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001515 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1516 }
1517 else
1518 {
Jamie Madill437fa652016-05-03 15:13:24 -04001519 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001520 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001521 }
Dian Xiang769769a2015-09-09 15:20:08 -07001522
1523 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001524}
1525
Geoff Langb1196682014-07-23 13:47:29 -04001526bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001527{
1528 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1529 {
1530 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1531
Geoff Langaae65a42014-05-26 12:43:44 -04001532 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001533 {
Jamie Madill437fa652016-05-03 15:13:24 -04001534 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001535 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001536 }
1537 }
1538 else
1539 {
1540 switch (attachment)
1541 {
1542 case GL_DEPTH_ATTACHMENT:
1543 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001544 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001545
1546 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001547 if (!context->getExtensions().webglCompatibility &&
1548 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001549 {
1550 context->handleError(Error(GL_INVALID_ENUM));
1551 return false;
1552 }
1553 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001554
1555 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001556 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001557 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001558 }
1559 }
1560
1561 return true;
1562}
1563
Corentin Walleze0902642014-11-04 12:32:15 -08001564bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1565 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001566{
1567 switch (target)
1568 {
1569 case GL_RENDERBUFFER:
1570 break;
1571 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001572 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001574 }
1575
1576 if (width < 0 || height < 0 || samples < 0)
1577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001579 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001580 }
1581
Geoff Langd87878e2014-09-19 15:42:59 -04001582 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1583 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001584 {
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001586 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001587 }
1588
1589 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1590 // 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 -08001591 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001592 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001593 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001594 {
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001596 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001597 }
1598
Geoff Langaae65a42014-05-26 12:43:44 -04001599 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001602 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001603 }
1604
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001605 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 if (handle == 0)
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001609 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001610 }
1611
1612 return true;
1613}
1614
Corentin Walleze0902642014-11-04 12:32:15 -08001615bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1616 GLenum internalformat, GLsizei width, GLsizei height)
1617{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001618 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001619
1620 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001621 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001622 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001623 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001624 {
Jamie Madill437fa652016-05-03 15:13:24 -04001625 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001626 return false;
1627 }
1628
1629 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1630 // the specified storage. This is different than ES 3.0 in which a sample number higher
1631 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001632 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001633 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001634 {
Geoff Langa4903b72015-03-02 16:02:48 -08001635 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1636 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1637 {
Jamie Madill437fa652016-05-03 15:13:24 -04001638 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001639 return false;
1640 }
Corentin Walleze0902642014-11-04 12:32:15 -08001641 }
1642
1643 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1644}
1645
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001646bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1647 GLenum renderbuffertarget, GLuint renderbuffer)
1648{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001649 if (!ValidFramebufferTarget(target))
1650 {
Jamie Madill437fa652016-05-03 15:13:24 -04001651 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001652 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001653 }
1654
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001655 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001656
Jamie Madill84115c92015-04-23 15:00:07 -04001657 ASSERT(framebuffer);
1658 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001659 {
Jamie Madill437fa652016-05-03 15:13:24 -04001660 context->handleError(
1661 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001662 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001663 }
1664
Jamie Madillb4472272014-07-03 10:38:55 -04001665 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001666 {
Jamie Madillb4472272014-07-03 10:38:55 -04001667 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001668 }
1669
Jamie Madillab9d82c2014-01-21 16:38:14 -05001670 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1671 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1672 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1673 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1674 if (renderbuffer != 0)
1675 {
1676 if (!context->getRenderbuffer(renderbuffer))
1677 {
Jamie Madill437fa652016-05-03 15:13:24 -04001678 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001679 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001680 }
1681 }
1682
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001683 return true;
1684}
1685
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001686bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001687 GLint srcX0,
1688 GLint srcY0,
1689 GLint srcX1,
1690 GLint srcY1,
1691 GLint dstX0,
1692 GLint dstY0,
1693 GLint dstX1,
1694 GLint dstY1,
1695 GLbitfield mask,
1696 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001697{
1698 switch (filter)
1699 {
1700 case GL_NEAREST:
1701 break;
1702 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001703 break;
1704 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001705 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001706 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001707 }
1708
1709 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001712 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001713 }
1714
1715 if (mask == 0)
1716 {
1717 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1718 // buffers are copied.
1719 return false;
1720 }
1721
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1723 // color buffer, leaving only nearest being unfiltered from above
1724 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1725 {
Jamie Madill437fa652016-05-03 15:13:24 -04001726 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001727 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 }
1729
Jamie Madill51f40ec2016-06-15 14:06:00 -04001730 const auto &glState = context->getGLState();
1731 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1732 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001733
1734 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Jamie Madill437fa652016-05-03 15:13:24 -04001736 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001737 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001738 }
1739
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001740 if (readFramebuffer->id() == drawFramebuffer->id())
1741 {
1742 context->handleError(Error(GL_INVALID_OPERATION));
1743 return false;
1744 }
1745
Jamie Madill51f40ec2016-06-15 14:06:00 -04001746 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001747 {
Jamie Madill437fa652016-05-03 15:13:24 -04001748 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001749 return false;
1750 }
1751
Jamie Madill51f40ec2016-06-15 14:06:00 -04001752 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001753 {
Jamie Madill437fa652016-05-03 15:13:24 -04001754 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001755 return false;
1756 }
1757
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001758 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001761 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001762 }
1763
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001764 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1765
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001766 if (mask & GL_COLOR_BUFFER_BIT)
1767 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001768 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1769 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001770 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001771
1772 if (readColorBuffer && drawColorBuffer)
1773 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001774 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775
Geoff Langa15472a2015-08-11 11:48:03 -04001776 for (size_t drawbufferIdx = 0;
1777 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001778 {
Geoff Langa15472a2015-08-11 11:48:03 -04001779 const FramebufferAttachment *attachment =
1780 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1781 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001783 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784
Geoff Langb2f3d052013-08-13 12:49:27 -04001785 // The GL ES 3.0.2 spec (pg 193) states that:
1786 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1787 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1788 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001789 // Changes with EXT_color_buffer_float:
1790 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001791 GLenum readComponentType = readFormat.info->componentType;
1792 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001793 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1794 readComponentType == GL_SIGNED_NORMALIZED);
1795 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1796 drawComponentType == GL_SIGNED_NORMALIZED);
1797
1798 if (extensions.colorBufferFloat)
1799 {
1800 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1801 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1802
1803 if (readFixedOrFloat != drawFixedOrFloat)
1804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001806 "If the read buffer contains fixed-point or "
1807 "floating-point values, the draw buffer "
1808 "must as well."));
1809 return false;
1810 }
1811 }
1812 else if (readFixedPoint != drawFixedPoint)
1813 {
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001815 "If the read buffer contains fixed-point "
1816 "values, the draw buffer must as well."));
1817 return false;
1818 }
1819
1820 if (readComponentType == GL_UNSIGNED_INT &&
1821 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001822 {
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001824 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001825 }
1826
Jamie Madill6163c752015-12-07 16:32:59 -05001827 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001830 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001831 }
1832
Jamie Madilla3944d42016-07-22 22:13:26 -04001833 if (readColorBuffer->getSamples() > 0 &&
1834 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001835 {
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001838 }
1839 }
1840 }
1841
Jamie Madilla3944d42016-07-22 22:13:26 -04001842 if ((readFormat.info->componentType == GL_INT ||
1843 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1844 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001845 {
Jamie Madill437fa652016-05-03 15:13:24 -04001846 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001847 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001848 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001849 }
1850 }
1851
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001852 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1853 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1854 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001855 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001856 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001857 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001858 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1859 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001860
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001861 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001862 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001863 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001864 {
Jamie Madill437fa652016-05-03 15:13:24 -04001865 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001866 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001867 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001868
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001869 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001870 {
Jamie Madill437fa652016-05-03 15:13:24 -04001871 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001872 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001873 }
1874 }
1875 }
1876 }
1877
1878 return true;
1879}
1880
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001881bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001882 GLint x,
1883 GLint y,
1884 GLsizei width,
1885 GLsizei height,
1886 GLenum format,
1887 GLenum type,
1888 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001889{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001890 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1891}
1892
1893bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1894 GLint x,
1895 GLint y,
1896 GLsizei width,
1897 GLsizei height,
1898 GLenum format,
1899 GLenum type,
1900 GLsizei bufSize,
1901 GLsizei *length,
1902 GLvoid *pixels)
1903{
1904 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001905 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001906 return false;
1907 }
1908
Geoff Lang62fce5b2016-09-30 10:46:35 -04001909 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1910 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001911 {
Geoff Langb1196682014-07-23 13:47:29 -04001912 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001913 }
1914
Geoff Lang62fce5b2016-09-30 10:46:35 -04001915 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001916 {
Geoff Langb1196682014-07-23 13:47:29 -04001917 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001918 }
1919
Jamie Madillc29968b2016-01-20 11:17:23 -05001920 return true;
1921}
1922
1923bool ValidateReadnPixelsEXT(Context *context,
1924 GLint x,
1925 GLint y,
1926 GLsizei width,
1927 GLsizei height,
1928 GLenum format,
1929 GLenum type,
1930 GLsizei bufSize,
1931 GLvoid *pixels)
1932{
1933 if (bufSize < 0)
1934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001936 return false;
1937 }
1938
Geoff Lang62fce5b2016-09-30 10:46:35 -04001939 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1940 pixels);
1941}
Jamie Madill26e91952014-03-05 15:01:27 -05001942
Geoff Lang62fce5b2016-09-30 10:46:35 -04001943bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1944 GLint x,
1945 GLint y,
1946 GLsizei width,
1947 GLsizei height,
1948 GLenum format,
1949 GLenum type,
1950 GLsizei bufSize,
1951 GLsizei *length,
1952 GLvoid *data)
1953{
1954 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001955 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001956 return false;
1957 }
1958
Geoff Lang62fce5b2016-09-30 10:46:35 -04001959 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001960 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001961 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001962 }
1963
Geoff Lang62fce5b2016-09-30 10:46:35 -04001964 if (!ValidateRobustBufferSize(context, bufSize, *length))
1965 {
1966 return false;
1967 }
1968
1969 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001970}
1971
Olli Etuaho41997e72016-03-10 13:38:39 +02001972bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001973{
1974 if (!context->getExtensions().occlusionQueryBoolean &&
1975 !context->getExtensions().disjointTimerQuery)
1976 {
Jamie Madill437fa652016-05-03 15:13:24 -04001977 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001978 return false;
1979 }
1980
Olli Etuaho41997e72016-03-10 13:38:39 +02001981 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001982}
1983
Olli Etuaho41997e72016-03-10 13:38:39 +02001984bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985{
1986 if (!context->getExtensions().occlusionQueryBoolean &&
1987 !context->getExtensions().disjointTimerQuery)
1988 {
Jamie Madill437fa652016-05-03 15:13:24 -04001989 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001990 return false;
1991 }
1992
Olli Etuaho41997e72016-03-10 13:38:39 +02001993 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001994}
1995
1996bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001997{
1998 if (!ValidQueryType(context, target))
1999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002001 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002002 }
2003
2004 if (id == 0)
2005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002007 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002008 }
2009
2010 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2011 // of zero, if the active query object name for <target> is non-zero (for the
2012 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2013 // the active query for either target is non-zero), if <id> is the name of an
2014 // existing query object whose type does not match <target>, or if <id> is the
2015 // active query object name for any query type, the error INVALID_OPERATION is
2016 // generated.
2017
2018 // Ensure no other queries are active
2019 // NOTE: If other queries than occlusion are supported, we will need to check
2020 // separately that:
2021 // a) The query ID passed is not the current active query for any target/type
2022 // b) There are no active queries for the requested target (and in the case
2023 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2024 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002025
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002026 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002029 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002030 }
2031
2032 Query *queryObject = context->getQuery(id, true, target);
2033
2034 // check that name was obtained with glGenQueries
2035 if (!queryObject)
2036 {
Jamie Madill437fa652016-05-03 15:13:24 -04002037 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002038 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002039 }
2040
2041 // check for type mismatch
2042 if (queryObject->getType() != target)
2043 {
Jamie Madill437fa652016-05-03 15:13:24 -04002044 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002045 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002046 }
2047
2048 return true;
2049}
2050
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002051bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2052{
2053 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002054 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
2059
2060 return ValidateBeginQueryBase(context, target, id);
2061}
2062
2063bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002064{
2065 if (!ValidQueryType(context, target))
2066 {
Jamie Madill437fa652016-05-03 15:13:24 -04002067 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002068 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002069 }
2070
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002071 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002072
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002073 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002074 {
Jamie Madill437fa652016-05-03 15:13:24 -04002075 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002076 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002077 }
2078
Jamie Madill45c785d2014-05-13 14:09:34 -04002079 return true;
2080}
2081
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002082bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2083{
2084 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002085 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002086 {
Jamie Madill437fa652016-05-03 15:13:24 -04002087 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002088 return false;
2089 }
2090
2091 return ValidateEndQueryBase(context, target);
2092}
2093
2094bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2095{
2096 if (!context->getExtensions().disjointTimerQuery)
2097 {
Jamie Madill437fa652016-05-03 15:13:24 -04002098 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002099 return false;
2100 }
2101
2102 if (target != GL_TIMESTAMP_EXT)
2103 {
Jamie Madill437fa652016-05-03 15:13:24 -04002104 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002105 return false;
2106 }
2107
2108 Query *queryObject = context->getQuery(id, true, target);
2109 if (queryObject == nullptr)
2110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002112 return false;
2113 }
2114
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002115 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002116 {
Jamie Madill437fa652016-05-03 15:13:24 -04002117 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002118 return false;
2119 }
2120
2121 return true;
2122}
2123
Geoff Lang2186c382016-10-14 10:54:54 -04002124bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125{
Geoff Lang2186c382016-10-14 10:54:54 -04002126 if (numParams)
2127 {
2128 *numParams = 0;
2129 }
2130
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002131 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2132 {
Jamie Madill437fa652016-05-03 15:13:24 -04002133 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002134 return false;
2135 }
2136
2137 switch (pname)
2138 {
2139 case GL_CURRENT_QUERY_EXT:
2140 if (target == GL_TIMESTAMP_EXT)
2141 {
Jamie Madill437fa652016-05-03 15:13:24 -04002142 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002143 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2144 return false;
2145 }
2146 break;
2147 case GL_QUERY_COUNTER_BITS_EXT:
2148 if (!context->getExtensions().disjointTimerQuery ||
2149 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2150 {
Jamie Madill437fa652016-05-03 15:13:24 -04002151 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002152 return false;
2153 }
2154 break;
2155 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002157 return false;
2158 }
2159
Geoff Lang2186c382016-10-14 10:54:54 -04002160 if (numParams)
2161 {
2162 // All queries return only one value
2163 *numParams = 1;
2164 }
2165
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002166 return true;
2167}
2168
2169bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2170{
2171 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002172 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002173 {
Jamie Madill437fa652016-05-03 15:13:24 -04002174 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002175 return false;
2176 }
2177
Geoff Lang2186c382016-10-14 10:54:54 -04002178 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002179}
2180
Geoff Lang2186c382016-10-14 10:54:54 -04002181bool ValidateGetQueryivRobustANGLE(Context *context,
2182 GLenum target,
2183 GLenum pname,
2184 GLsizei bufSize,
2185 GLsizei *length,
2186 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002187{
Geoff Lang2186c382016-10-14 10:54:54 -04002188 if (!ValidateRobustEntryPoint(context, bufSize))
2189 {
2190 return false;
2191 }
2192
2193 if (!ValidateGetQueryivBase(context, target, pname, length))
2194 {
2195 return false;
2196 }
2197
2198 if (!ValidateRobustBufferSize(context, bufSize, *length))
2199 {
2200 return false;
2201 }
2202
2203 return true;
2204}
2205
2206bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2207{
2208 if (numParams)
2209 {
2210 *numParams = 0;
2211 }
2212
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002213 Query *queryObject = context->getQuery(id, false, GL_NONE);
2214
2215 if (!queryObject)
2216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002218 return false;
2219 }
2220
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002221 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002222 {
Jamie Madill437fa652016-05-03 15:13:24 -04002223 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002224 return false;
2225 }
2226
2227 switch (pname)
2228 {
2229 case GL_QUERY_RESULT_EXT:
2230 case GL_QUERY_RESULT_AVAILABLE_EXT:
2231 break;
2232
2233 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002234 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002235 return false;
2236 }
2237
Geoff Lang2186c382016-10-14 10:54:54 -04002238 if (numParams)
2239 {
2240 *numParams = 1;
2241 }
2242
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002243 return true;
2244}
2245
2246bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2247{
2248 if (!context->getExtensions().disjointTimerQuery)
2249 {
Jamie Madill437fa652016-05-03 15:13:24 -04002250 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002251 return false;
2252 }
Geoff Lang2186c382016-10-14 10:54:54 -04002253 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2254}
2255
2256bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2257 GLuint id,
2258 GLenum pname,
2259 GLsizei bufSize,
2260 GLsizei *length,
2261 GLint *params)
2262{
2263 if (!context->getExtensions().disjointTimerQuery)
2264 {
2265 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2266 return false;
2267 }
2268
2269 if (!ValidateRobustEntryPoint(context, bufSize))
2270 {
2271 return false;
2272 }
2273
2274 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2275 {
2276 return false;
2277 }
2278
2279 if (!ValidateRobustBufferSize(context, bufSize, *length))
2280 {
2281 return false;
2282 }
2283
2284 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002285}
2286
2287bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2288{
2289 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002290 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
Geoff Lang2186c382016-10-14 10:54:54 -04002295 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2296}
2297
2298bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2299 GLuint id,
2300 GLenum pname,
2301 GLsizei bufSize,
2302 GLsizei *length,
2303 GLuint *params)
2304{
2305 if (!context->getExtensions().disjointTimerQuery &&
2306 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2307 {
2308 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2309 return false;
2310 }
2311
2312 if (!ValidateRobustEntryPoint(context, bufSize))
2313 {
2314 return false;
2315 }
2316
2317 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2318 {
2319 return false;
2320 }
2321
2322 if (!ValidateRobustBufferSize(context, bufSize, *length))
2323 {
2324 return false;
2325 }
2326
2327 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002328}
2329
2330bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2331{
2332 if (!context->getExtensions().disjointTimerQuery)
2333 {
Jamie Madill437fa652016-05-03 15:13:24 -04002334 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002335 return false;
2336 }
Geoff Lang2186c382016-10-14 10:54:54 -04002337 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2338}
2339
2340bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2341 GLuint id,
2342 GLenum pname,
2343 GLsizei bufSize,
2344 GLsizei *length,
2345 GLint64 *params)
2346{
2347 if (!context->getExtensions().disjointTimerQuery)
2348 {
2349 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2350 return false;
2351 }
2352
2353 if (!ValidateRobustEntryPoint(context, bufSize))
2354 {
2355 return false;
2356 }
2357
2358 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2359 {
2360 return false;
2361 }
2362
2363 if (!ValidateRobustBufferSize(context, bufSize, *length))
2364 {
2365 return false;
2366 }
2367
2368 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002369}
2370
2371bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2372{
2373 if (!context->getExtensions().disjointTimerQuery)
2374 {
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002376 return false;
2377 }
Geoff Lang2186c382016-10-14 10:54:54 -04002378 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2379}
2380
2381bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2382 GLuint id,
2383 GLenum pname,
2384 GLsizei bufSize,
2385 GLsizei *length,
2386 GLuint64 *params)
2387{
2388 if (!context->getExtensions().disjointTimerQuery)
2389 {
2390 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2391 return false;
2392 }
2393
2394 if (!ValidateRobustEntryPoint(context, bufSize))
2395 {
2396 return false;
2397 }
2398
2399 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2400 {
2401 return false;
2402 }
2403
2404 if (!ValidateRobustBufferSize(context, bufSize, *length))
2405 {
2406 return false;
2407 }
2408
2409 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002410}
2411
Jamie Madill62d31cb2015-09-11 13:25:51 -04002412static bool ValidateUniformCommonBase(gl::Context *context,
2413 GLenum targetUniformType,
2414 GLint location,
2415 GLsizei count,
2416 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002417{
2418 if (count < 0)
2419 {
Jamie Madill437fa652016-05-03 15:13:24 -04002420 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002422 }
2423
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002424 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002425 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002426 {
Jamie Madill437fa652016-05-03 15:13:24 -04002427 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002429 }
2430
Geoff Langd8605522016-04-13 10:19:12 -04002431 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002432 {
2433 // Silently ignore the uniform command
2434 return false;
2435 }
2436
Geoff Lang7dd2e102014-11-10 15:19:26 -05002437 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002441 }
2442
Jamie Madill62d31cb2015-09-11 13:25:51 -04002443 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002444
2445 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002446 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002447 {
Jamie Madill437fa652016-05-03 15:13:24 -04002448 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002449 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002450 }
2451
Jamie Madill62d31cb2015-09-11 13:25:51 -04002452 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002453 return true;
2454}
2455
Jamie Madillaa981bd2014-05-20 10:55:55 -04002456bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2457{
2458 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002459 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2460 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002461 {
Jamie Madill437fa652016-05-03 15:13:24 -04002462 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002463 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002464 }
2465
Jamie Madill62d31cb2015-09-11 13:25:51 -04002466 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002467 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2468 {
2469 return false;
2470 }
2471
Jamie Madillf2575982014-06-25 16:04:54 -04002472 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002473 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002474 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002478 }
2479
2480 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002481}
2482
2483bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2484 GLboolean transpose)
2485{
2486 // Check for ES3 uniform entry points
2487 int rows = VariableRowCount(matrixType);
2488 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002489 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002490 {
Jamie Madill437fa652016-05-03 15:13:24 -04002491 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002492 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002493 }
2494
Martin Radev1be913c2016-07-11 17:59:16 +03002495 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002498 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002499 }
2500
Jamie Madill62d31cb2015-09-11 13:25:51 -04002501 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002502 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2503 {
2504 return false;
2505 }
2506
2507 if (uniform->type != matrixType)
2508 {
Jamie Madill437fa652016-05-03 15:13:24 -04002509 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002510 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002511 }
2512
2513 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002514}
2515
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002516bool ValidateStateQuery(ValidationContext *context,
2517 GLenum pname,
2518 GLenum *nativeType,
2519 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002520{
2521 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2522 {
Jamie Madill437fa652016-05-03 15:13:24 -04002523 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002524 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002525 }
2526
Jamie Madill0af26e12015-03-05 19:54:33 -05002527 const Caps &caps = context->getCaps();
2528
Jamie Madill893ab082014-05-16 16:56:10 -04002529 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2530 {
2531 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2532
Jamie Madill0af26e12015-03-05 19:54:33 -05002533 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002534 {
Jamie Madill437fa652016-05-03 15:13:24 -04002535 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002536 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002537 }
2538 }
2539
2540 switch (pname)
2541 {
2542 case GL_TEXTURE_BINDING_2D:
2543 case GL_TEXTURE_BINDING_CUBE_MAP:
2544 case GL_TEXTURE_BINDING_3D:
2545 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002546 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002547 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002548 if (!context->getExtensions().eglStreamConsumerExternal &&
2549 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002550 {
John Bauman18319182016-09-28 14:22:27 -07002551 context->handleError(Error(GL_INVALID_ENUM,
2552 "Neither NV_EGL_stream_consumer_external nor "
2553 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002554 return false;
2555 }
2556 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002557
2558 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2559 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2560 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002561 if (context->getGLState().getReadFramebuffer()->checkStatus(
2562 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002563 {
Jamie Madill437fa652016-05-03 15:13:24 -04002564 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002565 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002566 }
2567
Jamie Madill51f40ec2016-06-15 14:06:00 -04002568 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2569 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002570
2571 if (framebuffer->getReadBufferState() == GL_NONE)
2572 {
2573 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2574 return false;
2575 }
2576
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002577 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002578 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002579 {
Jamie Madill437fa652016-05-03 15:13:24 -04002580 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002581 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002582 }
2583 }
2584 break;
2585
2586 default:
2587 break;
2588 }
2589
2590 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002591 if (*numParams == 0)
2592 {
2593 return false;
2594 }
2595
2596 return true;
2597}
2598
2599bool ValidateRobustStateQuery(ValidationContext *context,
2600 GLenum pname,
2601 GLsizei bufSize,
2602 GLenum *nativeType,
2603 unsigned int *numParams)
2604{
2605 if (!ValidateRobustEntryPoint(context, bufSize))
2606 {
2607 return false;
2608 }
2609
2610 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2611 {
2612 return false;
2613 }
2614
2615 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002616 {
2617 return false;
2618 }
2619
2620 return true;
2621}
2622
Jamie Madillc29968b2016-01-20 11:17:23 -05002623bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2624 GLenum target,
2625 GLint level,
2626 GLenum internalformat,
2627 bool isSubImage,
2628 GLint xoffset,
2629 GLint yoffset,
2630 GLint zoffset,
2631 GLint x,
2632 GLint y,
2633 GLsizei width,
2634 GLsizei height,
2635 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002636 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002637{
Jamie Madill560a8d82014-05-21 13:06:20 -04002638 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2639 {
Jamie Madill437fa652016-05-03 15:13:24 -04002640 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002641 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002642 }
2643
2644 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2645 {
Jamie Madill437fa652016-05-03 15:13:24 -04002646 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002647 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002648 }
2649
2650 if (border != 0)
2651 {
Jamie Madill437fa652016-05-03 15:13:24 -04002652 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002653 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002654 }
2655
2656 if (!ValidMipLevel(context, target, level))
2657 {
Jamie Madill437fa652016-05-03 15:13:24 -04002658 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002659 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002660 }
2661
Jamie Madill51f40ec2016-06-15 14:06:00 -04002662 const auto &state = context->getGLState();
2663 auto readFramebuffer = state.getReadFramebuffer();
2664 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002665 {
Jamie Madill437fa652016-05-03 15:13:24 -04002666 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002667 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002668 }
2669
Jamie Madill51f40ec2016-06-15 14:06:00 -04002670 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002671 {
Jamie Madill437fa652016-05-03 15:13:24 -04002672 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002673 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002674 }
2675
Martin Radev138064f2016-07-15 12:03:41 +03002676 if (readFramebuffer->getReadBufferState() == GL_NONE)
2677 {
2678 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2679 return false;
2680 }
2681
Geoff Langaae65a42014-05-26 12:43:44 -04002682 const gl::Caps &caps = context->getCaps();
2683
Geoff Langaae65a42014-05-26 12:43:44 -04002684 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002685 switch (target)
2686 {
2687 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002688 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002689 break;
2690
2691 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2692 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2693 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2694 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2695 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2696 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002697 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002698 break;
2699
2700 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002701 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002702 break;
2703
2704 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002705 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002706 break;
2707
2708 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002709 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002710 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002711 }
2712
Jamie Madillc29968b2016-01-20 11:17:23 -05002713 gl::Texture *texture =
2714 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002715 if (!texture)
2716 {
Jamie Madill437fa652016-05-03 15:13:24 -04002717 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002718 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002719 }
2720
Geoff Lang69cce582015-09-17 13:20:36 -04002721 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002722 {
Jamie Madill437fa652016-05-03 15:13:24 -04002723 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002724 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002725 }
2726
Geoff Lang5d601382014-07-22 15:14:06 -04002727 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2728
2729 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002730 {
Jamie Madill437fa652016-05-03 15:13:24 -04002731 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002732 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002733 }
2734
Geoff Langa9be0dc2014-12-17 12:34:40 -05002735 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002736 {
Jamie Madill437fa652016-05-03 15:13:24 -04002737 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002738 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002739 }
2740
2741 if (isSubImage)
2742 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002743 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2744 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2745 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002746 {
Jamie Madill437fa652016-05-03 15:13:24 -04002747 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002748 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002749 }
2750 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002751 else
2752 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002753 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002754 {
Jamie Madill437fa652016-05-03 15:13:24 -04002755 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002756 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002757 }
2758
Martin Radev1be913c2016-07-11 17:59:16 +03002759 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002760 {
Jamie Madill437fa652016-05-03 15:13:24 -04002761 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002762 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002763 }
2764
2765 int maxLevelDimension = (maxDimension >> level);
2766 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2767 {
Jamie Madill437fa652016-05-03 15:13:24 -04002768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002769 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002770 }
2771 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002772
Jamie Madill0c8abca2016-07-22 20:21:26 -04002773 if (textureFormatOut)
2774 {
2775 *textureFormatOut = texture->getFormat(target, level);
2776 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002777 return true;
2778}
2779
Jamie Madillf25855c2015-11-03 11:06:18 -05002780static bool ValidateDrawBase(ValidationContext *context,
2781 GLenum mode,
2782 GLsizei count,
2783 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002784{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002785 switch (mode)
2786 {
2787 case GL_POINTS:
2788 case GL_LINES:
2789 case GL_LINE_LOOP:
2790 case GL_LINE_STRIP:
2791 case GL_TRIANGLES:
2792 case GL_TRIANGLE_STRIP:
2793 case GL_TRIANGLE_FAN:
2794 break;
2795 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002796 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002797 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002798 }
2799
Jamie Madill250d33f2014-06-06 17:09:03 -04002800 if (count < 0)
2801 {
Jamie Madill437fa652016-05-03 15:13:24 -04002802 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002803 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002804 }
2805
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002806 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002807
Jamie Madill250d33f2014-06-06 17:09:03 -04002808 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002809 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002810 {
Jamie Madill437fa652016-05-03 15:13:24 -04002811 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002812 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002813 }
2814
Jamie Madill51f40ec2016-06-15 14:06:00 -04002815 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002816 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002817 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002818 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2819 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2820 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2821 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2822 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2823 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002824 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002825 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2826 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002827 {
2828 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2829 // Section 6.10 of the WebGL 1.0 spec
2830 ERR(
2831 "This ANGLE implementation does not support separate front/back stencil "
2832 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002833 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002834 return false;
2835 }
Jamie Madillac528012014-06-20 13:21:23 -04002836 }
2837
Jamie Madill51f40ec2016-06-15 14:06:00 -04002838 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002839 {
Jamie Madill437fa652016-05-03 15:13:24 -04002840 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002841 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002842 }
2843
Geoff Lang7dd2e102014-11-10 15:19:26 -05002844 gl::Program *program = state.getProgram();
2845 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002846 {
Jamie Madill437fa652016-05-03 15:13:24 -04002847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002849 }
2850
Geoff Lang7dd2e102014-11-10 15:19:26 -05002851 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002852 {
Jamie Madill437fa652016-05-03 15:13:24 -04002853 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002854 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002855 }
2856
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002857 // Uniform buffer validation
2858 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2859 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002860 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002861 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002862 const OffsetBindingPointer<Buffer> &uniformBuffer =
2863 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002864
Geoff Lang5d124a62015-09-15 13:03:27 -04002865 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002866 {
2867 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002868 context->handleError(
2869 Error(GL_INVALID_OPERATION,
2870 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002871 return false;
2872 }
2873
Geoff Lang5d124a62015-09-15 13:03:27 -04002874 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002875 if (uniformBufferSize == 0)
2876 {
2877 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002878 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002879 }
2880
Jamie Madill62d31cb2015-09-11 13:25:51 -04002881 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002882 {
2883 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002884 context->handleError(
2885 Error(GL_INVALID_OPERATION,
2886 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002887 return false;
2888 }
2889 }
2890
Jamie Madill250d33f2014-06-06 17:09:03 -04002891 // No-op if zero count
2892 return (count > 0);
2893}
2894
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002895bool ValidateDrawArrays(ValidationContext *context,
2896 GLenum mode,
2897 GLint first,
2898 GLsizei count,
2899 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002900{
Jamie Madillfd716582014-06-06 17:09:04 -04002901 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002902 {
Jamie Madill437fa652016-05-03 15:13:24 -04002903 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002904 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002905 }
2906
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002907 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002908 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002909 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2910 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002911 {
2912 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2913 // that does not match the current transform feedback object's draw mode (if transform feedback
2914 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002915 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002916 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002917 }
2918
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002919 if (!ValidateDrawBase(context, mode, count, primcount))
2920 {
2921 return false;
2922 }
2923
2924 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002925 {
2926 return false;
2927 }
2928
2929 return true;
2930}
2931
Geoff Langb1196682014-07-23 13:47:29 -04002932bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002933{
2934 if (primcount < 0)
2935 {
Jamie Madill437fa652016-05-03 15:13:24 -04002936 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002937 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002938 }
2939
Jamie Madill2b976812014-08-25 15:47:49 -04002940 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002941 {
2942 return false;
2943 }
2944
2945 // No-op if zero primitive count
2946 return (primcount > 0);
2947}
2948
Geoff Lang87a93302014-09-16 13:29:43 -04002949static bool ValidateDrawInstancedANGLE(Context *context)
2950{
2951 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002952 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002953
Geoff Lang7dd2e102014-11-10 15:19:26 -05002954 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002955
2956 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002957 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002958 {
2959 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002960 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002961 {
2962 return true;
2963 }
2964 }
2965
Jamie Madill437fa652016-05-03 15:13:24 -04002966 context->handleError(Error(GL_INVALID_OPERATION,
2967 "ANGLE_instanced_arrays requires that at least one active attribute"
2968 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002969 return false;
2970}
2971
2972bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2973{
2974 if (!ValidateDrawInstancedANGLE(context))
2975 {
2976 return false;
2977 }
2978
2979 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2980}
2981
Jamie Madillf25855c2015-11-03 11:06:18 -05002982bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002983 GLenum mode,
2984 GLsizei count,
2985 GLenum type,
2986 const GLvoid *indices,
2987 GLsizei primcount,
2988 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002989{
Jamie Madill250d33f2014-06-06 17:09:03 -04002990 switch (type)
2991 {
2992 case GL_UNSIGNED_BYTE:
2993 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002994 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002995 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002996 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2997 {
2998 context->handleError(Error(GL_INVALID_ENUM));
2999 return false;
3000 }
3001 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003002 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003003 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003004 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003005 }
3006
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003007 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003008
3009 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003010 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003011 {
3012 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3013 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003014 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003015 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003016 }
3017
3018 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003019 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003020 {
Jamie Madill437fa652016-05-03 15:13:24 -04003021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003023 }
3024
Jamie Madill2b976812014-08-25 15:47:49 -04003025 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003026 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003027 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003031 }
3032
Jamie Madillae3000b2014-08-25 15:47:51 -04003033 if (elementArrayBuffer)
3034 {
3035 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3036
3037 GLint64 offset = reinterpret_cast<GLint64>(indices);
3038 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3039
3040 // check for integer overflows
3041 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3042 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3043 {
Jamie Madill437fa652016-05-03 15:13:24 -04003044 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003046 }
3047
3048 // Check for reading past the end of the bound buffer object
3049 if (byteCount > elementArrayBuffer->getSize())
3050 {
Jamie Madill437fa652016-05-03 15:13:24 -04003051 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003052 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003053 }
3054 }
3055 else if (!indices)
3056 {
3057 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003060 }
3061
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003062 if (!ValidateDrawBase(context, mode, count, primcount))
3063 {
3064 return false;
3065 }
3066
Jamie Madill2b976812014-08-25 15:47:49 -04003067 // Use max index to validate if our vertex buffers are large enough for the pull.
3068 // TODO: offer fast path, with disabled index validation.
3069 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3070 if (elementArrayBuffer)
3071 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003072 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003073 Error error =
3074 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3075 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003076 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003077 {
Jamie Madill437fa652016-05-03 15:13:24 -04003078 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003079 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003080 }
3081 }
3082 else
3083 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003084 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003085 }
3086
Jamie Madille79b1e12015-11-04 16:36:37 -05003087 // If we use an index greater than our maximum supported index range, return an error.
3088 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3089 // return an error if possible here.
3090 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3091 {
Jamie Madill437fa652016-05-03 15:13:24 -04003092 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003093 return false;
3094 }
3095
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003096 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003097 {
3098 return false;
3099 }
3100
Geoff Lang3edfe032015-09-04 16:38:24 -04003101 // No op if there are no real indices in the index data (all are primitive restart).
3102 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003103}
3104
Geoff Langb1196682014-07-23 13:47:29 -04003105bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003106 GLenum mode,
3107 GLsizei count,
3108 GLenum type,
3109 const GLvoid *indices,
3110 GLsizei primcount,
3111 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003112{
3113 if (primcount < 0)
3114 {
Jamie Madill437fa652016-05-03 15:13:24 -04003115 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003116 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003117 }
3118
Jamie Madill2b976812014-08-25 15:47:49 -04003119 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003120 {
3121 return false;
3122 }
3123
3124 // No-op zero primitive count
3125 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003126}
3127
Geoff Lang3edfe032015-09-04 16:38:24 -04003128bool ValidateDrawElementsInstancedANGLE(Context *context,
3129 GLenum mode,
3130 GLsizei count,
3131 GLenum type,
3132 const GLvoid *indices,
3133 GLsizei primcount,
3134 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003135{
3136 if (!ValidateDrawInstancedANGLE(context))
3137 {
3138 return false;
3139 }
3140
3141 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3142}
3143
Geoff Langb1196682014-07-23 13:47:29 -04003144bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003145 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003146{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003147 if (!ValidFramebufferTarget(target))
3148 {
Jamie Madill437fa652016-05-03 15:13:24 -04003149 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003150 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003151 }
3152
3153 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003154 {
3155 return false;
3156 }
3157
Jamie Madill55ec3b12014-07-03 10:38:57 -04003158 if (texture != 0)
3159 {
3160 gl::Texture *tex = context->getTexture(texture);
3161
3162 if (tex == NULL)
3163 {
Jamie Madill437fa652016-05-03 15:13:24 -04003164 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003165 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003166 }
3167
3168 if (level < 0)
3169 {
Jamie Madill437fa652016-05-03 15:13:24 -04003170 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003172 }
3173 }
3174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003175 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003176 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003177
Jamie Madill84115c92015-04-23 15:00:07 -04003178 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003179 {
Jamie Madill437fa652016-05-03 15:13:24 -04003180 context->handleError(
3181 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003182 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003183 }
3184
3185 return true;
3186}
3187
Geoff Langb1196682014-07-23 13:47:29 -04003188bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003189 GLenum textarget, GLuint texture, GLint level)
3190{
Geoff Lang95663912015-04-02 15:54:45 -04003191 // 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 +03003192 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3193 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 {
Jamie Madill437fa652016-05-03 15:13:24 -04003195 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003196 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003197 }
3198
3199 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003200 {
3201 return false;
3202 }
3203
Jamie Madill55ec3b12014-07-03 10:38:57 -04003204 if (texture != 0)
3205 {
3206 gl::Texture *tex = context->getTexture(texture);
3207 ASSERT(tex);
3208
Jamie Madill2a6564e2014-07-11 09:53:19 -04003209 const gl::Caps &caps = context->getCaps();
3210
Jamie Madill55ec3b12014-07-03 10:38:57 -04003211 switch (textarget)
3212 {
3213 case GL_TEXTURE_2D:
3214 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003215 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003216 {
Jamie Madill437fa652016-05-03 15:13:24 -04003217 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003218 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003219 }
3220 if (tex->getTarget() != GL_TEXTURE_2D)
3221 {
Jamie Madill437fa652016-05-03 15:13:24 -04003222 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003223 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003224 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003225 }
3226 break;
3227
3228 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3229 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3230 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3231 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3232 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3233 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3234 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003235 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003236 {
Jamie Madill437fa652016-05-03 15:13:24 -04003237 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003238 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003239 }
3240 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3241 {
Jamie Madill437fa652016-05-03 15:13:24 -04003242 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003243 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003244 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003245 }
3246 break;
3247
3248 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003249 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003250 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003251 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003252
Jamie Madilla3944d42016-07-22 22:13:26 -04003253 const Format &format = tex->getFormat(textarget, level);
3254 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003255 {
Jamie Madill437fa652016-05-03 15:13:24 -04003256 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003257 return false;
3258 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003259 }
3260
Jamie Madill570f7c82014-07-03 10:38:54 -04003261 return true;
3262}
3263
Geoff Langb1196682014-07-23 13:47:29 -04003264bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003265{
3266 if (program == 0)
3267 {
Jamie Madill437fa652016-05-03 15:13:24 -04003268 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003269 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003270 }
3271
Dian Xiang769769a2015-09-09 15:20:08 -07003272 gl::Program *programObject = GetValidProgram(context, program);
3273 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003274 {
3275 return false;
3276 }
3277
Jamie Madill0063c512014-08-25 15:47:53 -04003278 if (!programObject || !programObject->isLinked())
3279 {
Jamie Madill437fa652016-05-03 15:13:24 -04003280 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003281 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003282 }
3283
Geoff Lang7dd2e102014-11-10 15:19:26 -05003284 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003285 {
Jamie Madill437fa652016-05-03 15:13:24 -04003286 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003287 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003288 }
3289
Jamie Madill0063c512014-08-25 15:47:53 -04003290 return true;
3291}
3292
Geoff Langb1196682014-07-23 13:47:29 -04003293bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003294{
3295 return ValidateGetUniformBase(context, program, location);
3296}
3297
Geoff Langb1196682014-07-23 13:47:29 -04003298bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003299{
Jamie Madill78f41802014-08-25 15:47:55 -04003300 return ValidateGetUniformBase(context, program, location);
3301}
3302
Geoff Langf41d0ee2016-10-07 13:04:23 -04003303static bool ValidateSizedGetUniform(Context *context,
3304 GLuint program,
3305 GLint location,
3306 GLsizei bufSize,
3307 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003308{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003309 if (length)
3310 {
3311 *length = 0;
3312 }
3313
Jamie Madill78f41802014-08-25 15:47:55 -04003314 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003315 {
Jamie Madill78f41802014-08-25 15:47:55 -04003316 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003317 }
3318
Geoff Langf41d0ee2016-10-07 13:04:23 -04003319 if (bufSize < 0)
3320 {
3321 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3322 return false;
3323 }
3324
Jamie Madilla502c742014-08-28 17:19:13 -04003325 gl::Program *programObject = context->getProgram(program);
3326 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003327
Jamie Madill78f41802014-08-25 15:47:55 -04003328 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003329 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3330 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003331 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003332 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003333 context->handleError(
3334 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003335 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003336 }
3337
Geoff Langf41d0ee2016-10-07 13:04:23 -04003338 if (length)
3339 {
3340 // Cast is safe because of comparison to bufSize.
3341 *length = static_cast<GLsizei>(requiredBytes);
3342 }
3343
Jamie Madill0063c512014-08-25 15:47:53 -04003344 return true;
3345}
3346
Geoff Langb1196682014-07-23 13:47:29 -04003347bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003348{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003349 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003350}
3351
Geoff Langb1196682014-07-23 13:47:29 -04003352bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003353{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003354 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3355}
3356
3357bool ValidateGetUniformfvRobustANGLE(Context *context,
3358 GLuint program,
3359 GLint location,
3360 GLsizei bufSize,
3361 GLsizei *length,
3362 GLfloat *params)
3363{
3364 if (!ValidateRobustEntryPoint(context, bufSize))
3365 {
3366 return false;
3367 }
3368
3369 // bufSize is validated in ValidateSizedGetUniform
3370 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3371}
3372
3373bool ValidateGetUniformivRobustANGLE(Context *context,
3374 GLuint program,
3375 GLint location,
3376 GLsizei bufSize,
3377 GLsizei *length,
3378 GLint *params)
3379{
3380 if (!ValidateRobustEntryPoint(context, bufSize))
3381 {
3382 return false;
3383 }
3384
3385 // bufSize is validated in ValidateSizedGetUniform
3386 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3387}
3388
3389bool ValidateGetUniformuivRobustANGLE(Context *context,
3390 GLuint program,
3391 GLint location,
3392 GLsizei bufSize,
3393 GLsizei *length,
3394 GLuint *params)
3395{
3396 if (!ValidateRobustEntryPoint(context, bufSize))
3397 {
3398 return false;
3399 }
3400
3401 if (context->getClientMajorVersion() < 3)
3402 {
3403 context->handleError(
3404 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3405 return false;
3406 }
3407
3408 // bufSize is validated in ValidateSizedGetUniform
3409 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003410}
3411
Austin Kinross08332632015-05-05 13:35:47 -07003412bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3413 const GLenum *attachments, bool defaultFramebuffer)
3414{
3415 if (numAttachments < 0)
3416 {
Jamie Madill437fa652016-05-03 15:13:24 -04003417 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003418 return false;
3419 }
3420
3421 for (GLsizei i = 0; i < numAttachments; ++i)
3422 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003423 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003424 {
3425 if (defaultFramebuffer)
3426 {
Jamie Madill437fa652016-05-03 15:13:24 -04003427 context->handleError(Error(
3428 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003429 return false;
3430 }
3431
3432 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3433 {
Jamie Madill437fa652016-05-03 15:13:24 -04003434 context->handleError(Error(GL_INVALID_OPERATION,
3435 "Requested color attachment is greater than the maximum "
3436 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003437 return false;
3438 }
3439 }
3440 else
3441 {
3442 switch (attachments[i])
3443 {
3444 case GL_DEPTH_ATTACHMENT:
3445 case GL_STENCIL_ATTACHMENT:
3446 case GL_DEPTH_STENCIL_ATTACHMENT:
3447 if (defaultFramebuffer)
3448 {
Jamie Madill437fa652016-05-03 15:13:24 -04003449 context->handleError(
3450 Error(GL_INVALID_ENUM,
3451 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003452 return false;
3453 }
3454 break;
3455 case GL_COLOR:
3456 case GL_DEPTH:
3457 case GL_STENCIL:
3458 if (!defaultFramebuffer)
3459 {
Jamie Madill437fa652016-05-03 15:13:24 -04003460 context->handleError(
3461 Error(GL_INVALID_ENUM,
3462 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003463 return false;
3464 }
3465 break;
3466 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003467 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003468 return false;
3469 }
3470 }
3471 }
3472
3473 return true;
3474}
3475
Austin Kinross6ee1e782015-05-29 17:05:37 -07003476bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3477{
3478 // Note that debug marker calls must not set error state
3479
3480 if (length < 0)
3481 {
3482 return false;
3483 }
3484
3485 if (marker == nullptr)
3486 {
3487 return false;
3488 }
3489
3490 return true;
3491}
3492
3493bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3494{
3495 // Note that debug marker calls must not set error state
3496
3497 if (length < 0)
3498 {
3499 return false;
3500 }
3501
3502 if (length > 0 && marker == nullptr)
3503 {
3504 return false;
3505 }
3506
3507 return true;
3508}
3509
Geoff Langdcab33b2015-07-21 13:03:16 -04003510bool ValidateEGLImageTargetTexture2DOES(Context *context,
3511 egl::Display *display,
3512 GLenum target,
3513 egl::Image *image)
3514{
Geoff Langa8406172015-07-21 16:53:39 -04003515 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3516 {
Jamie Madill437fa652016-05-03 15:13:24 -04003517 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003518 return false;
3519 }
3520
3521 switch (target)
3522 {
3523 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003524 if (!context->getExtensions().eglImage)
3525 {
3526 context->handleError(Error(
3527 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3528 }
3529 break;
3530
3531 case GL_TEXTURE_EXTERNAL_OES:
3532 if (!context->getExtensions().eglImageExternal)
3533 {
3534 context->handleError(Error(
3535 GL_INVALID_ENUM,
3536 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3537 }
Geoff Langa8406172015-07-21 16:53:39 -04003538 break;
3539
3540 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003541 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003542 return false;
3543 }
3544
3545 if (!display->isValidImage(image))
3546 {
Jamie Madill437fa652016-05-03 15:13:24 -04003547 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
3551 if (image->getSamples() > 0)
3552 {
Jamie Madill437fa652016-05-03 15:13:24 -04003553 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003554 "cannot create a 2D texture from a multisampled EGL image."));
3555 return false;
3556 }
3557
Jamie Madilla3944d42016-07-22 22:13:26 -04003558 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003559 if (!textureCaps.texturable)
3560 {
Jamie Madill437fa652016-05-03 15:13:24 -04003561 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003562 "EGL image internal format is not supported as a texture."));
3563 return false;
3564 }
3565
Geoff Langdcab33b2015-07-21 13:03:16 -04003566 return true;
3567}
3568
3569bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3570 egl::Display *display,
3571 GLenum target,
3572 egl::Image *image)
3573{
Geoff Langa8406172015-07-21 16:53:39 -04003574 if (!context->getExtensions().eglImage)
3575 {
Jamie Madill437fa652016-05-03 15:13:24 -04003576 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003577 return false;
3578 }
3579
3580 switch (target)
3581 {
3582 case GL_RENDERBUFFER:
3583 break;
3584
3585 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003586 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003587 return false;
3588 }
3589
3590 if (!display->isValidImage(image))
3591 {
Jamie Madill437fa652016-05-03 15:13:24 -04003592 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003593 return false;
3594 }
3595
Jamie Madilla3944d42016-07-22 22:13:26 -04003596 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003597 if (!textureCaps.renderable)
3598 {
Jamie Madill437fa652016-05-03 15:13:24 -04003599 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003600 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3601 return false;
3602 }
3603
Geoff Langdcab33b2015-07-21 13:03:16 -04003604 return true;
3605}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003606
3607bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3608{
Geoff Lang36167ab2015-12-07 10:27:14 -05003609 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003610 {
3611 // The default VAO should always exist
3612 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003613 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003614 return false;
3615 }
3616
3617 return true;
3618}
3619
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003620bool ValidateLinkProgram(Context *context, GLuint program)
3621{
3622 if (context->hasActiveTransformFeedback(program))
3623 {
3624 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003625 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003626 "Cannot link program while program is associated with an active "
3627 "transform feedback object."));
3628 return false;
3629 }
3630 return true;
3631}
3632
Geoff Langc5629752015-12-07 16:29:04 -05003633bool ValidateProgramBinaryBase(Context *context,
3634 GLuint program,
3635 GLenum binaryFormat,
3636 const void *binary,
3637 GLint length)
3638{
3639 Program *programObject = GetValidProgram(context, program);
3640 if (programObject == nullptr)
3641 {
3642 return false;
3643 }
3644
3645 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3646 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3647 programBinaryFormats.end())
3648 {
Jamie Madill437fa652016-05-03 15:13:24 -04003649 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003650 return false;
3651 }
3652
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003653 if (context->hasActiveTransformFeedback(program))
3654 {
3655 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003656 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003657 "Cannot change program binary while program is associated with "
3658 "an active transform feedback object."));
3659 return false;
3660 }
3661
Geoff Langc5629752015-12-07 16:29:04 -05003662 return true;
3663}
3664
3665bool ValidateGetProgramBinaryBase(Context *context,
3666 GLuint program,
3667 GLsizei bufSize,
3668 GLsizei *length,
3669 GLenum *binaryFormat,
3670 void *binary)
3671{
3672 Program *programObject = GetValidProgram(context, program);
3673 if (programObject == nullptr)
3674 {
3675 return false;
3676 }
3677
3678 if (!programObject->isLinked())
3679 {
Jamie Madill437fa652016-05-03 15:13:24 -04003680 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003681 return false;
3682 }
3683
3684 return true;
3685}
Jamie Madillc29968b2016-01-20 11:17:23 -05003686
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003687bool ValidateUseProgram(Context *context, GLuint program)
3688{
3689 if (program != 0)
3690 {
3691 Program *programObject = context->getProgram(program);
3692 if (!programObject)
3693 {
3694 // ES 3.1.0 section 7.3 page 72
3695 if (context->getShader(program))
3696 {
Jamie Madill437fa652016-05-03 15:13:24 -04003697 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003698 Error(GL_INVALID_OPERATION,
3699 "Attempted to use a single shader instead of a shader program."));
3700 return false;
3701 }
3702 else
3703 {
Jamie Madill437fa652016-05-03 15:13:24 -04003704 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003705 return false;
3706 }
3707 }
3708 if (!programObject->isLinked())
3709 {
Jamie Madill437fa652016-05-03 15:13:24 -04003710 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003711 return false;
3712 }
3713 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003714 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003715 {
3716 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003717 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003718 Error(GL_INVALID_OPERATION,
3719 "Cannot change active program while transform feedback is unpaused."));
3720 return false;
3721 }
3722
3723 return true;
3724}
3725
Jamie Madillc29968b2016-01-20 11:17:23 -05003726bool ValidateCopyTexImage2D(ValidationContext *context,
3727 GLenum target,
3728 GLint level,
3729 GLenum internalformat,
3730 GLint x,
3731 GLint y,
3732 GLsizei width,
3733 GLsizei height,
3734 GLint border)
3735{
Martin Radev1be913c2016-07-11 17:59:16 +03003736 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003737 {
3738 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3739 0, x, y, width, height, border);
3740 }
3741
Martin Radev1be913c2016-07-11 17:59:16 +03003742 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003743 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3744 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003745}
Jamie Madillc29968b2016-01-20 11:17:23 -05003746
3747bool ValidateFramebufferRenderbuffer(Context *context,
3748 GLenum target,
3749 GLenum attachment,
3750 GLenum renderbuffertarget,
3751 GLuint renderbuffer)
3752{
3753 if (!ValidFramebufferTarget(target) ||
3754 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3755 {
Jamie Madill437fa652016-05-03 15:13:24 -04003756 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003757 return false;
3758 }
3759
3760 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3761 renderbuffertarget, renderbuffer);
3762}
3763
3764bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3765{
3766 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3767 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3768 {
Jamie Madill437fa652016-05-03 15:13:24 -04003769 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003770 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3771 return false;
3772 }
3773
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003774 ASSERT(context->getGLState().getDrawFramebuffer());
3775 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003776 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3777
3778 // This should come first before the check for the default frame buffer
3779 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3780 // rather than INVALID_OPERATION
3781 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3782 {
3783 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3784
3785 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003786 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3787 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003788 {
3789 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003790 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3791 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3792 // 3.1 is still a bit ambiguous about the error, but future specs are
3793 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003794 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003795 return false;
3796 }
3797 else if (bufs[colorAttachment] >= maxColorAttachment)
3798 {
Jamie Madill437fa652016-05-03 15:13:24 -04003799 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003800 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003801 return false;
3802 }
3803 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3804 frameBufferId != 0)
3805 {
3806 // INVALID_OPERATION-GL is bound to buffer and ith argument
3807 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003808 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003809 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3810 return false;
3811 }
3812 }
3813
3814 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3815 // and n is not 1 or bufs is bound to value other than BACK and NONE
3816 if (frameBufferId == 0)
3817 {
3818 if (n != 1)
3819 {
Jamie Madill437fa652016-05-03 15:13:24 -04003820 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003821 "n must be 1 when GL is bound to the default framebuffer"));
3822 return false;
3823 }
3824
3825 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3826 {
Jamie Madill437fa652016-05-03 15:13:24 -04003827 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003828 GL_INVALID_OPERATION,
3829 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3830 return false;
3831 }
3832 }
3833
3834 return true;
3835}
3836
3837bool ValidateCopyTexSubImage2D(Context *context,
3838 GLenum target,
3839 GLint level,
3840 GLint xoffset,
3841 GLint yoffset,
3842 GLint x,
3843 GLint y,
3844 GLsizei width,
3845 GLsizei height)
3846{
Martin Radev1be913c2016-07-11 17:59:16 +03003847 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003848 {
3849 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3850 yoffset, x, y, width, height, 0);
3851 }
3852
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003853 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3854 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003855}
3856
Olli Etuaho4f667482016-03-30 15:56:35 +03003857bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3858{
3859 if (!ValidBufferTarget(context, target))
3860 {
Jamie Madill437fa652016-05-03 15:13:24 -04003861 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 return false;
3863 }
3864
3865 if (pname != GL_BUFFER_MAP_POINTER)
3866 {
Jamie Madill437fa652016-05-03 15:13:24 -04003867 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 return false;
3869 }
3870
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003871 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003872
3873 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3874 // target bound to zero generate an INVALID_OPERATION error."
3875 // GLES 3.1 section 6.6 explicitly specifies this error.
3876 if (!buffer)
3877 {
Jamie Madill437fa652016-05-03 15:13:24 -04003878 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3880 return false;
3881 }
3882
3883 return true;
3884}
3885
3886bool ValidateUnmapBufferBase(Context *context, GLenum target)
3887{
3888 if (!ValidBufferTarget(context, target))
3889 {
Jamie Madill437fa652016-05-03 15:13:24 -04003890 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 return false;
3892 }
3893
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003894 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003895
3896 if (buffer == nullptr || !buffer->isMapped())
3897 {
Jamie Madill437fa652016-05-03 15:13:24 -04003898 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
3902 return true;
3903}
3904
3905bool ValidateMapBufferRangeBase(Context *context,
3906 GLenum target,
3907 GLintptr offset,
3908 GLsizeiptr length,
3909 GLbitfield access)
3910{
3911 if (!ValidBufferTarget(context, target))
3912 {
Jamie Madill437fa652016-05-03 15:13:24 -04003913 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
3917 if (offset < 0 || length < 0)
3918 {
Jamie Madill437fa652016-05-03 15:13:24 -04003919 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
3922
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003923 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003924
3925 if (!buffer)
3926 {
Jamie Madill437fa652016-05-03 15:13:24 -04003927 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003928 return false;
3929 }
3930
3931 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003932 CheckedNumeric<size_t> checkedOffset(offset);
3933 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003934
Jamie Madille2e406c2016-06-02 13:04:10 -04003935 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 {
Jamie Madill437fa652016-05-03 15:13:24 -04003937 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3939 return false;
3940 }
3941
3942 // Check for invalid bits in the mask
3943 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3944 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3945 GL_MAP_UNSYNCHRONIZED_BIT;
3946
3947 if (access & ~(allAccessBits))
3948 {
Jamie Madill437fa652016-05-03 15:13:24 -04003949 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 return false;
3951 }
3952
3953 if (length == 0)
3954 {
Jamie Madill437fa652016-05-03 15:13:24 -04003955 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 return false;
3957 }
3958
3959 if (buffer->isMapped())
3960 {
Jamie Madill437fa652016-05-03 15:13:24 -04003961 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003962 return false;
3963 }
3964
3965 // Check for invalid bit combinations
3966 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3967 {
Jamie Madill437fa652016-05-03 15:13:24 -04003968 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003969 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3970 return false;
3971 }
3972
3973 GLbitfield writeOnlyBits =
3974 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3975
3976 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3977 {
Jamie Madill437fa652016-05-03 15:13:24 -04003978 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003979 "Invalid access bits when mapping buffer for reading: 0x%X.",
3980 access));
3981 return false;
3982 }
3983
3984 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3985 {
Jamie Madill437fa652016-05-03 15:13:24 -04003986 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003987 GL_INVALID_OPERATION,
3988 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3989 return false;
3990 }
3991 return true;
3992}
3993
3994bool ValidateFlushMappedBufferRangeBase(Context *context,
3995 GLenum target,
3996 GLintptr offset,
3997 GLsizeiptr length)
3998{
3999 if (offset < 0 || length < 0)
4000 {
Jamie Madill437fa652016-05-03 15:13:24 -04004001 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004002 return false;
4003 }
4004
4005 if (!ValidBufferTarget(context, target))
4006 {
Jamie Madill437fa652016-05-03 15:13:24 -04004007 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004008 return false;
4009 }
4010
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004011 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004012
4013 if (buffer == nullptr)
4014 {
Jamie Madill437fa652016-05-03 15:13:24 -04004015 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004016 return false;
4017 }
4018
4019 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4020 {
Jamie Madill437fa652016-05-03 15:13:24 -04004021 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004022 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4023 return false;
4024 }
4025
4026 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004027 CheckedNumeric<size_t> checkedOffset(offset);
4028 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004029
Jamie Madille2e406c2016-06-02 13:04:10 -04004030 if (!checkedSize.IsValid() ||
4031 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004032 {
Jamie Madill437fa652016-05-03 15:13:24 -04004033 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004034 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4035 return false;
4036 }
4037
4038 return true;
4039}
4040
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004041bool ValidateGenerateMipmap(Context *context, GLenum target)
4042{
4043 if (!ValidTextureTarget(context, target))
4044 {
4045 context->handleError(Error(GL_INVALID_ENUM));
4046 return false;
4047 }
4048
4049 Texture *texture = context->getTargetTexture(target);
4050
4051 if (texture == nullptr)
4052 {
4053 context->handleError(Error(GL_INVALID_OPERATION));
4054 return false;
4055 }
4056
4057 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4058
4059 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4060 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4061 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4062 {
4063 context->handleError(Error(GL_INVALID_OPERATION));
4064 return false;
4065 }
4066
Jamie Madilla3944d42016-07-22 22:13:26 -04004067 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4068 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4069 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004070
4071 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4072 // unsized formats or that are color renderable and filterable. Since we do not track if
4073 // the texture was created with sized or unsized format (only sized formats are stored),
4074 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4075 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4076 // textures since they're the only texture format that can be created with unsized formats
4077 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4078 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004079 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4080 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004081 {
4082 context->handleError(Error(GL_INVALID_OPERATION));
4083 return false;
4084 }
4085
4086 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004087 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004088 {
4089 context->handleError(Error(GL_INVALID_OPERATION));
4090 return false;
4091 }
4092
4093 // Non-power of 2 ES2 check
4094 if (!context->getExtensions().textureNPOT &&
4095 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4096 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4097 {
Martin Radev1be913c2016-07-11 17:59:16 +03004098 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004099 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
4100 context->handleError(Error(GL_INVALID_OPERATION));
4101 return false;
4102 }
4103
4104 // Cube completeness check
4105 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4106 {
4107 context->handleError(Error(GL_INVALID_OPERATION));
4108 return false;
4109 }
4110
4111 return true;
4112}
4113
Olli Etuaho41997e72016-03-10 13:38:39 +02004114bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4115{
4116 return ValidateGenOrDelete(context, n);
4117}
4118
4119bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4120{
4121 return ValidateGenOrDelete(context, n);
4122}
4123
4124bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4125{
4126 return ValidateGenOrDelete(context, n);
4127}
4128
4129bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4130{
4131 return ValidateGenOrDelete(context, n);
4132}
4133
4134bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4135{
4136 return ValidateGenOrDelete(context, n);
4137}
4138
4139bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4140{
4141 return ValidateGenOrDelete(context, n);
4142}
4143
4144bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4145{
4146 return ValidateGenOrDelete(context, n);
4147}
4148
4149bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4150{
4151 return ValidateGenOrDelete(context, n);
4152}
4153
4154bool ValidateGenOrDelete(Context *context, GLint n)
4155{
4156 if (n < 0)
4157 {
Jamie Madill437fa652016-05-03 15:13:24 -04004158 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004159 return false;
4160 }
4161 return true;
4162}
4163
Geoff Langf41a7152016-09-19 15:11:17 -04004164bool ValidateEnable(Context *context, GLenum cap)
4165{
4166 if (!ValidCap(context, cap, false))
4167 {
4168 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4169 return false;
4170 }
4171
4172 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4173 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4174 {
4175 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4176 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4177
4178 // We also output an error message to the debugger window if tracing is active, so that
4179 // developers can see the error message.
4180 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004181 return false;
4182 }
4183
4184 return true;
4185}
4186
4187bool ValidateDisable(Context *context, GLenum cap)
4188{
4189 if (!ValidCap(context, cap, false))
4190 {
4191 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4192 return false;
4193 }
4194
4195 return true;
4196}
4197
4198bool ValidateIsEnabled(Context *context, GLenum cap)
4199{
4200 if (!ValidCap(context, cap, true))
4201 {
4202 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4203 return false;
4204 }
4205
4206 return true;
4207}
4208
Geoff Langff5b2d52016-09-07 11:32:23 -04004209bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4210{
4211 if (!context->getExtensions().robustClientMemory)
4212 {
4213 context->handleError(
4214 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4215 return false;
4216 }
4217
4218 if (bufSize < 0)
4219 {
4220 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4221 return false;
4222 }
4223
4224 return true;
4225}
4226
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004227bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4228{
4229 if (bufSize < numParams)
4230 {
4231 context->handleError(Error(GL_INVALID_OPERATION,
4232 "%u parameters are required but %i were provided.", numParams,
4233 bufSize));
4234 return false;
4235 }
4236
4237 return true;
4238}
4239
Geoff Langff5b2d52016-09-07 11:32:23 -04004240bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4241 GLenum target,
4242 GLenum attachment,
4243 GLenum pname,
4244 GLsizei *numParams)
4245{
4246 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4247 *numParams = 1;
4248
4249 if (!ValidFramebufferTarget(target))
4250 {
4251 context->handleError(Error(GL_INVALID_ENUM));
4252 return false;
4253 }
4254
4255 int clientVersion = context->getClientMajorVersion();
4256
4257 switch (pname)
4258 {
4259 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4260 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4261 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4262 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4263 break;
4264
4265 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4266 if (clientVersion < 3 && !context->getExtensions().sRGB)
4267 {
4268 context->handleError(Error(GL_INVALID_ENUM));
4269 return false;
4270 }
4271 break;
4272
4273 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4274 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4275 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4276 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4277 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4278 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4279 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4280 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4281 if (clientVersion < 3)
4282 {
4283 context->handleError(Error(GL_INVALID_ENUM));
4284 return false;
4285 }
4286 break;
4287
4288 default:
4289 context->handleError(Error(GL_INVALID_ENUM));
4290 return false;
4291 }
4292
4293 // Determine if the attachment is a valid enum
4294 switch (attachment)
4295 {
4296 case GL_BACK:
4297 case GL_FRONT:
4298 case GL_DEPTH:
4299 case GL_STENCIL:
4300 case GL_DEPTH_STENCIL_ATTACHMENT:
4301 if (clientVersion < 3)
4302 {
4303 context->handleError(Error(GL_INVALID_ENUM));
4304 return false;
4305 }
4306 break;
4307
4308 case GL_DEPTH_ATTACHMENT:
4309 case GL_STENCIL_ATTACHMENT:
4310 break;
4311
4312 default:
4313 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4314 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4315 {
4316 context->handleError(Error(GL_INVALID_ENUM));
4317 return false;
4318 }
4319 break;
4320 }
4321
4322 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4323 ASSERT(framebuffer);
4324
4325 if (framebuffer->id() == 0)
4326 {
4327 if (clientVersion < 3)
4328 {
4329 context->handleError(Error(GL_INVALID_OPERATION));
4330 return false;
4331 }
4332
4333 switch (attachment)
4334 {
4335 case GL_BACK:
4336 case GL_DEPTH:
4337 case GL_STENCIL:
4338 break;
4339
4340 default:
4341 context->handleError(Error(GL_INVALID_OPERATION));
4342 return false;
4343 }
4344 }
4345 else
4346 {
4347 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4348 {
4349 // Valid attachment query
4350 }
4351 else
4352 {
4353 switch (attachment)
4354 {
4355 case GL_DEPTH_ATTACHMENT:
4356 case GL_STENCIL_ATTACHMENT:
4357 break;
4358
4359 case GL_DEPTH_STENCIL_ATTACHMENT:
4360 if (!framebuffer->hasValidDepthStencil())
4361 {
4362 context->handleError(Error(GL_INVALID_OPERATION));
4363 return false;
4364 }
4365 break;
4366
4367 default:
4368 context->handleError(Error(GL_INVALID_OPERATION));
4369 return false;
4370 }
4371 }
4372 }
4373
4374 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4375 if (attachmentObject)
4376 {
4377 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4378 attachmentObject->type() == GL_TEXTURE ||
4379 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4380
4381 switch (pname)
4382 {
4383 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4384 if (attachmentObject->type() != GL_RENDERBUFFER &&
4385 attachmentObject->type() != GL_TEXTURE)
4386 {
4387 context->handleError(Error(GL_INVALID_ENUM));
4388 return false;
4389 }
4390 break;
4391
4392 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4393 if (attachmentObject->type() != GL_TEXTURE)
4394 {
4395 context->handleError(Error(GL_INVALID_ENUM));
4396 return false;
4397 }
4398 break;
4399
4400 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4401 if (attachmentObject->type() != GL_TEXTURE)
4402 {
4403 context->handleError(Error(GL_INVALID_ENUM));
4404 return false;
4405 }
4406 break;
4407
4408 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4409 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4410 {
4411 context->handleError(Error(GL_INVALID_OPERATION));
4412 return false;
4413 }
4414 break;
4415
4416 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4417 if (attachmentObject->type() != GL_TEXTURE)
4418 {
4419 context->handleError(Error(GL_INVALID_ENUM));
4420 return false;
4421 }
4422 break;
4423
4424 default:
4425 break;
4426 }
4427 }
4428 else
4429 {
4430 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4431 // is NONE, then querying any other pname will generate INVALID_ENUM.
4432
4433 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4434 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4435 // INVALID_OPERATION for all other pnames
4436
4437 switch (pname)
4438 {
4439 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4440 break;
4441
4442 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4443 if (clientVersion < 3)
4444 {
4445 context->handleError(Error(GL_INVALID_ENUM));
4446 return false;
4447 }
4448 break;
4449
4450 default:
4451 if (clientVersion < 3)
4452 {
4453 context->handleError(Error(GL_INVALID_ENUM));
4454 return false;
4455 }
4456 else
4457 {
4458 context->handleError(Error(GL_INVALID_OPERATION));
4459 return false;
4460 }
4461 }
4462 }
4463
4464 return true;
4465}
4466
4467bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4468 GLenum target,
4469 GLenum attachment,
4470 GLenum pname,
4471 GLsizei bufSize,
4472 GLsizei *numParams)
4473{
4474 if (!ValidateRobustEntryPoint(context, bufSize))
4475 {
4476 return false;
4477 }
4478
4479 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4480 {
4481 return false;
4482 }
4483
4484 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4485 {
4486 return false;
4487 }
4488
4489 return true;
4490}
4491
4492bool ValidateGetBufferParameteriv(ValidationContext *context,
4493 GLenum target,
4494 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004495 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004496{
Geoff Langebebe1c2016-10-14 12:01:31 -04004497 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004498}
4499
4500bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4501 GLenum target,
4502 GLenum pname,
4503 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004504 GLsizei *length,
4505 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004506{
4507 if (!ValidateRobustEntryPoint(context, bufSize))
4508 {
4509 return false;
4510 }
4511
Geoff Langebebe1c2016-10-14 12:01:31 -04004512 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004513 {
4514 return false;
4515 }
4516
Geoff Langebebe1c2016-10-14 12:01:31 -04004517 if (!ValidateRobustBufferSize(context, bufSize, *length))
4518 {
4519 return false;
4520 }
4521
4522 return true;
4523}
4524
4525bool ValidateGetBufferParameteri64v(ValidationContext *context,
4526 GLenum target,
4527 GLenum pname,
4528 GLint64 *params)
4529{
4530 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4531}
4532
4533bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4534 GLenum target,
4535 GLenum pname,
4536 GLsizei bufSize,
4537 GLsizei *length,
4538 GLint64 *params)
4539{
4540 if (!ValidateRobustEntryPoint(context, bufSize))
4541 {
4542 return false;
4543 }
4544
4545 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4546 {
4547 return false;
4548 }
4549
4550 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004551 {
4552 return false;
4553 }
4554
4555 return true;
4556}
4557
4558bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4559{
4560 // Currently, all GetProgramiv queries return 1 parameter
4561 *numParams = 1;
4562
4563 Program *programObject = GetValidProgram(context, program);
4564 if (!programObject)
4565 {
4566 return false;
4567 }
4568
4569 switch (pname)
4570 {
4571 case GL_DELETE_STATUS:
4572 case GL_LINK_STATUS:
4573 case GL_VALIDATE_STATUS:
4574 case GL_INFO_LOG_LENGTH:
4575 case GL_ATTACHED_SHADERS:
4576 case GL_ACTIVE_ATTRIBUTES:
4577 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4578 case GL_ACTIVE_UNIFORMS:
4579 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4580 break;
4581
4582 case GL_PROGRAM_BINARY_LENGTH:
4583 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4584 {
4585 context->handleError(Error(GL_INVALID_ENUM,
4586 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4587 "GL_OES_get_program_binary or ES 3.0."));
4588 return false;
4589 }
4590 break;
4591
4592 case GL_ACTIVE_UNIFORM_BLOCKS:
4593 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4594 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4595 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4596 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4597 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4598 if (context->getClientMajorVersion() < 3)
4599 {
4600 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4601 return false;
4602 }
4603 break;
4604
4605 default:
4606 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4607 return false;
4608 }
4609
4610 return true;
4611}
4612
4613bool ValidateGetProgramivRobustANGLE(Context *context,
4614 GLuint program,
4615 GLenum pname,
4616 GLsizei bufSize,
4617 GLsizei *numParams)
4618{
4619 if (!ValidateRobustEntryPoint(context, bufSize))
4620 {
4621 return false;
4622 }
4623
4624 if (!ValidateGetProgramiv(context, program, pname, numParams))
4625 {
4626 return false;
4627 }
4628
4629 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4630 {
4631 return false;
4632 }
4633
4634 return true;
4635}
4636
Geoff Lang740d9022016-10-07 11:20:52 -04004637bool ValidateGetRenderbufferParameteriv(Context *context,
4638 GLenum target,
4639 GLenum pname,
4640 GLint *params)
4641{
4642 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4643}
4644
4645bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4646 GLenum target,
4647 GLenum pname,
4648 GLsizei bufSize,
4649 GLsizei *length,
4650 GLint *params)
4651{
4652 if (!ValidateRobustEntryPoint(context, bufSize))
4653 {
4654 return false;
4655 }
4656
4657 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4658 {
4659 return false;
4660 }
4661
4662 if (!ValidateRobustBufferSize(context, bufSize, *length))
4663 {
4664 return false;
4665 }
4666
4667 return true;
4668}
4669
Geoff Langd7d0ed32016-10-07 11:33:51 -04004670bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4671{
4672 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4673}
4674
4675bool ValidateGetShaderivRobustANGLE(Context *context,
4676 GLuint shader,
4677 GLenum pname,
4678 GLsizei bufSize,
4679 GLsizei *length,
4680 GLint *params)
4681{
4682 if (!ValidateRobustEntryPoint(context, bufSize))
4683 {
4684 return false;
4685 }
4686
4687 if (!ValidateGetShaderivBase(context, shader, pname, length))
4688 {
4689 return false;
4690 }
4691
4692 if (!ValidateRobustBufferSize(context, bufSize, *length))
4693 {
4694 return false;
4695 }
4696
4697 return true;
4698}
4699
Geoff Langc1984ed2016-10-07 12:41:00 -04004700bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4701{
4702 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4703}
4704
4705bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4706 GLenum target,
4707 GLenum pname,
4708 GLsizei bufSize,
4709 GLsizei *length,
4710 GLfloat *params)
4711{
4712 if (!ValidateRobustEntryPoint(context, bufSize))
4713 {
4714 return false;
4715 }
4716
4717 if (!ValidateGetTexParameterBase(context, target, pname, length))
4718 {
4719 return false;
4720 }
4721
4722 if (!ValidateRobustBufferSize(context, bufSize, *length))
4723 {
4724 return false;
4725 }
4726
4727 return true;
4728}
4729
4730bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4731{
4732 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4733}
4734
4735bool ValidateGetTexParameterivRobustANGLE(Context *context,
4736 GLenum target,
4737 GLenum pname,
4738 GLsizei bufSize,
4739 GLsizei *length,
4740 GLint *params)
4741{
4742 if (!ValidateRobustEntryPoint(context, bufSize))
4743 {
4744 return false;
4745 }
4746
4747 if (!ValidateGetTexParameterBase(context, target, pname, length))
4748 {
4749 return false;
4750 }
4751
4752 if (!ValidateRobustBufferSize(context, bufSize, *length))
4753 {
4754 return false;
4755 }
4756
4757 return true;
4758}
4759
4760bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4761{
4762 return ValidateTexParameterBase(context, target, pname, -1, &param);
4763}
4764
4765bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4766{
4767 return ValidateTexParameterBase(context, target, pname, -1, params);
4768}
4769
4770bool ValidateTexParameterfvRobustANGLE(Context *context,
4771 GLenum target,
4772 GLenum pname,
4773 GLsizei bufSize,
4774 const GLfloat *params)
4775{
4776 if (!ValidateRobustEntryPoint(context, bufSize))
4777 {
4778 return false;
4779 }
4780
4781 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4782}
4783
4784bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4785{
4786 return ValidateTexParameterBase(context, target, pname, -1, &param);
4787}
4788
4789bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4790{
4791 return ValidateTexParameterBase(context, target, pname, -1, params);
4792}
4793
4794bool ValidateTexParameterivRobustANGLE(Context *context,
4795 GLenum target,
4796 GLenum pname,
4797 GLsizei bufSize,
4798 const GLint *params)
4799{
4800 if (!ValidateRobustEntryPoint(context, bufSize))
4801 {
4802 return false;
4803 }
4804
4805 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4806}
4807
4808bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4809{
4810 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4811}
4812
4813bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4814 GLuint sampler,
4815 GLenum pname,
4816 GLuint bufSize,
4817 GLsizei *length,
4818 GLfloat *params)
4819{
4820 if (!ValidateRobustEntryPoint(context, bufSize))
4821 {
4822 return false;
4823 }
4824
4825 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4826 {
4827 return false;
4828 }
4829
4830 if (!ValidateRobustBufferSize(context, bufSize, *length))
4831 {
4832 return false;
4833 }
4834
4835 return true;
4836}
4837
4838bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4839{
4840 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4841}
4842
4843bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4844 GLuint sampler,
4845 GLenum pname,
4846 GLuint bufSize,
4847 GLsizei *length,
4848 GLint *params)
4849{
4850 if (!ValidateRobustEntryPoint(context, bufSize))
4851 {
4852 return false;
4853 }
4854
4855 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4856 {
4857 return false;
4858 }
4859
4860 if (!ValidateRobustBufferSize(context, bufSize, *length))
4861 {
4862 return false;
4863 }
4864
4865 return true;
4866}
4867
4868bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4869{
4870 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4871}
4872
4873bool ValidateSamplerParameterfv(Context *context,
4874 GLuint sampler,
4875 GLenum pname,
4876 const GLfloat *params)
4877{
4878 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4879}
4880
4881bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4882 GLuint sampler,
4883 GLenum pname,
4884 GLsizei bufSize,
4885 const GLfloat *params)
4886{
4887 if (!ValidateRobustEntryPoint(context, bufSize))
4888 {
4889 return false;
4890 }
4891
4892 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4893}
4894
4895bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4896{
4897 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4898}
4899
4900bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4901{
4902 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4903}
4904
4905bool ValidateSamplerParameterivRobustANGLE(Context *context,
4906 GLuint sampler,
4907 GLenum pname,
4908 GLsizei bufSize,
4909 const GLint *params)
4910{
4911 if (!ValidateRobustEntryPoint(context, bufSize))
4912 {
4913 return false;
4914 }
4915
4916 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4917}
4918
Geoff Lang0b031062016-10-13 14:30:04 -04004919bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
4920{
4921 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4922}
4923
4924bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4925 GLuint index,
4926 GLenum pname,
4927 GLsizei bufSize,
4928 GLsizei *length,
4929 GLfloat *params)
4930{
4931 if (!ValidateRobustEntryPoint(context, bufSize))
4932 {
4933 return false;
4934 }
4935
4936 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4937 {
4938 return false;
4939 }
4940
4941 if (!ValidateRobustBufferSize(context, bufSize, *length))
4942 {
4943 return false;
4944 }
4945
4946 return true;
4947}
4948
4949bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
4950{
4951 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4952}
4953
4954bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4955 GLuint index,
4956 GLenum pname,
4957 GLsizei bufSize,
4958 GLsizei *length,
4959 GLint *params)
4960{
4961 if (!ValidateRobustEntryPoint(context, bufSize))
4962 {
4963 return false;
4964 }
4965
4966 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4967 {
4968 return false;
4969 }
4970
4971 if (!ValidateRobustBufferSize(context, bufSize, *length))
4972 {
4973 return false;
4974 }
4975
4976 return true;
4977}
4978
4979bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
4980{
4981 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
4982}
4983
4984bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4985 GLuint index,
4986 GLenum pname,
4987 GLsizei bufSize,
4988 GLsizei *length,
4989 void **pointer)
4990{
4991 if (!ValidateRobustEntryPoint(context, bufSize))
4992 {
4993 return false;
4994 }
4995
4996 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4997 {
4998 return false;
4999 }
5000
5001 if (!ValidateRobustBufferSize(context, bufSize, *length))
5002 {
5003 return false;
5004 }
5005
5006 return true;
5007}
5008
5009bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5010{
5011 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5012}
5013
5014bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5015 GLuint index,
5016 GLenum pname,
5017 GLsizei bufSize,
5018 GLsizei *length,
5019 GLint *params)
5020{
5021 if (!ValidateRobustEntryPoint(context, bufSize))
5022 {
5023 return false;
5024 }
5025
5026 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5027 {
5028 return false;
5029 }
5030
5031 if (!ValidateRobustBufferSize(context, bufSize, *length))
5032 {
5033 return false;
5034 }
5035
5036 return true;
5037}
5038
5039bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5040{
5041 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5042}
5043
5044bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5045 GLuint index,
5046 GLenum pname,
5047 GLsizei bufSize,
5048 GLsizei *length,
5049 GLuint *params)
5050{
5051 if (!ValidateRobustEntryPoint(context, bufSize))
5052 {
5053 return false;
5054 }
5055
5056 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5057 {
5058 return false;
5059 }
5060
5061 if (!ValidateRobustBufferSize(context, bufSize, *length))
5062 {
5063 return false;
5064 }
5065
5066 return true;
5067}
5068
Geoff Lang6899b872016-10-14 11:30:13 -04005069bool ValidateGetActiveUniformBlockiv(Context *context,
5070 GLuint program,
5071 GLuint uniformBlockIndex,
5072 GLenum pname,
5073 GLint *params)
5074{
5075 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5076}
5077
5078bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5079 GLuint program,
5080 GLuint uniformBlockIndex,
5081 GLenum pname,
5082 GLsizei bufSize,
5083 GLsizei *length,
5084 GLint *params)
5085{
5086 if (!ValidateRobustEntryPoint(context, bufSize))
5087 {
5088 return false;
5089 }
5090
5091 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5092 {
5093 return false;
5094 }
5095
5096 if (!ValidateRobustBufferSize(context, bufSize, *length))
5097 {
5098 return false;
5099 }
5100
5101 return true;
5102}
5103
Jamie Madillc29968b2016-01-20 11:17:23 -05005104} // namespace gl