blob: 76815eed9d1f5daef7aca46b9123ebeeec0ac4fc [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 Langf41a7152016-09-19 15:11:17 -04001070} // anonymous namespace
1071
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001072bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001073{
Jamie Madilld7460c72014-01-21 16:38:14 -05001074 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001075 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001076 case GL_TEXTURE_2D:
1077 case GL_TEXTURE_CUBE_MAP:
1078 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001079
Jamie Madilld7460c72014-01-21 16:38:14 -05001080 case GL_TEXTURE_3D:
1081 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001082 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001083
1084 default:
1085 return false;
1086 }
Jamie Madill35d15012013-10-07 10:46:37 -04001087}
1088
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001089bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1090{
1091 switch (target)
1092 {
1093 case GL_TEXTURE_2D:
1094 case GL_TEXTURE_CUBE_MAP:
1095 return true;
1096
1097 default:
1098 return false;
1099 }
1100}
1101
1102bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1103{
1104 switch (target)
1105 {
1106 case GL_TEXTURE_3D:
1107 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001108 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001109
1110 default:
1111 return false;
1112 }
1113}
1114
Ian Ewellbda75592016-04-18 17:25:54 -04001115// Most texture GL calls are not compatible with external textures, so we have a separate validation
1116// function for use in the GL calls that do
1117bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1118{
1119 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1120 (context->getExtensions().eglImageExternal ||
1121 context->getExtensions().eglStreamConsumerExternal);
1122}
1123
Shannon Woods4dfed832014-03-17 20:03:39 -04001124// This function differs from ValidTextureTarget in that the target must be
1125// usable as the destination of a 2D operation-- so a cube face is valid, but
1126// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001127// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001128bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001129{
1130 switch (target)
1131 {
1132 case GL_TEXTURE_2D:
1133 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1134 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1135 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1136 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1137 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1138 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1139 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001140 default:
1141 return false;
1142 }
1143}
1144
1145bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1146{
1147 switch (target)
1148 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001149 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001150 case GL_TEXTURE_2D_ARRAY:
1151 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001152 default:
1153 return false;
1154 }
1155}
1156
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001157bool ValidFramebufferTarget(GLenum target)
1158{
Geoff Langd4475812015-03-18 10:53:05 -04001159 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1160 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001161
1162 switch (target)
1163 {
1164 case GL_FRAMEBUFFER: return true;
1165 case GL_READ_FRAMEBUFFER: return true;
1166 case GL_DRAW_FRAMEBUFFER: return true;
1167 default: return false;
1168 }
1169}
1170
Jamie Madill29639852016-09-02 15:00:09 -04001171bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001172{
1173 switch (target)
1174 {
1175 case GL_ARRAY_BUFFER:
1176 case GL_ELEMENT_ARRAY_BUFFER:
1177 return true;
1178
Jamie Madill8c96d582014-03-05 15:01:23 -05001179 case GL_PIXEL_PACK_BUFFER:
1180 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001181 return (context->getExtensions().pixelBufferObject ||
1182 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001183
Shannon Woodsb3801742014-03-27 14:59:19 -04001184 case GL_COPY_READ_BUFFER:
1185 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001186 case GL_TRANSFORM_FEEDBACK_BUFFER:
1187 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001188 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001189
1190 default:
1191 return false;
1192 }
1193}
1194
Geoff Langff5b2d52016-09-07 11:32:23 -04001195bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -05001196{
Geoff Langff5b2d52016-09-07 11:32:23 -04001197 // All buffer parameter queries return one value.
1198 *numParams = 1;
1199
Geoff Langcc6f55d2015-03-20 13:01:02 -04001200 const Extensions &extensions = context->getExtensions();
1201
Jamie Madill70656a62014-03-05 15:01:26 -05001202 switch (pname)
1203 {
1204 case GL_BUFFER_USAGE:
1205 case GL_BUFFER_SIZE:
1206 return true;
1207
Geoff Langcc6f55d2015-03-20 13:01:02 -04001208 case GL_BUFFER_ACCESS_OES:
1209 return extensions.mapBuffer;
1210
1211 case GL_BUFFER_MAPPED:
1212 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +03001213 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
1214 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -04001215
Jamie Madill70656a62014-03-05 15:01:26 -05001216 // GL_BUFFER_MAP_POINTER is a special case, and may only be
1217 // queried with GetBufferPointerv
1218 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -05001219 case GL_BUFFER_MAP_OFFSET:
1220 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +03001221 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -05001222
1223 default:
1224 return false;
1225 }
1226}
1227
Jamie Madillc29968b2016-01-20 11:17:23 -05001228bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001229{
Jamie Madillc29968b2016-01-20 11:17:23 -05001230 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001231 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001232 switch (target)
1233 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001234 case GL_TEXTURE_2D:
1235 maxDimension = caps.max2DTextureSize;
1236 break;
Geoff Langce635692013-09-24 13:56:32 -04001237 case GL_TEXTURE_CUBE_MAP:
1238 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1239 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1240 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1241 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1242 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001243 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1244 maxDimension = caps.maxCubeMapTextureSize;
1245 break;
1246 case GL_TEXTURE_3D:
1247 maxDimension = caps.max3DTextureSize;
1248 break;
1249 case GL_TEXTURE_2D_ARRAY:
1250 maxDimension = caps.max2DTextureSize;
1251 break;
Geoff Langce635692013-09-24 13:56:32 -04001252 default: UNREACHABLE();
1253 }
1254
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001255 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001256}
1257
Austin Kinross08528e12015-10-07 16:24:40 -07001258bool ValidImageSizeParameters(const Context *context,
1259 GLenum target,
1260 GLint level,
1261 GLsizei width,
1262 GLsizei height,
1263 GLsizei depth,
1264 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001265{
1266 if (level < 0 || width < 0 || height < 0 || depth < 0)
1267 {
1268 return false;
1269 }
1270
Austin Kinross08528e12015-10-07 16:24:40 -07001271 // TexSubImage parameters can be NPOT without textureNPOT extension,
1272 // as long as the destination texture is POT.
1273 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001274 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001275 {
1276 return false;
1277 }
1278
1279 if (!ValidMipLevel(context, target, level))
1280 {
1281 return false;
1282 }
1283
1284 return true;
1285}
1286
Geoff Lang0d8b7242015-09-09 14:56:53 -04001287bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1288{
1289 // List of compressed format that require that the texture size is smaller than or a multiple of
1290 // the compressed block size.
1291 switch (internalFormat)
1292 {
1293 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1294 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1295 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1296 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001297 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001298 return true;
1299
1300 default:
1301 return false;
1302 }
1303}
1304
Jamie Madillc29968b2016-01-20 11:17:23 -05001305bool ValidCompressedImageSize(const ValidationContext *context,
1306 GLenum internalFormat,
1307 GLsizei width,
1308 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001309{
Geoff Lang5d601382014-07-22 15:14:06 -04001310 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1311 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001312 {
1313 return false;
1314 }
1315
Geoff Lang0d8b7242015-09-09 14:56:53 -04001316 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001317 {
1318 return false;
1319 }
1320
Geoff Lang0d8b7242015-09-09 14:56:53 -04001321 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1322 {
1323 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1324 width % formatInfo.compressedBlockWidth != 0) ||
1325 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1326 height % formatInfo.compressedBlockHeight != 0))
1327 {
1328 return false;
1329 }
1330 }
1331
Geoff Langd4f180b2013-09-24 13:57:44 -04001332 return true;
1333}
1334
Geoff Langff5b2d52016-09-07 11:32:23 -04001335bool ValidImageDataSize(ValidationContext *context,
1336 GLenum textureTarget,
1337 GLsizei width,
1338 GLsizei height,
1339 GLsizei depth,
1340 GLenum internalFormat,
1341 GLenum type,
1342 const GLvoid *pixels,
1343 GLsizei imageSize)
1344{
1345 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1346 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1347 {
1348 // Checks are not required
1349 return true;
1350 }
1351
1352 // ...the data would be unpacked from the buffer object such that the memory reads required
1353 // would exceed the data store size.
1354 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1355 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1356 const gl::Extents size(width, height, depth);
1357 const auto &unpack = context->getGLState().getUnpackState();
1358
1359 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1360 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1361 if (endByteOrErr.isError())
1362 {
1363 context->handleError(endByteOrErr.getError());
1364 return false;
1365 }
1366
1367 GLuint endByte = endByteOrErr.getResult();
1368
1369 if (pixelUnpackBuffer)
1370 {
1371 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1372 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1373 checkedEndByte += checkedOffset;
1374
1375 if (!checkedEndByte.IsValid() ||
1376 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1377 {
1378 // Overflow past the end of the buffer
1379 context->handleError(Error(GL_INVALID_OPERATION));
1380 return false;
1381 }
1382 }
1383 else
1384 {
1385 ASSERT(imageSize >= 0);
1386 if (pixels == nullptr && imageSize != 0)
1387 {
1388 context->handleError(
1389 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1390 }
1391
1392 if (endByte > static_cast<GLuint>(imageSize))
1393 {
1394 context->handleError(
1395 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1396 return false;
1397 }
1398 }
1399
1400 return true;
1401}
1402
Geoff Lang37dde692014-01-31 16:34:54 -05001403bool ValidQueryType(const Context *context, GLenum queryType)
1404{
Geoff Langd4475812015-03-18 10:53:05 -04001405 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1406 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 -05001407
1408 switch (queryType)
1409 {
1410 case GL_ANY_SAMPLES_PASSED:
1411 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1412 return true;
1413 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001414 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001415 case GL_TIME_ELAPSED_EXT:
1416 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001417 case GL_COMMANDS_COMPLETED_CHROMIUM:
1418 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001419 default:
1420 return false;
1421 }
1422}
1423
Jamie Madillef300b12016-10-07 15:12:09 -04001424Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001425{
1426 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1427 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1428 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1429
Dian Xiang769769a2015-09-09 15:20:08 -07001430 Program *validProgram = context->getProgram(id);
1431
1432 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001433 {
Dian Xiang769769a2015-09-09 15:20:08 -07001434 if (context->getShader(id))
1435 {
Jamie Madill437fa652016-05-03 15:13:24 -04001436 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001437 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1438 }
1439 else
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001442 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001443 }
Dian Xiang769769a2015-09-09 15:20:08 -07001444
1445 return validProgram;
1446}
1447
Jamie Madillef300b12016-10-07 15:12:09 -04001448Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001449{
1450 // See ValidProgram for spec details.
1451
1452 Shader *validShader = context->getShader(id);
1453
1454 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001455 {
Dian Xiang769769a2015-09-09 15:20:08 -07001456 if (context->getProgram(id))
1457 {
Jamie Madill437fa652016-05-03 15:13:24 -04001458 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001459 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1460 }
1461 else
1462 {
Jamie Madill437fa652016-05-03 15:13:24 -04001463 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001464 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001465 }
Dian Xiang769769a2015-09-09 15:20:08 -07001466
1467 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001468}
1469
Geoff Langb1196682014-07-23 13:47:29 -04001470bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001471{
1472 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1473 {
1474 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1475
Geoff Langaae65a42014-05-26 12:43:44 -04001476 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001479 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001480 }
1481 }
1482 else
1483 {
1484 switch (attachment)
1485 {
1486 case GL_DEPTH_ATTACHMENT:
1487 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001488 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001489
1490 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001491 if (!context->getExtensions().webglCompatibility &&
1492 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001493 {
1494 context->handleError(Error(GL_INVALID_ENUM));
1495 return false;
1496 }
1497 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001498
1499 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001500 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001501 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001502 }
1503 }
1504
1505 return true;
1506}
1507
Corentin Walleze0902642014-11-04 12:32:15 -08001508bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1509 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510{
1511 switch (target)
1512 {
1513 case GL_RENDERBUFFER:
1514 break;
1515 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001516 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001517 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518 }
1519
1520 if (width < 0 || height < 0 || samples < 0)
1521 {
Jamie Madill437fa652016-05-03 15:13:24 -04001522 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001523 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524 }
1525
Geoff Langd87878e2014-09-19 15:42:59 -04001526 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1527 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
1533 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1534 // 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 -08001535 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001536 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001537 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 {
Jamie Madill437fa652016-05-03 15:13:24 -04001539 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001540 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001541 }
1542
Geoff Langaae65a42014-05-26 12:43:44 -04001543 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001544 {
Jamie Madill437fa652016-05-03 15:13:24 -04001545 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001546 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001547 }
1548
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001549 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001550 if (handle == 0)
1551 {
Jamie Madill437fa652016-05-03 15:13:24 -04001552 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001553 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001554 }
1555
1556 return true;
1557}
1558
Corentin Walleze0902642014-11-04 12:32:15 -08001559bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1560 GLenum internalformat, GLsizei width, GLsizei height)
1561{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001562 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001563
1564 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001565 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001566 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001567 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001568 {
Jamie Madill437fa652016-05-03 15:13:24 -04001569 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001570 return false;
1571 }
1572
1573 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1574 // the specified storage. This is different than ES 3.0 in which a sample number higher
1575 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001576 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001577 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001578 {
Geoff Langa4903b72015-03-02 16:02:48 -08001579 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1580 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1581 {
Jamie Madill437fa652016-05-03 15:13:24 -04001582 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001583 return false;
1584 }
Corentin Walleze0902642014-11-04 12:32:15 -08001585 }
1586
1587 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1588}
1589
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001590bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1591 GLenum renderbuffertarget, GLuint renderbuffer)
1592{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001593 if (!ValidFramebufferTarget(target))
1594 {
Jamie Madill437fa652016-05-03 15:13:24 -04001595 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001596 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001597 }
1598
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001599 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001600
Jamie Madill84115c92015-04-23 15:00:07 -04001601 ASSERT(framebuffer);
1602 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001603 {
Jamie Madill437fa652016-05-03 15:13:24 -04001604 context->handleError(
1605 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001606 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001607 }
1608
Jamie Madillb4472272014-07-03 10:38:55 -04001609 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001610 {
Jamie Madillb4472272014-07-03 10:38:55 -04001611 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001612 }
1613
Jamie Madillab9d82c2014-01-21 16:38:14 -05001614 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1615 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1616 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1617 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1618 if (renderbuffer != 0)
1619 {
1620 if (!context->getRenderbuffer(renderbuffer))
1621 {
Jamie Madill437fa652016-05-03 15:13:24 -04001622 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001623 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001624 }
1625 }
1626
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001627 return true;
1628}
1629
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001630bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001631 GLint srcX0,
1632 GLint srcY0,
1633 GLint srcX1,
1634 GLint srcY1,
1635 GLint dstX0,
1636 GLint dstY0,
1637 GLint dstX1,
1638 GLint dstY1,
1639 GLbitfield mask,
1640 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001641{
1642 switch (filter)
1643 {
1644 case GL_NEAREST:
1645 break;
1646 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001647 break;
1648 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001650 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651 }
1652
1653 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1654 {
Jamie Madill437fa652016-05-03 15:13:24 -04001655 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001657 }
1658
1659 if (mask == 0)
1660 {
1661 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1662 // buffers are copied.
1663 return false;
1664 }
1665
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001666 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1667 // color buffer, leaving only nearest being unfiltered from above
1668 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1669 {
Jamie Madill437fa652016-05-03 15:13:24 -04001670 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001671 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001672 }
1673
Jamie Madill51f40ec2016-06-15 14:06:00 -04001674 const auto &glState = context->getGLState();
1675 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1676 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001677
1678 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001679 {
Jamie Madill437fa652016-05-03 15:13:24 -04001680 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001681 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001682 }
1683
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001684 if (readFramebuffer->id() == drawFramebuffer->id())
1685 {
1686 context->handleError(Error(GL_INVALID_OPERATION));
1687 return false;
1688 }
1689
Jamie Madill51f40ec2016-06-15 14:06:00 -04001690 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001691 {
Jamie Madill437fa652016-05-03 15:13:24 -04001692 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001693 return false;
1694 }
1695
Jamie Madill51f40ec2016-06-15 14:06:00 -04001696 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001697 {
Jamie Madill437fa652016-05-03 15:13:24 -04001698 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001699 return false;
1700 }
1701
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001702 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001703 {
Jamie Madill437fa652016-05-03 15:13:24 -04001704 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001705 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001706 }
1707
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001708 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1709
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001710 if (mask & GL_COLOR_BUFFER_BIT)
1711 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001712 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1713 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001714 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715
1716 if (readColorBuffer && drawColorBuffer)
1717 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001718 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001719
Geoff Langa15472a2015-08-11 11:48:03 -04001720 for (size_t drawbufferIdx = 0;
1721 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Geoff Langa15472a2015-08-11 11:48:03 -04001723 const FramebufferAttachment *attachment =
1724 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1725 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001726 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001727 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728
Geoff Langb2f3d052013-08-13 12:49:27 -04001729 // The GL ES 3.0.2 spec (pg 193) states that:
1730 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1731 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1732 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001733 // Changes with EXT_color_buffer_float:
1734 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001735 GLenum readComponentType = readFormat.info->componentType;
1736 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001737 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1738 readComponentType == GL_SIGNED_NORMALIZED);
1739 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1740 drawComponentType == GL_SIGNED_NORMALIZED);
1741
1742 if (extensions.colorBufferFloat)
1743 {
1744 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1745 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1746
1747 if (readFixedOrFloat != drawFixedOrFloat)
1748 {
Jamie Madill437fa652016-05-03 15:13:24 -04001749 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001750 "If the read buffer contains fixed-point or "
1751 "floating-point values, the draw buffer "
1752 "must as well."));
1753 return false;
1754 }
1755 }
1756 else if (readFixedPoint != drawFixedPoint)
1757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001759 "If the read buffer contains fixed-point "
1760 "values, the draw buffer must as well."));
1761 return false;
1762 }
1763
1764 if (readComponentType == GL_UNSIGNED_INT &&
1765 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001766 {
Jamie Madill437fa652016-05-03 15:13:24 -04001767 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001768 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001769 }
1770
Jamie Madill6163c752015-12-07 16:32:59 -05001771 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001772 {
Jamie Madill437fa652016-05-03 15:13:24 -04001773 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001774 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 }
1776
Jamie Madilla3944d42016-07-22 22:13:26 -04001777 if (readColorBuffer->getSamples() > 0 &&
1778 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001781 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782 }
1783 }
1784 }
1785
Jamie Madilla3944d42016-07-22 22:13:26 -04001786 if ((readFormat.info->componentType == GL_INT ||
1787 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1788 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 {
Jamie Madill437fa652016-05-03 15:13:24 -04001790 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001791 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001793 }
1794 }
1795
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001796 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1797 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1798 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001799 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001800 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001801 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001802 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1803 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001804
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001805 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001806 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001807 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001808 {
Jamie Madill437fa652016-05-03 15:13:24 -04001809 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001810 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001811 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001812
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001813 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001814 {
Jamie Madill437fa652016-05-03 15:13:24 -04001815 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001816 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001817 }
1818 }
1819 }
1820 }
1821
1822 return true;
1823}
1824
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001825bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001826 GLint x,
1827 GLint y,
1828 GLsizei width,
1829 GLsizei height,
1830 GLenum format,
1831 GLenum type,
1832 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001833{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001834 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1835}
1836
1837bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1838 GLint x,
1839 GLint y,
1840 GLsizei width,
1841 GLsizei height,
1842 GLenum format,
1843 GLenum type,
1844 GLsizei bufSize,
1845 GLsizei *length,
1846 GLvoid *pixels)
1847{
1848 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852
Geoff Lang62fce5b2016-09-30 10:46:35 -04001853 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1854 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001855 {
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001857 }
1858
Geoff Lang62fce5b2016-09-30 10:46:35 -04001859 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001860 {
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001862 }
1863
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return true;
1865}
1866
1867bool ValidateReadnPixelsEXT(Context *context,
1868 GLint x,
1869 GLint y,
1870 GLsizei width,
1871 GLsizei height,
1872 GLenum format,
1873 GLenum type,
1874 GLsizei bufSize,
1875 GLvoid *pixels)
1876{
1877 if (bufSize < 0)
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
Geoff Lang62fce5b2016-09-30 10:46:35 -04001883 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1884 pixels);
1885}
Jamie Madill26e91952014-03-05 15:01:27 -05001886
Geoff Lang62fce5b2016-09-30 10:46:35 -04001887bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1888 GLint x,
1889 GLint y,
1890 GLsizei width,
1891 GLsizei height,
1892 GLenum format,
1893 GLenum type,
1894 GLsizei bufSize,
1895 GLsizei *length,
1896 GLvoid *data)
1897{
1898 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001899 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001900 return false;
1901 }
1902
Geoff Lang62fce5b2016-09-30 10:46:35 -04001903 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001904 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001905 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001906 }
1907
Geoff Lang62fce5b2016-09-30 10:46:35 -04001908 if (!ValidateRobustBufferSize(context, bufSize, *length))
1909 {
1910 return false;
1911 }
1912
1913 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001914}
1915
Olli Etuaho41997e72016-03-10 13:38:39 +02001916bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917{
1918 if (!context->getExtensions().occlusionQueryBoolean &&
1919 !context->getExtensions().disjointTimerQuery)
1920 {
Jamie Madill437fa652016-05-03 15:13:24 -04001921 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001922 return false;
1923 }
1924
Olli Etuaho41997e72016-03-10 13:38:39 +02001925 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926}
1927
Olli Etuaho41997e72016-03-10 13:38:39 +02001928bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929{
1930 if (!context->getExtensions().occlusionQueryBoolean &&
1931 !context->getExtensions().disjointTimerQuery)
1932 {
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001934 return false;
1935 }
1936
Olli Etuaho41997e72016-03-10 13:38:39 +02001937 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001938}
1939
1940bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001941{
1942 if (!ValidQueryType(context, target))
1943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001945 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001946 }
1947
1948 if (id == 0)
1949 {
Jamie Madill437fa652016-05-03 15:13:24 -04001950 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001951 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001952 }
1953
1954 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1955 // of zero, if the active query object name for <target> is non-zero (for the
1956 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1957 // the active query for either target is non-zero), if <id> is the name of an
1958 // existing query object whose type does not match <target>, or if <id> is the
1959 // active query object name for any query type, the error INVALID_OPERATION is
1960 // generated.
1961
1962 // Ensure no other queries are active
1963 // NOTE: If other queries than occlusion are supported, we will need to check
1964 // separately that:
1965 // a) The query ID passed is not the current active query for any target/type
1966 // b) There are no active queries for the requested target (and in the case
1967 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1968 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001969
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001970 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001973 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001974 }
1975
1976 Query *queryObject = context->getQuery(id, true, target);
1977
1978 // check that name was obtained with glGenQueries
1979 if (!queryObject)
1980 {
Jamie Madill437fa652016-05-03 15:13:24 -04001981 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001982 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001983 }
1984
1985 // check for type mismatch
1986 if (queryObject->getType() != target)
1987 {
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001989 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001990 }
1991
1992 return true;
1993}
1994
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001995bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1996{
1997 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001998 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002001 return false;
2002 }
2003
2004 return ValidateBeginQueryBase(context, target, id);
2005}
2006
2007bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002008{
2009 if (!ValidQueryType(context, target))
2010 {
Jamie Madill437fa652016-05-03 15:13:24 -04002011 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002012 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002013 }
2014
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002015 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002016
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002017 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002020 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002021 }
2022
Jamie Madill45c785d2014-05-13 14:09:34 -04002023 return true;
2024}
2025
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002026bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2027{
2028 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002029 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002030 {
Jamie Madill437fa652016-05-03 15:13:24 -04002031 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032 return false;
2033 }
2034
2035 return ValidateEndQueryBase(context, target);
2036}
2037
2038bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2039{
2040 if (!context->getExtensions().disjointTimerQuery)
2041 {
Jamie Madill437fa652016-05-03 15:13:24 -04002042 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002043 return false;
2044 }
2045
2046 if (target != GL_TIMESTAMP_EXT)
2047 {
Jamie Madill437fa652016-05-03 15:13:24 -04002048 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002049 return false;
2050 }
2051
2052 Query *queryObject = context->getQuery(id, true, target);
2053 if (queryObject == nullptr)
2054 {
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056 return false;
2057 }
2058
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002059 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002060 {
Jamie Madill437fa652016-05-03 15:13:24 -04002061 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002062 return false;
2063 }
2064
2065 return true;
2066}
2067
Geoff Lang2186c382016-10-14 10:54:54 -04002068bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002069{
Geoff Lang2186c382016-10-14 10:54:54 -04002070 if (numParams)
2071 {
2072 *numParams = 0;
2073 }
2074
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002075 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2076 {
Jamie Madill437fa652016-05-03 15:13:24 -04002077 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002078 return false;
2079 }
2080
2081 switch (pname)
2082 {
2083 case GL_CURRENT_QUERY_EXT:
2084 if (target == GL_TIMESTAMP_EXT)
2085 {
Jamie Madill437fa652016-05-03 15:13:24 -04002086 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002087 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2088 return false;
2089 }
2090 break;
2091 case GL_QUERY_COUNTER_BITS_EXT:
2092 if (!context->getExtensions().disjointTimerQuery ||
2093 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002096 return false;
2097 }
2098 break;
2099 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002101 return false;
2102 }
2103
Geoff Lang2186c382016-10-14 10:54:54 -04002104 if (numParams)
2105 {
2106 // All queries return only one value
2107 *numParams = 1;
2108 }
2109
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002110 return true;
2111}
2112
2113bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2114{
2115 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002116 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002117 {
Jamie Madill437fa652016-05-03 15:13:24 -04002118 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119 return false;
2120 }
2121
Geoff Lang2186c382016-10-14 10:54:54 -04002122 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002123}
2124
Geoff Lang2186c382016-10-14 10:54:54 -04002125bool ValidateGetQueryivRobustANGLE(Context *context,
2126 GLenum target,
2127 GLenum pname,
2128 GLsizei bufSize,
2129 GLsizei *length,
2130 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002131{
Geoff Lang2186c382016-10-14 10:54:54 -04002132 if (!ValidateRobustEntryPoint(context, bufSize))
2133 {
2134 return false;
2135 }
2136
2137 if (!ValidateGetQueryivBase(context, target, pname, length))
2138 {
2139 return false;
2140 }
2141
2142 if (!ValidateRobustBufferSize(context, bufSize, *length))
2143 {
2144 return false;
2145 }
2146
2147 return true;
2148}
2149
2150bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2151{
2152 if (numParams)
2153 {
2154 *numParams = 0;
2155 }
2156
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002157 Query *queryObject = context->getQuery(id, false, GL_NONE);
2158
2159 if (!queryObject)
2160 {
Jamie Madill437fa652016-05-03 15:13:24 -04002161 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002162 return false;
2163 }
2164
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002165 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002166 {
Jamie Madill437fa652016-05-03 15:13:24 -04002167 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002168 return false;
2169 }
2170
2171 switch (pname)
2172 {
2173 case GL_QUERY_RESULT_EXT:
2174 case GL_QUERY_RESULT_AVAILABLE_EXT:
2175 break;
2176
2177 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002179 return false;
2180 }
2181
Geoff Lang2186c382016-10-14 10:54:54 -04002182 if (numParams)
2183 {
2184 *numParams = 1;
2185 }
2186
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002187 return true;
2188}
2189
2190bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2191{
2192 if (!context->getExtensions().disjointTimerQuery)
2193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002195 return false;
2196 }
Geoff Lang2186c382016-10-14 10:54:54 -04002197 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2198}
2199
2200bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2201 GLuint id,
2202 GLenum pname,
2203 GLsizei bufSize,
2204 GLsizei *length,
2205 GLint *params)
2206{
2207 if (!context->getExtensions().disjointTimerQuery)
2208 {
2209 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2210 return false;
2211 }
2212
2213 if (!ValidateRobustEntryPoint(context, bufSize))
2214 {
2215 return false;
2216 }
2217
2218 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2219 {
2220 return false;
2221 }
2222
2223 if (!ValidateRobustBufferSize(context, bufSize, *length))
2224 {
2225 return false;
2226 }
2227
2228 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002229}
2230
2231bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2232{
2233 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002234 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002235 {
Jamie Madill437fa652016-05-03 15:13:24 -04002236 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002237 return false;
2238 }
Geoff Lang2186c382016-10-14 10:54:54 -04002239 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2240}
2241
2242bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2243 GLuint id,
2244 GLenum pname,
2245 GLsizei bufSize,
2246 GLsizei *length,
2247 GLuint *params)
2248{
2249 if (!context->getExtensions().disjointTimerQuery &&
2250 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2251 {
2252 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2253 return false;
2254 }
2255
2256 if (!ValidateRobustEntryPoint(context, bufSize))
2257 {
2258 return false;
2259 }
2260
2261 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2262 {
2263 return false;
2264 }
2265
2266 if (!ValidateRobustBufferSize(context, bufSize, *length))
2267 {
2268 return false;
2269 }
2270
2271 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002272}
2273
2274bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2275{
2276 if (!context->getExtensions().disjointTimerQuery)
2277 {
Jamie Madill437fa652016-05-03 15:13:24 -04002278 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002279 return false;
2280 }
Geoff Lang2186c382016-10-14 10:54:54 -04002281 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2282}
2283
2284bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2285 GLuint id,
2286 GLenum pname,
2287 GLsizei bufSize,
2288 GLsizei *length,
2289 GLint64 *params)
2290{
2291 if (!context->getExtensions().disjointTimerQuery)
2292 {
2293 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2294 return false;
2295 }
2296
2297 if (!ValidateRobustEntryPoint(context, bufSize))
2298 {
2299 return false;
2300 }
2301
2302 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2303 {
2304 return false;
2305 }
2306
2307 if (!ValidateRobustBufferSize(context, bufSize, *length))
2308 {
2309 return false;
2310 }
2311
2312 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002313}
2314
2315bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2316{
2317 if (!context->getExtensions().disjointTimerQuery)
2318 {
Jamie Madill437fa652016-05-03 15:13:24 -04002319 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002320 return false;
2321 }
Geoff Lang2186c382016-10-14 10:54:54 -04002322 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2323}
2324
2325bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2326 GLuint id,
2327 GLenum pname,
2328 GLsizei bufSize,
2329 GLsizei *length,
2330 GLuint64 *params)
2331{
2332 if (!context->getExtensions().disjointTimerQuery)
2333 {
2334 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2335 return false;
2336 }
2337
2338 if (!ValidateRobustEntryPoint(context, bufSize))
2339 {
2340 return false;
2341 }
2342
2343 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2344 {
2345 return false;
2346 }
2347
2348 if (!ValidateRobustBufferSize(context, bufSize, *length))
2349 {
2350 return false;
2351 }
2352
2353 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002354}
2355
Jamie Madill62d31cb2015-09-11 13:25:51 -04002356static bool ValidateUniformCommonBase(gl::Context *context,
2357 GLenum targetUniformType,
2358 GLint location,
2359 GLsizei count,
2360 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002361{
2362 if (count < 0)
2363 {
Jamie Madill437fa652016-05-03 15:13:24 -04002364 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002365 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002366 }
2367
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002368 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002369 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002370 {
Jamie Madill437fa652016-05-03 15:13:24 -04002371 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002372 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002373 }
2374
Geoff Langd8605522016-04-13 10:19:12 -04002375 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002376 {
2377 // Silently ignore the uniform command
2378 return false;
2379 }
2380
Geoff Lang7dd2e102014-11-10 15:19:26 -05002381 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002382 {
Jamie Madill437fa652016-05-03 15:13:24 -04002383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002384 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002385 }
2386
Jamie Madill62d31cb2015-09-11 13:25:51 -04002387 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002388
2389 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002390 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002391 {
Jamie Madill437fa652016-05-03 15:13:24 -04002392 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002394 }
2395
Jamie Madill62d31cb2015-09-11 13:25:51 -04002396 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002397 return true;
2398}
2399
Jamie Madillaa981bd2014-05-20 10:55:55 -04002400bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2401{
2402 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002403 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2404 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002405 {
Jamie Madill437fa652016-05-03 15:13:24 -04002406 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002408 }
2409
Jamie Madill62d31cb2015-09-11 13:25:51 -04002410 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002411 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2412 {
2413 return false;
2414 }
2415
Jamie Madillf2575982014-06-25 16:04:54 -04002416 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002417 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002418 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2419 {
Jamie Madill437fa652016-05-03 15:13:24 -04002420 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002422 }
2423
2424 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002425}
2426
2427bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2428 GLboolean transpose)
2429{
2430 // Check for ES3 uniform entry points
2431 int rows = VariableRowCount(matrixType);
2432 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002433 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002434 {
Jamie Madill437fa652016-05-03 15:13:24 -04002435 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002436 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002437 }
2438
Martin Radev1be913c2016-07-11 17:59:16 +03002439 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002440 {
Jamie Madill437fa652016-05-03 15:13:24 -04002441 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002442 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002443 }
2444
Jamie Madill62d31cb2015-09-11 13:25:51 -04002445 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002446 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2447 {
2448 return false;
2449 }
2450
2451 if (uniform->type != matrixType)
2452 {
Jamie Madill437fa652016-05-03 15:13:24 -04002453 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002455 }
2456
2457 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002458}
2459
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002460bool ValidateStateQuery(ValidationContext *context,
2461 GLenum pname,
2462 GLenum *nativeType,
2463 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002464{
2465 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2466 {
Jamie Madill437fa652016-05-03 15:13:24 -04002467 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002468 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002469 }
2470
Jamie Madill0af26e12015-03-05 19:54:33 -05002471 const Caps &caps = context->getCaps();
2472
Jamie Madill893ab082014-05-16 16:56:10 -04002473 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2474 {
2475 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2476
Jamie Madill0af26e12015-03-05 19:54:33 -05002477 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002478 {
Jamie Madill437fa652016-05-03 15:13:24 -04002479 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002480 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002481 }
2482 }
2483
2484 switch (pname)
2485 {
2486 case GL_TEXTURE_BINDING_2D:
2487 case GL_TEXTURE_BINDING_CUBE_MAP:
2488 case GL_TEXTURE_BINDING_3D:
2489 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002490 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002491 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002492 if (!context->getExtensions().eglStreamConsumerExternal &&
2493 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002494 {
John Bauman18319182016-09-28 14:22:27 -07002495 context->handleError(Error(GL_INVALID_ENUM,
2496 "Neither NV_EGL_stream_consumer_external nor "
2497 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002498 return false;
2499 }
2500 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002501
2502 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2503 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2504 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002505 if (context->getGLState().getReadFramebuffer()->checkStatus(
2506 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002507 {
Jamie Madill437fa652016-05-03 15:13:24 -04002508 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002509 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002510 }
2511
Jamie Madill51f40ec2016-06-15 14:06:00 -04002512 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2513 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002514
2515 if (framebuffer->getReadBufferState() == GL_NONE)
2516 {
2517 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2518 return false;
2519 }
2520
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002521 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002522 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002523 {
Jamie Madill437fa652016-05-03 15:13:24 -04002524 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002526 }
2527 }
2528 break;
2529
2530 default:
2531 break;
2532 }
2533
2534 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002535 if (*numParams == 0)
2536 {
2537 return false;
2538 }
2539
2540 return true;
2541}
2542
2543bool ValidateRobustStateQuery(ValidationContext *context,
2544 GLenum pname,
2545 GLsizei bufSize,
2546 GLenum *nativeType,
2547 unsigned int *numParams)
2548{
2549 if (!ValidateRobustEntryPoint(context, bufSize))
2550 {
2551 return false;
2552 }
2553
2554 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2555 {
2556 return false;
2557 }
2558
2559 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002560 {
2561 return false;
2562 }
2563
2564 return true;
2565}
2566
Jamie Madillc29968b2016-01-20 11:17:23 -05002567bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2568 GLenum target,
2569 GLint level,
2570 GLenum internalformat,
2571 bool isSubImage,
2572 GLint xoffset,
2573 GLint yoffset,
2574 GLint zoffset,
2575 GLint x,
2576 GLint y,
2577 GLsizei width,
2578 GLsizei height,
2579 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002580 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002581{
Jamie Madill560a8d82014-05-21 13:06:20 -04002582 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2583 {
Jamie Madill437fa652016-05-03 15:13:24 -04002584 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002585 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 }
2587
2588 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2589 {
Jamie Madill437fa652016-05-03 15:13:24 -04002590 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002591 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002592 }
2593
2594 if (border != 0)
2595 {
Jamie Madill437fa652016-05-03 15:13:24 -04002596 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002597 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002598 }
2599
2600 if (!ValidMipLevel(context, target, level))
2601 {
Jamie Madill437fa652016-05-03 15:13:24 -04002602 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002603 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002604 }
2605
Jamie Madill51f40ec2016-06-15 14:06:00 -04002606 const auto &state = context->getGLState();
2607 auto readFramebuffer = state.getReadFramebuffer();
2608 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002609 {
Jamie Madill437fa652016-05-03 15:13:24 -04002610 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002611 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002612 }
2613
Jamie Madill51f40ec2016-06-15 14:06:00 -04002614 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002615 {
Jamie Madill437fa652016-05-03 15:13:24 -04002616 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002617 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002618 }
2619
Martin Radev138064f2016-07-15 12:03:41 +03002620 if (readFramebuffer->getReadBufferState() == GL_NONE)
2621 {
2622 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2623 return false;
2624 }
2625
Geoff Langaae65a42014-05-26 12:43:44 -04002626 const gl::Caps &caps = context->getCaps();
2627
Geoff Langaae65a42014-05-26 12:43:44 -04002628 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002629 switch (target)
2630 {
2631 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002632 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002633 break;
2634
2635 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2636 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2637 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2638 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2639 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2640 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002641 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002642 break;
2643
2644 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002645 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002646 break;
2647
2648 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002649 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002650 break;
2651
2652 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002653 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002654 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002655 }
2656
Jamie Madillc29968b2016-01-20 11:17:23 -05002657 gl::Texture *texture =
2658 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002659 if (!texture)
2660 {
Jamie Madill437fa652016-05-03 15:13:24 -04002661 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002662 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002663 }
2664
Geoff Lang69cce582015-09-17 13:20:36 -04002665 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002666 {
Jamie Madill437fa652016-05-03 15:13:24 -04002667 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002668 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002669 }
2670
Geoff Lang5d601382014-07-22 15:14:06 -04002671 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2672
2673 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002674 {
Jamie Madill437fa652016-05-03 15:13:24 -04002675 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002676 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002677 }
2678
Geoff Langa9be0dc2014-12-17 12:34:40 -05002679 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002680 {
Jamie Madill437fa652016-05-03 15:13:24 -04002681 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002682 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002683 }
2684
2685 if (isSubImage)
2686 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002687 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2688 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2689 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002690 {
Jamie Madill437fa652016-05-03 15:13:24 -04002691 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002692 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002693 }
2694 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002695 else
2696 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002697 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002698 {
Jamie Madill437fa652016-05-03 15:13:24 -04002699 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002701 }
2702
Martin Radev1be913c2016-07-11 17:59:16 +03002703 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002704 {
Jamie Madill437fa652016-05-03 15:13:24 -04002705 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002707 }
2708
2709 int maxLevelDimension = (maxDimension >> level);
2710 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2711 {
Jamie Madill437fa652016-05-03 15:13:24 -04002712 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002713 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002714 }
2715 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002716
Jamie Madill0c8abca2016-07-22 20:21:26 -04002717 if (textureFormatOut)
2718 {
2719 *textureFormatOut = texture->getFormat(target, level);
2720 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002721 return true;
2722}
2723
Jamie Madillf25855c2015-11-03 11:06:18 -05002724static bool ValidateDrawBase(ValidationContext *context,
2725 GLenum mode,
2726 GLsizei count,
2727 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002728{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002729 switch (mode)
2730 {
2731 case GL_POINTS:
2732 case GL_LINES:
2733 case GL_LINE_LOOP:
2734 case GL_LINE_STRIP:
2735 case GL_TRIANGLES:
2736 case GL_TRIANGLE_STRIP:
2737 case GL_TRIANGLE_FAN:
2738 break;
2739 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002740 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002741 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002742 }
2743
Jamie Madill250d33f2014-06-06 17:09:03 -04002744 if (count < 0)
2745 {
Jamie Madill437fa652016-05-03 15:13:24 -04002746 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002747 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002748 }
2749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002750 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002751
Jamie Madill250d33f2014-06-06 17:09:03 -04002752 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002753 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002754 {
Jamie Madill437fa652016-05-03 15:13:24 -04002755 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002756 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002757 }
2758
Jamie Madill51f40ec2016-06-15 14:06:00 -04002759 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002760 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002761 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002762 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2763 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2764 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2765 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2766 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2767 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002768 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002769 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2770 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002771 {
2772 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2773 // Section 6.10 of the WebGL 1.0 spec
2774 ERR(
2775 "This ANGLE implementation does not support separate front/back stencil "
2776 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002777 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002778 return false;
2779 }
Jamie Madillac528012014-06-20 13:21:23 -04002780 }
2781
Jamie Madill51f40ec2016-06-15 14:06:00 -04002782 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002783 {
Jamie Madill437fa652016-05-03 15:13:24 -04002784 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002785 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002786 }
2787
Geoff Lang7dd2e102014-11-10 15:19:26 -05002788 gl::Program *program = state.getProgram();
2789 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002790 {
Jamie Madill437fa652016-05-03 15:13:24 -04002791 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002792 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002793 }
2794
Geoff Lang7dd2e102014-11-10 15:19:26 -05002795 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002796 {
Jamie Madill437fa652016-05-03 15:13:24 -04002797 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002798 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002799 }
2800
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002801 // Uniform buffer validation
2802 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2803 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002804 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002805 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002806 const OffsetBindingPointer<Buffer> &uniformBuffer =
2807 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002808
Geoff Lang5d124a62015-09-15 13:03:27 -04002809 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002810 {
2811 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002812 context->handleError(
2813 Error(GL_INVALID_OPERATION,
2814 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002815 return false;
2816 }
2817
Geoff Lang5d124a62015-09-15 13:03:27 -04002818 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002819 if (uniformBufferSize == 0)
2820 {
2821 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002822 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002823 }
2824
Jamie Madill62d31cb2015-09-11 13:25:51 -04002825 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002826 {
2827 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002828 context->handleError(
2829 Error(GL_INVALID_OPERATION,
2830 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002831 return false;
2832 }
2833 }
2834
Jamie Madill250d33f2014-06-06 17:09:03 -04002835 // No-op if zero count
2836 return (count > 0);
2837}
2838
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002839bool ValidateDrawArrays(ValidationContext *context,
2840 GLenum mode,
2841 GLint first,
2842 GLsizei count,
2843 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002844{
Jamie Madillfd716582014-06-06 17:09:04 -04002845 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002846 {
Jamie Madill437fa652016-05-03 15:13:24 -04002847 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002849 }
2850
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002851 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002852 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002853 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2854 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002855 {
2856 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2857 // that does not match the current transform feedback object's draw mode (if transform feedback
2858 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002859 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002860 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002861 }
2862
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002863 if (!ValidateDrawBase(context, mode, count, primcount))
2864 {
2865 return false;
2866 }
2867
2868 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002869 {
2870 return false;
2871 }
2872
2873 return true;
2874}
2875
Geoff Langb1196682014-07-23 13:47:29 -04002876bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002877{
2878 if (primcount < 0)
2879 {
Jamie Madill437fa652016-05-03 15:13:24 -04002880 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002881 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002882 }
2883
Jamie Madill2b976812014-08-25 15:47:49 -04002884 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002885 {
2886 return false;
2887 }
2888
2889 // No-op if zero primitive count
2890 return (primcount > 0);
2891}
2892
Geoff Lang87a93302014-09-16 13:29:43 -04002893static bool ValidateDrawInstancedANGLE(Context *context)
2894{
2895 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002896 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002897
Geoff Lang7dd2e102014-11-10 15:19:26 -05002898 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002899
2900 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002901 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002902 {
2903 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002904 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002905 {
2906 return true;
2907 }
2908 }
2909
Jamie Madill437fa652016-05-03 15:13:24 -04002910 context->handleError(Error(GL_INVALID_OPERATION,
2911 "ANGLE_instanced_arrays requires that at least one active attribute"
2912 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002913 return false;
2914}
2915
2916bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2917{
2918 if (!ValidateDrawInstancedANGLE(context))
2919 {
2920 return false;
2921 }
2922
2923 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2924}
2925
Jamie Madillf25855c2015-11-03 11:06:18 -05002926bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002927 GLenum mode,
2928 GLsizei count,
2929 GLenum type,
2930 const GLvoid *indices,
2931 GLsizei primcount,
2932 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002933{
Jamie Madill250d33f2014-06-06 17:09:03 -04002934 switch (type)
2935 {
2936 case GL_UNSIGNED_BYTE:
2937 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002938 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002939 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002940 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2941 {
2942 context->handleError(Error(GL_INVALID_ENUM));
2943 return false;
2944 }
2945 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002946 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002947 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002948 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002949 }
2950
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002951 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002952
2953 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002954 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002955 {
2956 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2957 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002958 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002959 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002960 }
2961
2962 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002963 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002964 {
Jamie Madill437fa652016-05-03 15:13:24 -04002965 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002966 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002967 }
2968
Jamie Madill2b976812014-08-25 15:47:49 -04002969 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002970 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002971 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002972 {
Jamie Madill437fa652016-05-03 15:13:24 -04002973 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002974 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002975 }
2976
Jamie Madillae3000b2014-08-25 15:47:51 -04002977 if (elementArrayBuffer)
2978 {
2979 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2980
2981 GLint64 offset = reinterpret_cast<GLint64>(indices);
2982 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2983
2984 // check for integer overflows
2985 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2986 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2987 {
Jamie Madill437fa652016-05-03 15:13:24 -04002988 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002989 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002990 }
2991
2992 // Check for reading past the end of the bound buffer object
2993 if (byteCount > elementArrayBuffer->getSize())
2994 {
Jamie Madill437fa652016-05-03 15:13:24 -04002995 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002996 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002997 }
2998 }
2999 else if (!indices)
3000 {
3001 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003002 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003004 }
3005
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003006 if (!ValidateDrawBase(context, mode, count, primcount))
3007 {
3008 return false;
3009 }
3010
Jamie Madill2b976812014-08-25 15:47:49 -04003011 // Use max index to validate if our vertex buffers are large enough for the pull.
3012 // TODO: offer fast path, with disabled index validation.
3013 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3014 if (elementArrayBuffer)
3015 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003016 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003017 Error error =
3018 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3019 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003020 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003021 {
Jamie Madill437fa652016-05-03 15:13:24 -04003022 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003023 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003024 }
3025 }
3026 else
3027 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003028 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003029 }
3030
Jamie Madille79b1e12015-11-04 16:36:37 -05003031 // If we use an index greater than our maximum supported index range, return an error.
3032 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3033 // return an error if possible here.
3034 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3035 {
Jamie Madill437fa652016-05-03 15:13:24 -04003036 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003037 return false;
3038 }
3039
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003040 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003041 {
3042 return false;
3043 }
3044
Geoff Lang3edfe032015-09-04 16:38:24 -04003045 // No op if there are no real indices in the index data (all are primitive restart).
3046 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003047}
3048
Geoff Langb1196682014-07-23 13:47:29 -04003049bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003050 GLenum mode,
3051 GLsizei count,
3052 GLenum type,
3053 const GLvoid *indices,
3054 GLsizei primcount,
3055 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003056{
3057 if (primcount < 0)
3058 {
Jamie Madill437fa652016-05-03 15:13:24 -04003059 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003060 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003061 }
3062
Jamie Madill2b976812014-08-25 15:47:49 -04003063 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003064 {
3065 return false;
3066 }
3067
3068 // No-op zero primitive count
3069 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003070}
3071
Geoff Lang3edfe032015-09-04 16:38:24 -04003072bool ValidateDrawElementsInstancedANGLE(Context *context,
3073 GLenum mode,
3074 GLsizei count,
3075 GLenum type,
3076 const GLvoid *indices,
3077 GLsizei primcount,
3078 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003079{
3080 if (!ValidateDrawInstancedANGLE(context))
3081 {
3082 return false;
3083 }
3084
3085 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3086}
3087
Geoff Langb1196682014-07-23 13:47:29 -04003088bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003089 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003090{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003091 if (!ValidFramebufferTarget(target))
3092 {
Jamie Madill437fa652016-05-03 15:13:24 -04003093 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003094 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003095 }
3096
3097 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003098 {
3099 return false;
3100 }
3101
Jamie Madill55ec3b12014-07-03 10:38:57 -04003102 if (texture != 0)
3103 {
3104 gl::Texture *tex = context->getTexture(texture);
3105
3106 if (tex == NULL)
3107 {
Jamie Madill437fa652016-05-03 15:13:24 -04003108 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003109 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003110 }
3111
3112 if (level < 0)
3113 {
Jamie Madill437fa652016-05-03 15:13:24 -04003114 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003115 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003116 }
3117 }
3118
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003119 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003120 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003121
Jamie Madill84115c92015-04-23 15:00:07 -04003122 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003123 {
Jamie Madill437fa652016-05-03 15:13:24 -04003124 context->handleError(
3125 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003127 }
3128
3129 return true;
3130}
3131
Geoff Langb1196682014-07-23 13:47:29 -04003132bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003133 GLenum textarget, GLuint texture, GLint level)
3134{
Geoff Lang95663912015-04-02 15:54:45 -04003135 // 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 +03003136 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3137 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003138 {
Jamie Madill437fa652016-05-03 15:13:24 -04003139 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003140 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003141 }
3142
3143 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003144 {
3145 return false;
3146 }
3147
Jamie Madill55ec3b12014-07-03 10:38:57 -04003148 if (texture != 0)
3149 {
3150 gl::Texture *tex = context->getTexture(texture);
3151 ASSERT(tex);
3152
Jamie Madill2a6564e2014-07-11 09:53:19 -04003153 const gl::Caps &caps = context->getCaps();
3154
Jamie Madill55ec3b12014-07-03 10:38:57 -04003155 switch (textarget)
3156 {
3157 case GL_TEXTURE_2D:
3158 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003159 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160 {
Jamie Madill437fa652016-05-03 15:13:24 -04003161 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003162 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 }
3164 if (tex->getTarget() != GL_TEXTURE_2D)
3165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003168 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003169 }
3170 break;
3171
3172 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3173 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3174 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3175 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3176 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3177 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3178 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003179 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003180 {
Jamie Madill437fa652016-05-03 15:13:24 -04003181 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003182 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003183 }
3184 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3185 {
Jamie Madill437fa652016-05-03 15:13:24 -04003186 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003187 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003188 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003189 }
3190 break;
3191
3192 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003193 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003195 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003196
Jamie Madilla3944d42016-07-22 22:13:26 -04003197 const Format &format = tex->getFormat(textarget, level);
3198 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003199 {
Jamie Madill437fa652016-05-03 15:13:24 -04003200 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003201 return false;
3202 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003203 }
3204
Jamie Madill570f7c82014-07-03 10:38:54 -04003205 return true;
3206}
3207
Geoff Langb1196682014-07-23 13:47:29 -04003208bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003209{
3210 if (program == 0)
3211 {
Jamie Madill437fa652016-05-03 15:13:24 -04003212 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003213 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003214 }
3215
Dian Xiang769769a2015-09-09 15:20:08 -07003216 gl::Program *programObject = GetValidProgram(context, program);
3217 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003218 {
3219 return false;
3220 }
3221
Jamie Madill0063c512014-08-25 15:47:53 -04003222 if (!programObject || !programObject->isLinked())
3223 {
Jamie Madill437fa652016-05-03 15:13:24 -04003224 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003226 }
3227
Geoff Lang7dd2e102014-11-10 15:19:26 -05003228 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003229 {
Jamie Madill437fa652016-05-03 15:13:24 -04003230 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003232 }
3233
Jamie Madill0063c512014-08-25 15:47:53 -04003234 return true;
3235}
3236
Geoff Langb1196682014-07-23 13:47:29 -04003237bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003238{
3239 return ValidateGetUniformBase(context, program, location);
3240}
3241
Geoff Langb1196682014-07-23 13:47:29 -04003242bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003243{
Jamie Madill78f41802014-08-25 15:47:55 -04003244 return ValidateGetUniformBase(context, program, location);
3245}
3246
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247static bool ValidateSizedGetUniform(Context *context,
3248 GLuint program,
3249 GLint location,
3250 GLsizei bufSize,
3251 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003252{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003253 if (length)
3254 {
3255 *length = 0;
3256 }
3257
Jamie Madill78f41802014-08-25 15:47:55 -04003258 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003259 {
Jamie Madill78f41802014-08-25 15:47:55 -04003260 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003261 }
3262
Geoff Langf41d0ee2016-10-07 13:04:23 -04003263 if (bufSize < 0)
3264 {
3265 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3266 return false;
3267 }
3268
Jamie Madilla502c742014-08-28 17:19:13 -04003269 gl::Program *programObject = context->getProgram(program);
3270 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003271
Jamie Madill78f41802014-08-25 15:47:55 -04003272 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003273 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3274 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003275 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003276 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003277 context->handleError(
3278 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003279 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003280 }
3281
Geoff Langf41d0ee2016-10-07 13:04:23 -04003282 if (length)
3283 {
3284 // Cast is safe because of comparison to bufSize.
3285 *length = static_cast<GLsizei>(requiredBytes);
3286 }
3287
Jamie Madill0063c512014-08-25 15:47:53 -04003288 return true;
3289}
3290
Geoff Langb1196682014-07-23 13:47:29 -04003291bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003292{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003293 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003294}
3295
Geoff Langb1196682014-07-23 13:47:29 -04003296bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003297{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003298 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3299}
3300
3301bool ValidateGetUniformfvRobustANGLE(Context *context,
3302 GLuint program,
3303 GLint location,
3304 GLsizei bufSize,
3305 GLsizei *length,
3306 GLfloat *params)
3307{
3308 if (!ValidateRobustEntryPoint(context, bufSize))
3309 {
3310 return false;
3311 }
3312
3313 // bufSize is validated in ValidateSizedGetUniform
3314 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3315}
3316
3317bool ValidateGetUniformivRobustANGLE(Context *context,
3318 GLuint program,
3319 GLint location,
3320 GLsizei bufSize,
3321 GLsizei *length,
3322 GLint *params)
3323{
3324 if (!ValidateRobustEntryPoint(context, bufSize))
3325 {
3326 return false;
3327 }
3328
3329 // bufSize is validated in ValidateSizedGetUniform
3330 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3331}
3332
3333bool ValidateGetUniformuivRobustANGLE(Context *context,
3334 GLuint program,
3335 GLint location,
3336 GLsizei bufSize,
3337 GLsizei *length,
3338 GLuint *params)
3339{
3340 if (!ValidateRobustEntryPoint(context, bufSize))
3341 {
3342 return false;
3343 }
3344
3345 if (context->getClientMajorVersion() < 3)
3346 {
3347 context->handleError(
3348 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3349 return false;
3350 }
3351
3352 // bufSize is validated in ValidateSizedGetUniform
3353 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003354}
3355
Austin Kinross08332632015-05-05 13:35:47 -07003356bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3357 const GLenum *attachments, bool defaultFramebuffer)
3358{
3359 if (numAttachments < 0)
3360 {
Jamie Madill437fa652016-05-03 15:13:24 -04003361 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003362 return false;
3363 }
3364
3365 for (GLsizei i = 0; i < numAttachments; ++i)
3366 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003367 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003368 {
3369 if (defaultFramebuffer)
3370 {
Jamie Madill437fa652016-05-03 15:13:24 -04003371 context->handleError(Error(
3372 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003373 return false;
3374 }
3375
3376 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3377 {
Jamie Madill437fa652016-05-03 15:13:24 -04003378 context->handleError(Error(GL_INVALID_OPERATION,
3379 "Requested color attachment is greater than the maximum "
3380 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003381 return false;
3382 }
3383 }
3384 else
3385 {
3386 switch (attachments[i])
3387 {
3388 case GL_DEPTH_ATTACHMENT:
3389 case GL_STENCIL_ATTACHMENT:
3390 case GL_DEPTH_STENCIL_ATTACHMENT:
3391 if (defaultFramebuffer)
3392 {
Jamie Madill437fa652016-05-03 15:13:24 -04003393 context->handleError(
3394 Error(GL_INVALID_ENUM,
3395 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003396 return false;
3397 }
3398 break;
3399 case GL_COLOR:
3400 case GL_DEPTH:
3401 case GL_STENCIL:
3402 if (!defaultFramebuffer)
3403 {
Jamie Madill437fa652016-05-03 15:13:24 -04003404 context->handleError(
3405 Error(GL_INVALID_ENUM,
3406 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003407 return false;
3408 }
3409 break;
3410 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003411 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003412 return false;
3413 }
3414 }
3415 }
3416
3417 return true;
3418}
3419
Austin Kinross6ee1e782015-05-29 17:05:37 -07003420bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3421{
3422 // Note that debug marker calls must not set error state
3423
3424 if (length < 0)
3425 {
3426 return false;
3427 }
3428
3429 if (marker == nullptr)
3430 {
3431 return false;
3432 }
3433
3434 return true;
3435}
3436
3437bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3438{
3439 // Note that debug marker calls must not set error state
3440
3441 if (length < 0)
3442 {
3443 return false;
3444 }
3445
3446 if (length > 0 && marker == nullptr)
3447 {
3448 return false;
3449 }
3450
3451 return true;
3452}
3453
Geoff Langdcab33b2015-07-21 13:03:16 -04003454bool ValidateEGLImageTargetTexture2DOES(Context *context,
3455 egl::Display *display,
3456 GLenum target,
3457 egl::Image *image)
3458{
Geoff Langa8406172015-07-21 16:53:39 -04003459 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3460 {
Jamie Madill437fa652016-05-03 15:13:24 -04003461 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003462 return false;
3463 }
3464
3465 switch (target)
3466 {
3467 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003468 if (!context->getExtensions().eglImage)
3469 {
3470 context->handleError(Error(
3471 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3472 }
3473 break;
3474
3475 case GL_TEXTURE_EXTERNAL_OES:
3476 if (!context->getExtensions().eglImageExternal)
3477 {
3478 context->handleError(Error(
3479 GL_INVALID_ENUM,
3480 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3481 }
Geoff Langa8406172015-07-21 16:53:39 -04003482 break;
3483
3484 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003485 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003486 return false;
3487 }
3488
3489 if (!display->isValidImage(image))
3490 {
Jamie Madill437fa652016-05-03 15:13:24 -04003491 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003492 return false;
3493 }
3494
3495 if (image->getSamples() > 0)
3496 {
Jamie Madill437fa652016-05-03 15:13:24 -04003497 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003498 "cannot create a 2D texture from a multisampled EGL image."));
3499 return false;
3500 }
3501
Jamie Madilla3944d42016-07-22 22:13:26 -04003502 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003503 if (!textureCaps.texturable)
3504 {
Jamie Madill437fa652016-05-03 15:13:24 -04003505 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003506 "EGL image internal format is not supported as a texture."));
3507 return false;
3508 }
3509
Geoff Langdcab33b2015-07-21 13:03:16 -04003510 return true;
3511}
3512
3513bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3514 egl::Display *display,
3515 GLenum target,
3516 egl::Image *image)
3517{
Geoff Langa8406172015-07-21 16:53:39 -04003518 if (!context->getExtensions().eglImage)
3519 {
Jamie Madill437fa652016-05-03 15:13:24 -04003520 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003521 return false;
3522 }
3523
3524 switch (target)
3525 {
3526 case GL_RENDERBUFFER:
3527 break;
3528
3529 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003530 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003531 return false;
3532 }
3533
3534 if (!display->isValidImage(image))
3535 {
Jamie Madill437fa652016-05-03 15:13:24 -04003536 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003537 return false;
3538 }
3539
Jamie Madilla3944d42016-07-22 22:13:26 -04003540 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003541 if (!textureCaps.renderable)
3542 {
Jamie Madill437fa652016-05-03 15:13:24 -04003543 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003544 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3545 return false;
3546 }
3547
Geoff Langdcab33b2015-07-21 13:03:16 -04003548 return true;
3549}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003550
3551bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3552{
Geoff Lang36167ab2015-12-07 10:27:14 -05003553 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003554 {
3555 // The default VAO should always exist
3556 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003557 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003558 return false;
3559 }
3560
3561 return true;
3562}
3563
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003564bool ValidateLinkProgram(Context *context, GLuint program)
3565{
3566 if (context->hasActiveTransformFeedback(program))
3567 {
3568 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003569 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003570 "Cannot link program while program is associated with an active "
3571 "transform feedback object."));
3572 return false;
3573 }
3574 return true;
3575}
3576
Geoff Langc5629752015-12-07 16:29:04 -05003577bool ValidateProgramBinaryBase(Context *context,
3578 GLuint program,
3579 GLenum binaryFormat,
3580 const void *binary,
3581 GLint length)
3582{
3583 Program *programObject = GetValidProgram(context, program);
3584 if (programObject == nullptr)
3585 {
3586 return false;
3587 }
3588
3589 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3590 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3591 programBinaryFormats.end())
3592 {
Jamie Madill437fa652016-05-03 15:13:24 -04003593 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003594 return false;
3595 }
3596
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003597 if (context->hasActiveTransformFeedback(program))
3598 {
3599 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003600 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003601 "Cannot change program binary while program is associated with "
3602 "an active transform feedback object."));
3603 return false;
3604 }
3605
Geoff Langc5629752015-12-07 16:29:04 -05003606 return true;
3607}
3608
3609bool ValidateGetProgramBinaryBase(Context *context,
3610 GLuint program,
3611 GLsizei bufSize,
3612 GLsizei *length,
3613 GLenum *binaryFormat,
3614 void *binary)
3615{
3616 Program *programObject = GetValidProgram(context, program);
3617 if (programObject == nullptr)
3618 {
3619 return false;
3620 }
3621
3622 if (!programObject->isLinked())
3623 {
Jamie Madill437fa652016-05-03 15:13:24 -04003624 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003625 return false;
3626 }
3627
3628 return true;
3629}
Jamie Madillc29968b2016-01-20 11:17:23 -05003630
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003631bool ValidateUseProgram(Context *context, GLuint program)
3632{
3633 if (program != 0)
3634 {
3635 Program *programObject = context->getProgram(program);
3636 if (!programObject)
3637 {
3638 // ES 3.1.0 section 7.3 page 72
3639 if (context->getShader(program))
3640 {
Jamie Madill437fa652016-05-03 15:13:24 -04003641 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003642 Error(GL_INVALID_OPERATION,
3643 "Attempted to use a single shader instead of a shader program."));
3644 return false;
3645 }
3646 else
3647 {
Jamie Madill437fa652016-05-03 15:13:24 -04003648 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003649 return false;
3650 }
3651 }
3652 if (!programObject->isLinked())
3653 {
Jamie Madill437fa652016-05-03 15:13:24 -04003654 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003655 return false;
3656 }
3657 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003658 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003659 {
3660 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003661 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003662 Error(GL_INVALID_OPERATION,
3663 "Cannot change active program while transform feedback is unpaused."));
3664 return false;
3665 }
3666
3667 return true;
3668}
3669
Jamie Madillc29968b2016-01-20 11:17:23 -05003670bool ValidateCopyTexImage2D(ValidationContext *context,
3671 GLenum target,
3672 GLint level,
3673 GLenum internalformat,
3674 GLint x,
3675 GLint y,
3676 GLsizei width,
3677 GLsizei height,
3678 GLint border)
3679{
Martin Radev1be913c2016-07-11 17:59:16 +03003680 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 {
3682 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3683 0, x, y, width, height, border);
3684 }
3685
Martin Radev1be913c2016-07-11 17:59:16 +03003686 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003687 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3688 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003689}
Jamie Madillc29968b2016-01-20 11:17:23 -05003690
3691bool ValidateFramebufferRenderbuffer(Context *context,
3692 GLenum target,
3693 GLenum attachment,
3694 GLenum renderbuffertarget,
3695 GLuint renderbuffer)
3696{
3697 if (!ValidFramebufferTarget(target) ||
3698 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3699 {
Jamie Madill437fa652016-05-03 15:13:24 -04003700 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003701 return false;
3702 }
3703
3704 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3705 renderbuffertarget, renderbuffer);
3706}
3707
3708bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3709{
3710 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3711 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3712 {
Jamie Madill437fa652016-05-03 15:13:24 -04003713 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003714 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3715 return false;
3716 }
3717
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003718 ASSERT(context->getGLState().getDrawFramebuffer());
3719 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003720 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3721
3722 // This should come first before the check for the default frame buffer
3723 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3724 // rather than INVALID_OPERATION
3725 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3726 {
3727 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3728
3729 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003730 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3731 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003732 {
3733 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003734 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3735 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3736 // 3.1 is still a bit ambiguous about the error, but future specs are
3737 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003738 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003739 return false;
3740 }
3741 else if (bufs[colorAttachment] >= maxColorAttachment)
3742 {
Jamie Madill437fa652016-05-03 15:13:24 -04003743 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003744 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003745 return false;
3746 }
3747 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3748 frameBufferId != 0)
3749 {
3750 // INVALID_OPERATION-GL is bound to buffer and ith argument
3751 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003752 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003753 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3754 return false;
3755 }
3756 }
3757
3758 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3759 // and n is not 1 or bufs is bound to value other than BACK and NONE
3760 if (frameBufferId == 0)
3761 {
3762 if (n != 1)
3763 {
Jamie Madill437fa652016-05-03 15:13:24 -04003764 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003765 "n must be 1 when GL is bound to the default framebuffer"));
3766 return false;
3767 }
3768
3769 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3770 {
Jamie Madill437fa652016-05-03 15:13:24 -04003771 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003772 GL_INVALID_OPERATION,
3773 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3774 return false;
3775 }
3776 }
3777
3778 return true;
3779}
3780
3781bool ValidateCopyTexSubImage2D(Context *context,
3782 GLenum target,
3783 GLint level,
3784 GLint xoffset,
3785 GLint yoffset,
3786 GLint x,
3787 GLint y,
3788 GLsizei width,
3789 GLsizei height)
3790{
Martin Radev1be913c2016-07-11 17:59:16 +03003791 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003792 {
3793 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3794 yoffset, x, y, width, height, 0);
3795 }
3796
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003797 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3798 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003799}
3800
Olli Etuaho4f667482016-03-30 15:56:35 +03003801bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3802{
3803 if (!ValidBufferTarget(context, target))
3804 {
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 return false;
3807 }
3808
3809 if (pname != GL_BUFFER_MAP_POINTER)
3810 {
Jamie Madill437fa652016-05-03 15:13:24 -04003811 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 return false;
3813 }
3814
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003815 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003816
3817 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3818 // target bound to zero generate an INVALID_OPERATION error."
3819 // GLES 3.1 section 6.6 explicitly specifies this error.
3820 if (!buffer)
3821 {
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3824 return false;
3825 }
3826
3827 return true;
3828}
3829
3830bool ValidateUnmapBufferBase(Context *context, GLenum target)
3831{
3832 if (!ValidBufferTarget(context, target))
3833 {
Jamie Madill437fa652016-05-03 15:13:24 -04003834 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 return false;
3836 }
3837
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003838 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003839
3840 if (buffer == nullptr || !buffer->isMapped())
3841 {
Jamie Madill437fa652016-05-03 15:13:24 -04003842 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 return false;
3844 }
3845
3846 return true;
3847}
3848
3849bool ValidateMapBufferRangeBase(Context *context,
3850 GLenum target,
3851 GLintptr offset,
3852 GLsizeiptr length,
3853 GLbitfield access)
3854{
3855 if (!ValidBufferTarget(context, target))
3856 {
Jamie Madill437fa652016-05-03 15:13:24 -04003857 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
3861 if (offset < 0 || length < 0)
3862 {
Jamie Madill437fa652016-05-03 15:13:24 -04003863 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 return false;
3865 }
3866
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003867 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003868
3869 if (!buffer)
3870 {
Jamie Madill437fa652016-05-03 15:13:24 -04003871 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003872 return false;
3873 }
3874
3875 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003876 CheckedNumeric<size_t> checkedOffset(offset);
3877 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003878
Jamie Madille2e406c2016-06-02 13:04:10 -04003879 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 {
Jamie Madill437fa652016-05-03 15:13:24 -04003881 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3883 return false;
3884 }
3885
3886 // Check for invalid bits in the mask
3887 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3888 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3889 GL_MAP_UNSYNCHRONIZED_BIT;
3890
3891 if (access & ~(allAccessBits))
3892 {
Jamie Madill437fa652016-05-03 15:13:24 -04003893 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 if (length == 0)
3898 {
Jamie Madill437fa652016-05-03 15:13:24 -04003899 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
3903 if (buffer->isMapped())
3904 {
Jamie Madill437fa652016-05-03 15:13:24 -04003905 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 return false;
3907 }
3908
3909 // Check for invalid bit combinations
3910 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3911 {
Jamie Madill437fa652016-05-03 15:13:24 -04003912 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003913 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3914 return false;
3915 }
3916
3917 GLbitfield writeOnlyBits =
3918 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3919
3920 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3921 {
Jamie Madill437fa652016-05-03 15:13:24 -04003922 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003923 "Invalid access bits when mapping buffer for reading: 0x%X.",
3924 access));
3925 return false;
3926 }
3927
3928 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3929 {
Jamie Madill437fa652016-05-03 15:13:24 -04003930 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 GL_INVALID_OPERATION,
3932 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3933 return false;
3934 }
3935 return true;
3936}
3937
3938bool ValidateFlushMappedBufferRangeBase(Context *context,
3939 GLenum target,
3940 GLintptr offset,
3941 GLsizeiptr length)
3942{
3943 if (offset < 0 || length < 0)
3944 {
Jamie Madill437fa652016-05-03 15:13:24 -04003945 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003946 return false;
3947 }
3948
3949 if (!ValidBufferTarget(context, target))
3950 {
Jamie Madill437fa652016-05-03 15:13:24 -04003951 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 return false;
3953 }
3954
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003955 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003956
3957 if (buffer == nullptr)
3958 {
Jamie Madill437fa652016-05-03 15:13:24 -04003959 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003960 return false;
3961 }
3962
3963 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3964 {
Jamie Madill437fa652016-05-03 15:13:24 -04003965 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003966 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3967 return false;
3968 }
3969
3970 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003971 CheckedNumeric<size_t> checkedOffset(offset);
3972 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003973
Jamie Madille2e406c2016-06-02 13:04:10 -04003974 if (!checkedSize.IsValid() ||
3975 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003976 {
Jamie Madill437fa652016-05-03 15:13:24 -04003977 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003978 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3979 return false;
3980 }
3981
3982 return true;
3983}
3984
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003985bool ValidateGenerateMipmap(Context *context, GLenum target)
3986{
3987 if (!ValidTextureTarget(context, target))
3988 {
3989 context->handleError(Error(GL_INVALID_ENUM));
3990 return false;
3991 }
3992
3993 Texture *texture = context->getTargetTexture(target);
3994
3995 if (texture == nullptr)
3996 {
3997 context->handleError(Error(GL_INVALID_OPERATION));
3998 return false;
3999 }
4000
4001 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4002
4003 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4004 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4005 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4006 {
4007 context->handleError(Error(GL_INVALID_OPERATION));
4008 return false;
4009 }
4010
Jamie Madilla3944d42016-07-22 22:13:26 -04004011 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4012 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4013 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004014
4015 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4016 // unsized formats or that are color renderable and filterable. Since we do not track if
4017 // the texture was created with sized or unsized format (only sized formats are stored),
4018 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4019 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4020 // textures since they're the only texture format that can be created with unsized formats
4021 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4022 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004023 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4024 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004025 {
4026 context->handleError(Error(GL_INVALID_OPERATION));
4027 return false;
4028 }
4029
4030 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004031 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004032 {
4033 context->handleError(Error(GL_INVALID_OPERATION));
4034 return false;
4035 }
4036
4037 // Non-power of 2 ES2 check
4038 if (!context->getExtensions().textureNPOT &&
4039 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4040 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4041 {
Martin Radev1be913c2016-07-11 17:59:16 +03004042 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004043 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
4044 context->handleError(Error(GL_INVALID_OPERATION));
4045 return false;
4046 }
4047
4048 // Cube completeness check
4049 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4050 {
4051 context->handleError(Error(GL_INVALID_OPERATION));
4052 return false;
4053 }
4054
4055 return true;
4056}
4057
Olli Etuaho41997e72016-03-10 13:38:39 +02004058bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4059{
4060 return ValidateGenOrDelete(context, n);
4061}
4062
4063bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4064{
4065 return ValidateGenOrDelete(context, n);
4066}
4067
4068bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4069{
4070 return ValidateGenOrDelete(context, n);
4071}
4072
4073bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4074{
4075 return ValidateGenOrDelete(context, n);
4076}
4077
4078bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4079{
4080 return ValidateGenOrDelete(context, n);
4081}
4082
4083bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4084{
4085 return ValidateGenOrDelete(context, n);
4086}
4087
4088bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4089{
4090 return ValidateGenOrDelete(context, n);
4091}
4092
4093bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4094{
4095 return ValidateGenOrDelete(context, n);
4096}
4097
4098bool ValidateGenOrDelete(Context *context, GLint n)
4099{
4100 if (n < 0)
4101 {
Jamie Madill437fa652016-05-03 15:13:24 -04004102 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004103 return false;
4104 }
4105 return true;
4106}
4107
Geoff Langf41a7152016-09-19 15:11:17 -04004108bool ValidateEnable(Context *context, GLenum cap)
4109{
4110 if (!ValidCap(context, cap, false))
4111 {
4112 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4113 return false;
4114 }
4115
4116 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4117 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4118 {
4119 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4120 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4121
4122 // We also output an error message to the debugger window if tracing is active, so that
4123 // developers can see the error message.
4124 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004125 return false;
4126 }
4127
4128 return true;
4129}
4130
4131bool ValidateDisable(Context *context, GLenum cap)
4132{
4133 if (!ValidCap(context, cap, false))
4134 {
4135 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4136 return false;
4137 }
4138
4139 return true;
4140}
4141
4142bool ValidateIsEnabled(Context *context, GLenum cap)
4143{
4144 if (!ValidCap(context, cap, true))
4145 {
4146 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4147 return false;
4148 }
4149
4150 return true;
4151}
4152
Geoff Langff5b2d52016-09-07 11:32:23 -04004153bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4154{
4155 if (!context->getExtensions().robustClientMemory)
4156 {
4157 context->handleError(
4158 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4159 return false;
4160 }
4161
4162 if (bufSize < 0)
4163 {
4164 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4165 return false;
4166 }
4167
4168 return true;
4169}
4170
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004171bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4172{
4173 if (bufSize < numParams)
4174 {
4175 context->handleError(Error(GL_INVALID_OPERATION,
4176 "%u parameters are required but %i were provided.", numParams,
4177 bufSize));
4178 return false;
4179 }
4180
4181 return true;
4182}
4183
Geoff Langff5b2d52016-09-07 11:32:23 -04004184bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4185 GLenum target,
4186 GLenum attachment,
4187 GLenum pname,
4188 GLsizei *numParams)
4189{
4190 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4191 *numParams = 1;
4192
4193 if (!ValidFramebufferTarget(target))
4194 {
4195 context->handleError(Error(GL_INVALID_ENUM));
4196 return false;
4197 }
4198
4199 int clientVersion = context->getClientMajorVersion();
4200
4201 switch (pname)
4202 {
4203 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4204 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4205 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4206 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4207 break;
4208
4209 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4210 if (clientVersion < 3 && !context->getExtensions().sRGB)
4211 {
4212 context->handleError(Error(GL_INVALID_ENUM));
4213 return false;
4214 }
4215 break;
4216
4217 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4218 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4219 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4220 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4221 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4222 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4223 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4224 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4225 if (clientVersion < 3)
4226 {
4227 context->handleError(Error(GL_INVALID_ENUM));
4228 return false;
4229 }
4230 break;
4231
4232 default:
4233 context->handleError(Error(GL_INVALID_ENUM));
4234 return false;
4235 }
4236
4237 // Determine if the attachment is a valid enum
4238 switch (attachment)
4239 {
4240 case GL_BACK:
4241 case GL_FRONT:
4242 case GL_DEPTH:
4243 case GL_STENCIL:
4244 case GL_DEPTH_STENCIL_ATTACHMENT:
4245 if (clientVersion < 3)
4246 {
4247 context->handleError(Error(GL_INVALID_ENUM));
4248 return false;
4249 }
4250 break;
4251
4252 case GL_DEPTH_ATTACHMENT:
4253 case GL_STENCIL_ATTACHMENT:
4254 break;
4255
4256 default:
4257 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4258 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4259 {
4260 context->handleError(Error(GL_INVALID_ENUM));
4261 return false;
4262 }
4263 break;
4264 }
4265
4266 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4267 ASSERT(framebuffer);
4268
4269 if (framebuffer->id() == 0)
4270 {
4271 if (clientVersion < 3)
4272 {
4273 context->handleError(Error(GL_INVALID_OPERATION));
4274 return false;
4275 }
4276
4277 switch (attachment)
4278 {
4279 case GL_BACK:
4280 case GL_DEPTH:
4281 case GL_STENCIL:
4282 break;
4283
4284 default:
4285 context->handleError(Error(GL_INVALID_OPERATION));
4286 return false;
4287 }
4288 }
4289 else
4290 {
4291 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4292 {
4293 // Valid attachment query
4294 }
4295 else
4296 {
4297 switch (attachment)
4298 {
4299 case GL_DEPTH_ATTACHMENT:
4300 case GL_STENCIL_ATTACHMENT:
4301 break;
4302
4303 case GL_DEPTH_STENCIL_ATTACHMENT:
4304 if (!framebuffer->hasValidDepthStencil())
4305 {
4306 context->handleError(Error(GL_INVALID_OPERATION));
4307 return false;
4308 }
4309 break;
4310
4311 default:
4312 context->handleError(Error(GL_INVALID_OPERATION));
4313 return false;
4314 }
4315 }
4316 }
4317
4318 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4319 if (attachmentObject)
4320 {
4321 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4322 attachmentObject->type() == GL_TEXTURE ||
4323 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4324
4325 switch (pname)
4326 {
4327 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4328 if (attachmentObject->type() != GL_RENDERBUFFER &&
4329 attachmentObject->type() != GL_TEXTURE)
4330 {
4331 context->handleError(Error(GL_INVALID_ENUM));
4332 return false;
4333 }
4334 break;
4335
4336 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4337 if (attachmentObject->type() != GL_TEXTURE)
4338 {
4339 context->handleError(Error(GL_INVALID_ENUM));
4340 return false;
4341 }
4342 break;
4343
4344 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4345 if (attachmentObject->type() != GL_TEXTURE)
4346 {
4347 context->handleError(Error(GL_INVALID_ENUM));
4348 return false;
4349 }
4350 break;
4351
4352 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4353 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4354 {
4355 context->handleError(Error(GL_INVALID_OPERATION));
4356 return false;
4357 }
4358 break;
4359
4360 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4361 if (attachmentObject->type() != GL_TEXTURE)
4362 {
4363 context->handleError(Error(GL_INVALID_ENUM));
4364 return false;
4365 }
4366 break;
4367
4368 default:
4369 break;
4370 }
4371 }
4372 else
4373 {
4374 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4375 // is NONE, then querying any other pname will generate INVALID_ENUM.
4376
4377 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4378 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4379 // INVALID_OPERATION for all other pnames
4380
4381 switch (pname)
4382 {
4383 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4384 break;
4385
4386 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4387 if (clientVersion < 3)
4388 {
4389 context->handleError(Error(GL_INVALID_ENUM));
4390 return false;
4391 }
4392 break;
4393
4394 default:
4395 if (clientVersion < 3)
4396 {
4397 context->handleError(Error(GL_INVALID_ENUM));
4398 return false;
4399 }
4400 else
4401 {
4402 context->handleError(Error(GL_INVALID_OPERATION));
4403 return false;
4404 }
4405 }
4406 }
4407
4408 return true;
4409}
4410
4411bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4412 GLenum target,
4413 GLenum attachment,
4414 GLenum pname,
4415 GLsizei bufSize,
4416 GLsizei *numParams)
4417{
4418 if (!ValidateRobustEntryPoint(context, bufSize))
4419 {
4420 return false;
4421 }
4422
4423 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4424 {
4425 return false;
4426 }
4427
4428 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4429 {
4430 return false;
4431 }
4432
4433 return true;
4434}
4435
4436bool ValidateGetBufferParameteriv(ValidationContext *context,
4437 GLenum target,
4438 GLenum pname,
4439 GLsizei *numParams)
4440{
4441 // Initialize result
4442 *numParams = 0;
4443
4444 if (!ValidBufferTarget(context, target))
4445 {
4446 context->handleError(Error(GL_INVALID_ENUM));
4447 return false;
4448 }
4449
4450 if (!ValidBufferParameter(context, pname, numParams))
4451 {
4452 context->handleError(Error(GL_INVALID_ENUM));
4453 return false;
4454 }
4455
4456 if (context->getGLState().getTargetBuffer(target) == nullptr)
4457 {
4458 // A null buffer means that "0" is bound to the requested buffer target
4459 context->handleError(Error(GL_INVALID_OPERATION));
4460 return false;
4461 }
4462
4463 return true;
4464}
4465
4466bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4467 GLenum target,
4468 GLenum pname,
4469 GLsizei bufSize,
4470 GLsizei *numParams)
4471{
4472 if (!ValidateRobustEntryPoint(context, bufSize))
4473 {
4474 return false;
4475 }
4476
4477 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
4478 {
4479 return false;
4480 }
4481
4482 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4483 {
4484 return false;
4485 }
4486
4487 return true;
4488}
4489
4490bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4491{
4492 // Currently, all GetProgramiv queries return 1 parameter
4493 *numParams = 1;
4494
4495 Program *programObject = GetValidProgram(context, program);
4496 if (!programObject)
4497 {
4498 return false;
4499 }
4500
4501 switch (pname)
4502 {
4503 case GL_DELETE_STATUS:
4504 case GL_LINK_STATUS:
4505 case GL_VALIDATE_STATUS:
4506 case GL_INFO_LOG_LENGTH:
4507 case GL_ATTACHED_SHADERS:
4508 case GL_ACTIVE_ATTRIBUTES:
4509 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4510 case GL_ACTIVE_UNIFORMS:
4511 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4512 break;
4513
4514 case GL_PROGRAM_BINARY_LENGTH:
4515 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4516 {
4517 context->handleError(Error(GL_INVALID_ENUM,
4518 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4519 "GL_OES_get_program_binary or ES 3.0."));
4520 return false;
4521 }
4522 break;
4523
4524 case GL_ACTIVE_UNIFORM_BLOCKS:
4525 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4526 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4527 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4528 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4529 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4530 if (context->getClientMajorVersion() < 3)
4531 {
4532 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4533 return false;
4534 }
4535 break;
4536
4537 default:
4538 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4539 return false;
4540 }
4541
4542 return true;
4543}
4544
4545bool ValidateGetProgramivRobustANGLE(Context *context,
4546 GLuint program,
4547 GLenum pname,
4548 GLsizei bufSize,
4549 GLsizei *numParams)
4550{
4551 if (!ValidateRobustEntryPoint(context, bufSize))
4552 {
4553 return false;
4554 }
4555
4556 if (!ValidateGetProgramiv(context, program, pname, numParams))
4557 {
4558 return false;
4559 }
4560
4561 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4562 {
4563 return false;
4564 }
4565
4566 return true;
4567}
4568
Geoff Lang740d9022016-10-07 11:20:52 -04004569bool ValidateGetRenderbufferParameteriv(Context *context,
4570 GLenum target,
4571 GLenum pname,
4572 GLint *params)
4573{
4574 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4575}
4576
4577bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4578 GLenum target,
4579 GLenum pname,
4580 GLsizei bufSize,
4581 GLsizei *length,
4582 GLint *params)
4583{
4584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
4588
4589 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4590 {
4591 return false;
4592 }
4593
4594 if (!ValidateRobustBufferSize(context, bufSize, *length))
4595 {
4596 return false;
4597 }
4598
4599 return true;
4600}
4601
Geoff Langd7d0ed32016-10-07 11:33:51 -04004602bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4603{
4604 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4605}
4606
4607bool ValidateGetShaderivRobustANGLE(Context *context,
4608 GLuint shader,
4609 GLenum pname,
4610 GLsizei bufSize,
4611 GLsizei *length,
4612 GLint *params)
4613{
4614 if (!ValidateRobustEntryPoint(context, bufSize))
4615 {
4616 return false;
4617 }
4618
4619 if (!ValidateGetShaderivBase(context, shader, pname, length))
4620 {
4621 return false;
4622 }
4623
4624 if (!ValidateRobustBufferSize(context, bufSize, *length))
4625 {
4626 return false;
4627 }
4628
4629 return true;
4630}
4631
Geoff Langc1984ed2016-10-07 12:41:00 -04004632bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4633{
4634 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4635}
4636
4637bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4638 GLenum target,
4639 GLenum pname,
4640 GLsizei bufSize,
4641 GLsizei *length,
4642 GLfloat *params)
4643{
4644 if (!ValidateRobustEntryPoint(context, bufSize))
4645 {
4646 return false;
4647 }
4648
4649 if (!ValidateGetTexParameterBase(context, target, pname, length))
4650 {
4651 return false;
4652 }
4653
4654 if (!ValidateRobustBufferSize(context, bufSize, *length))
4655 {
4656 return false;
4657 }
4658
4659 return true;
4660}
4661
4662bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4663{
4664 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4665}
4666
4667bool ValidateGetTexParameterivRobustANGLE(Context *context,
4668 GLenum target,
4669 GLenum pname,
4670 GLsizei bufSize,
4671 GLsizei *length,
4672 GLint *params)
4673{
4674 if (!ValidateRobustEntryPoint(context, bufSize))
4675 {
4676 return false;
4677 }
4678
4679 if (!ValidateGetTexParameterBase(context, target, pname, length))
4680 {
4681 return false;
4682 }
4683
4684 if (!ValidateRobustBufferSize(context, bufSize, *length))
4685 {
4686 return false;
4687 }
4688
4689 return true;
4690}
4691
4692bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4693{
4694 return ValidateTexParameterBase(context, target, pname, -1, &param);
4695}
4696
4697bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4698{
4699 return ValidateTexParameterBase(context, target, pname, -1, params);
4700}
4701
4702bool ValidateTexParameterfvRobustANGLE(Context *context,
4703 GLenum target,
4704 GLenum pname,
4705 GLsizei bufSize,
4706 const GLfloat *params)
4707{
4708 if (!ValidateRobustEntryPoint(context, bufSize))
4709 {
4710 return false;
4711 }
4712
4713 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4714}
4715
4716bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4717{
4718 return ValidateTexParameterBase(context, target, pname, -1, &param);
4719}
4720
4721bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4722{
4723 return ValidateTexParameterBase(context, target, pname, -1, params);
4724}
4725
4726bool ValidateTexParameterivRobustANGLE(Context *context,
4727 GLenum target,
4728 GLenum pname,
4729 GLsizei bufSize,
4730 const GLint *params)
4731{
4732 if (!ValidateRobustEntryPoint(context, bufSize))
4733 {
4734 return false;
4735 }
4736
4737 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4738}
4739
4740bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4741{
4742 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4743}
4744
4745bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4746 GLuint sampler,
4747 GLenum pname,
4748 GLuint bufSize,
4749 GLsizei *length,
4750 GLfloat *params)
4751{
4752 if (!ValidateRobustEntryPoint(context, bufSize))
4753 {
4754 return false;
4755 }
4756
4757 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4758 {
4759 return false;
4760 }
4761
4762 if (!ValidateRobustBufferSize(context, bufSize, *length))
4763 {
4764 return false;
4765 }
4766
4767 return true;
4768}
4769
4770bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4771{
4772 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4773}
4774
4775bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4776 GLuint sampler,
4777 GLenum pname,
4778 GLuint bufSize,
4779 GLsizei *length,
4780 GLint *params)
4781{
4782 if (!ValidateRobustEntryPoint(context, bufSize))
4783 {
4784 return false;
4785 }
4786
4787 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4788 {
4789 return false;
4790 }
4791
4792 if (!ValidateRobustBufferSize(context, bufSize, *length))
4793 {
4794 return false;
4795 }
4796
4797 return true;
4798}
4799
4800bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4801{
4802 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4803}
4804
4805bool ValidateSamplerParameterfv(Context *context,
4806 GLuint sampler,
4807 GLenum pname,
4808 const GLfloat *params)
4809{
4810 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4811}
4812
4813bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4814 GLuint sampler,
4815 GLenum pname,
4816 GLsizei bufSize,
4817 const GLfloat *params)
4818{
4819 if (!ValidateRobustEntryPoint(context, bufSize))
4820 {
4821 return false;
4822 }
4823
4824 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4825}
4826
4827bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4828{
4829 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4830}
4831
4832bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4833{
4834 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4835}
4836
4837bool ValidateSamplerParameterivRobustANGLE(Context *context,
4838 GLuint sampler,
4839 GLenum pname,
4840 GLsizei bufSize,
4841 const GLint *params)
4842{
4843 if (!ValidateRobustEntryPoint(context, bufSize))
4844 {
4845 return false;
4846 }
4847
4848 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4849}
4850
Geoff Lang0b031062016-10-13 14:30:04 -04004851bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
4852{
4853 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4854}
4855
4856bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4857 GLuint index,
4858 GLenum pname,
4859 GLsizei bufSize,
4860 GLsizei *length,
4861 GLfloat *params)
4862{
4863 if (!ValidateRobustEntryPoint(context, bufSize))
4864 {
4865 return false;
4866 }
4867
4868 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4869 {
4870 return false;
4871 }
4872
4873 if (!ValidateRobustBufferSize(context, bufSize, *length))
4874 {
4875 return false;
4876 }
4877
4878 return true;
4879}
4880
4881bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
4882{
4883 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4884}
4885
4886bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4887 GLuint index,
4888 GLenum pname,
4889 GLsizei bufSize,
4890 GLsizei *length,
4891 GLint *params)
4892{
4893 if (!ValidateRobustEntryPoint(context, bufSize))
4894 {
4895 return false;
4896 }
4897
4898 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4899 {
4900 return false;
4901 }
4902
4903 if (!ValidateRobustBufferSize(context, bufSize, *length))
4904 {
4905 return false;
4906 }
4907
4908 return true;
4909}
4910
4911bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
4912{
4913 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
4914}
4915
4916bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4917 GLuint index,
4918 GLenum pname,
4919 GLsizei bufSize,
4920 GLsizei *length,
4921 void **pointer)
4922{
4923 if (!ValidateRobustEntryPoint(context, bufSize))
4924 {
4925 return false;
4926 }
4927
4928 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4929 {
4930 return false;
4931 }
4932
4933 if (!ValidateRobustBufferSize(context, bufSize, *length))
4934 {
4935 return false;
4936 }
4937
4938 return true;
4939}
4940
4941bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4942{
4943 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4944}
4945
4946bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4947 GLuint index,
4948 GLenum pname,
4949 GLsizei bufSize,
4950 GLsizei *length,
4951 GLint *params)
4952{
4953 if (!ValidateRobustEntryPoint(context, bufSize))
4954 {
4955 return false;
4956 }
4957
4958 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4959 {
4960 return false;
4961 }
4962
4963 if (!ValidateRobustBufferSize(context, bufSize, *length))
4964 {
4965 return false;
4966 }
4967
4968 return true;
4969}
4970
4971bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4972{
4973 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4974}
4975
4976bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4977 GLuint index,
4978 GLenum pname,
4979 GLsizei bufSize,
4980 GLsizei *length,
4981 GLuint *params)
4982{
4983 if (!ValidateRobustEntryPoint(context, bufSize))
4984 {
4985 return false;
4986 }
4987
4988 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4989 {
4990 return false;
4991 }
4992
4993 if (!ValidateRobustBufferSize(context, bufSize, *length))
4994 {
4995 return false;
4996 }
4997
4998 return true;
4999}
5000
Geoff Lang6899b872016-10-14 11:30:13 -04005001bool ValidateGetActiveUniformBlockiv(Context *context,
5002 GLuint program,
5003 GLuint uniformBlockIndex,
5004 GLenum pname,
5005 GLint *params)
5006{
5007 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5008}
5009
5010bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5011 GLuint program,
5012 GLuint uniformBlockIndex,
5013 GLenum pname,
5014 GLsizei bufSize,
5015 GLsizei *length,
5016 GLint *params)
5017{
5018 if (!ValidateRobustEntryPoint(context, bufSize))
5019 {
5020 return false;
5021 }
5022
5023 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5024 {
5025 return false;
5026 }
5027
5028 if (!ValidateRobustBufferSize(context, bufSize, *length))
5029 {
5030 return false;
5031 }
5032
5033 return true;
5034}
5035
Jamie Madillc29968b2016-01-20 11:17:23 -05005036} // namespace gl