blob: a41e3f69d197d08d9109e2ecb3a843477dddb14b [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 Langf41a7152016-09-19 15:11:17 -04001006} // anonymous namespace
1007
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001008bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001009{
Jamie Madilld7460c72014-01-21 16:38:14 -05001010 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001011 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001012 case GL_TEXTURE_2D:
1013 case GL_TEXTURE_CUBE_MAP:
1014 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001015
Jamie Madilld7460c72014-01-21 16:38:14 -05001016 case GL_TEXTURE_3D:
1017 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001018 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001019
1020 default:
1021 return false;
1022 }
Jamie Madill35d15012013-10-07 10:46:37 -04001023}
1024
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001025bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1026{
1027 switch (target)
1028 {
1029 case GL_TEXTURE_2D:
1030 case GL_TEXTURE_CUBE_MAP:
1031 return true;
1032
1033 default:
1034 return false;
1035 }
1036}
1037
1038bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1039{
1040 switch (target)
1041 {
1042 case GL_TEXTURE_3D:
1043 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001044 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001045
1046 default:
1047 return false;
1048 }
1049}
1050
Ian Ewellbda75592016-04-18 17:25:54 -04001051// Most texture GL calls are not compatible with external textures, so we have a separate validation
1052// function for use in the GL calls that do
1053bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1054{
1055 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1056 (context->getExtensions().eglImageExternal ||
1057 context->getExtensions().eglStreamConsumerExternal);
1058}
1059
Shannon Woods4dfed832014-03-17 20:03:39 -04001060// This function differs from ValidTextureTarget in that the target must be
1061// usable as the destination of a 2D operation-- so a cube face is valid, but
1062// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001063// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001064bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001065{
1066 switch (target)
1067 {
1068 case GL_TEXTURE_2D:
1069 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1070 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1071 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1072 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1073 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1074 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1075 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001076 default:
1077 return false;
1078 }
1079}
1080
1081bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1082{
1083 switch (target)
1084 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001085 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001086 case GL_TEXTURE_2D_ARRAY:
1087 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001088 default:
1089 return false;
1090 }
1091}
1092
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001093bool ValidFramebufferTarget(GLenum target)
1094{
Geoff Langd4475812015-03-18 10:53:05 -04001095 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1096 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001097
1098 switch (target)
1099 {
1100 case GL_FRAMEBUFFER: return true;
1101 case GL_READ_FRAMEBUFFER: return true;
1102 case GL_DRAW_FRAMEBUFFER: return true;
1103 default: return false;
1104 }
1105}
1106
Jamie Madill29639852016-09-02 15:00:09 -04001107bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001108{
1109 switch (target)
1110 {
1111 case GL_ARRAY_BUFFER:
1112 case GL_ELEMENT_ARRAY_BUFFER:
1113 return true;
1114
Jamie Madill8c96d582014-03-05 15:01:23 -05001115 case GL_PIXEL_PACK_BUFFER:
1116 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001117 return (context->getExtensions().pixelBufferObject ||
1118 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001119
Shannon Woodsb3801742014-03-27 14:59:19 -04001120 case GL_COPY_READ_BUFFER:
1121 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001122 case GL_TRANSFORM_FEEDBACK_BUFFER:
1123 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001124 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001125
1126 default:
1127 return false;
1128 }
1129}
1130
Geoff Langff5b2d52016-09-07 11:32:23 -04001131bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -05001132{
Geoff Langff5b2d52016-09-07 11:32:23 -04001133 // All buffer parameter queries return one value.
1134 *numParams = 1;
1135
Geoff Langcc6f55d2015-03-20 13:01:02 -04001136 const Extensions &extensions = context->getExtensions();
1137
Jamie Madill70656a62014-03-05 15:01:26 -05001138 switch (pname)
1139 {
1140 case GL_BUFFER_USAGE:
1141 case GL_BUFFER_SIZE:
1142 return true;
1143
Geoff Langcc6f55d2015-03-20 13:01:02 -04001144 case GL_BUFFER_ACCESS_OES:
1145 return extensions.mapBuffer;
1146
1147 case GL_BUFFER_MAPPED:
1148 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +03001149 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
1150 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -04001151
Jamie Madill70656a62014-03-05 15:01:26 -05001152 // GL_BUFFER_MAP_POINTER is a special case, and may only be
1153 // queried with GetBufferPointerv
1154 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -05001155 case GL_BUFFER_MAP_OFFSET:
1156 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +03001157 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -05001158
1159 default:
1160 return false;
1161 }
1162}
1163
Jamie Madillc29968b2016-01-20 11:17:23 -05001164bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001165{
Jamie Madillc29968b2016-01-20 11:17:23 -05001166 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001167 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001168 switch (target)
1169 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001170 case GL_TEXTURE_2D:
1171 maxDimension = caps.max2DTextureSize;
1172 break;
Geoff Langce635692013-09-24 13:56:32 -04001173 case GL_TEXTURE_CUBE_MAP:
1174 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1175 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1176 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1177 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1178 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001179 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1180 maxDimension = caps.maxCubeMapTextureSize;
1181 break;
1182 case GL_TEXTURE_3D:
1183 maxDimension = caps.max3DTextureSize;
1184 break;
1185 case GL_TEXTURE_2D_ARRAY:
1186 maxDimension = caps.max2DTextureSize;
1187 break;
Geoff Langce635692013-09-24 13:56:32 -04001188 default: UNREACHABLE();
1189 }
1190
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001191 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001192}
1193
Austin Kinross08528e12015-10-07 16:24:40 -07001194bool ValidImageSizeParameters(const Context *context,
1195 GLenum target,
1196 GLint level,
1197 GLsizei width,
1198 GLsizei height,
1199 GLsizei depth,
1200 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001201{
1202 if (level < 0 || width < 0 || height < 0 || depth < 0)
1203 {
1204 return false;
1205 }
1206
Austin Kinross08528e12015-10-07 16:24:40 -07001207 // TexSubImage parameters can be NPOT without textureNPOT extension,
1208 // as long as the destination texture is POT.
1209 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001210 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001211 {
1212 return false;
1213 }
1214
1215 if (!ValidMipLevel(context, target, level))
1216 {
1217 return false;
1218 }
1219
1220 return true;
1221}
1222
Geoff Lang0d8b7242015-09-09 14:56:53 -04001223bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1224{
1225 // List of compressed format that require that the texture size is smaller than or a multiple of
1226 // the compressed block size.
1227 switch (internalFormat)
1228 {
1229 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1230 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1231 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1232 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001233 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001234 return true;
1235
1236 default:
1237 return false;
1238 }
1239}
1240
Jamie Madillc29968b2016-01-20 11:17:23 -05001241bool ValidCompressedImageSize(const ValidationContext *context,
1242 GLenum internalFormat,
1243 GLsizei width,
1244 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001245{
Geoff Lang5d601382014-07-22 15:14:06 -04001246 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1247 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001248 {
1249 return false;
1250 }
1251
Geoff Lang0d8b7242015-09-09 14:56:53 -04001252 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001253 {
1254 return false;
1255 }
1256
Geoff Lang0d8b7242015-09-09 14:56:53 -04001257 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1258 {
1259 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1260 width % formatInfo.compressedBlockWidth != 0) ||
1261 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1262 height % formatInfo.compressedBlockHeight != 0))
1263 {
1264 return false;
1265 }
1266 }
1267
Geoff Langd4f180b2013-09-24 13:57:44 -04001268 return true;
1269}
1270
Geoff Langff5b2d52016-09-07 11:32:23 -04001271bool ValidImageDataSize(ValidationContext *context,
1272 GLenum textureTarget,
1273 GLsizei width,
1274 GLsizei height,
1275 GLsizei depth,
1276 GLenum internalFormat,
1277 GLenum type,
1278 const GLvoid *pixels,
1279 GLsizei imageSize)
1280{
1281 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1282 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1283 {
1284 // Checks are not required
1285 return true;
1286 }
1287
1288 // ...the data would be unpacked from the buffer object such that the memory reads required
1289 // would exceed the data store size.
1290 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1291 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1292 const gl::Extents size(width, height, depth);
1293 const auto &unpack = context->getGLState().getUnpackState();
1294
1295 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1296 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1297 if (endByteOrErr.isError())
1298 {
1299 context->handleError(endByteOrErr.getError());
1300 return false;
1301 }
1302
1303 GLuint endByte = endByteOrErr.getResult();
1304
1305 if (pixelUnpackBuffer)
1306 {
1307 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1308 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1309 checkedEndByte += checkedOffset;
1310
1311 if (!checkedEndByte.IsValid() ||
1312 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1313 {
1314 // Overflow past the end of the buffer
1315 context->handleError(Error(GL_INVALID_OPERATION));
1316 return false;
1317 }
1318 }
1319 else
1320 {
1321 ASSERT(imageSize >= 0);
1322 if (pixels == nullptr && imageSize != 0)
1323 {
1324 context->handleError(
1325 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1326 }
1327
1328 if (endByte > static_cast<GLuint>(imageSize))
1329 {
1330 context->handleError(
1331 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1332 return false;
1333 }
1334 }
1335
1336 return true;
1337}
1338
Geoff Lang37dde692014-01-31 16:34:54 -05001339bool ValidQueryType(const Context *context, GLenum queryType)
1340{
Geoff Langd4475812015-03-18 10:53:05 -04001341 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1342 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 -05001343
1344 switch (queryType)
1345 {
1346 case GL_ANY_SAMPLES_PASSED:
1347 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1348 return true;
1349 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001350 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001351 case GL_TIME_ELAPSED_EXT:
1352 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001353 case GL_COMMANDS_COMPLETED_CHROMIUM:
1354 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001355 default:
1356 return false;
1357 }
1358}
1359
Jamie Madillef300b12016-10-07 15:12:09 -04001360Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001361{
1362 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1363 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1364 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1365
Dian Xiang769769a2015-09-09 15:20:08 -07001366 Program *validProgram = context->getProgram(id);
1367
1368 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001369 {
Dian Xiang769769a2015-09-09 15:20:08 -07001370 if (context->getShader(id))
1371 {
Jamie Madill437fa652016-05-03 15:13:24 -04001372 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001373 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1374 }
1375 else
1376 {
Jamie Madill437fa652016-05-03 15:13:24 -04001377 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001378 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001379 }
Dian Xiang769769a2015-09-09 15:20:08 -07001380
1381 return validProgram;
1382}
1383
Jamie Madillef300b12016-10-07 15:12:09 -04001384Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001385{
1386 // See ValidProgram for spec details.
1387
1388 Shader *validShader = context->getShader(id);
1389
1390 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001391 {
Dian Xiang769769a2015-09-09 15:20:08 -07001392 if (context->getProgram(id))
1393 {
Jamie Madill437fa652016-05-03 15:13:24 -04001394 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001395 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1396 }
1397 else
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001400 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001401 }
Dian Xiang769769a2015-09-09 15:20:08 -07001402
1403 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001404}
1405
Geoff Langb1196682014-07-23 13:47:29 -04001406bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001407{
1408 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1409 {
1410 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1411
Geoff Langaae65a42014-05-26 12:43:44 -04001412 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001413 {
Jamie Madill437fa652016-05-03 15:13:24 -04001414 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001415 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001416 }
1417 }
1418 else
1419 {
1420 switch (attachment)
1421 {
1422 case GL_DEPTH_ATTACHMENT:
1423 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001424 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001425
1426 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001427 if (!context->getExtensions().webglCompatibility &&
1428 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001429 {
1430 context->handleError(Error(GL_INVALID_ENUM));
1431 return false;
1432 }
1433 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001434
1435 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001436 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001437 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001438 }
1439 }
1440
1441 return true;
1442}
1443
Corentin Walleze0902642014-11-04 12:32:15 -08001444bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1445 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001446{
1447 switch (target)
1448 {
1449 case GL_RENDERBUFFER:
1450 break;
1451 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455
1456 if (width < 0 || height < 0 || samples < 0)
1457 {
Jamie Madill437fa652016-05-03 15:13:24 -04001458 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001459 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001460 }
1461
Geoff Langd87878e2014-09-19 15:42:59 -04001462 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1463 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 {
Jamie Madill437fa652016-05-03 15:13:24 -04001465 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 }
1468
1469 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1470 // 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 -08001471 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001472 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001473 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001474 {
Jamie Madill437fa652016-05-03 15:13:24 -04001475 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001476 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 }
1478
Geoff Langaae65a42014-05-26 12:43:44 -04001479 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 {
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001483 }
1484
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001485 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 if (handle == 0)
1487 {
Jamie Madill437fa652016-05-03 15:13:24 -04001488 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001489 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001490 }
1491
1492 return true;
1493}
1494
Corentin Walleze0902642014-11-04 12:32:15 -08001495bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1496 GLenum internalformat, GLsizei width, GLsizei height)
1497{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001498 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001499
1500 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001501 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001502 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001503 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001504 {
Jamie Madill437fa652016-05-03 15:13:24 -04001505 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001506 return false;
1507 }
1508
1509 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1510 // the specified storage. This is different than ES 3.0 in which a sample number higher
1511 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001512 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001513 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001514 {
Geoff Langa4903b72015-03-02 16:02:48 -08001515 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1516 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1517 {
Jamie Madill437fa652016-05-03 15:13:24 -04001518 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001519 return false;
1520 }
Corentin Walleze0902642014-11-04 12:32:15 -08001521 }
1522
1523 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1524}
1525
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001526bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1527 GLenum renderbuffertarget, GLuint renderbuffer)
1528{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001529 if (!ValidFramebufferTarget(target))
1530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001532 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001533 }
1534
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001535 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001536
Jamie Madill84115c92015-04-23 15:00:07 -04001537 ASSERT(framebuffer);
1538 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001539 {
Jamie Madill437fa652016-05-03 15:13:24 -04001540 context->handleError(
1541 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001542 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001543 }
1544
Jamie Madillb4472272014-07-03 10:38:55 -04001545 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001546 {
Jamie Madillb4472272014-07-03 10:38:55 -04001547 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001548 }
1549
Jamie Madillab9d82c2014-01-21 16:38:14 -05001550 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1551 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1552 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1553 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1554 if (renderbuffer != 0)
1555 {
1556 if (!context->getRenderbuffer(renderbuffer))
1557 {
Jamie Madill437fa652016-05-03 15:13:24 -04001558 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001559 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001560 }
1561 }
1562
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001563 return true;
1564}
1565
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001566bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001567 GLint srcX0,
1568 GLint srcY0,
1569 GLint srcX1,
1570 GLint srcY1,
1571 GLint dstX0,
1572 GLint dstY0,
1573 GLint dstX1,
1574 GLint dstY1,
1575 GLbitfield mask,
1576 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001577{
1578 switch (filter)
1579 {
1580 case GL_NEAREST:
1581 break;
1582 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001583 break;
1584 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001586 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001587 }
1588
1589 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001593 }
1594
1595 if (mask == 0)
1596 {
1597 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1598 // buffers are copied.
1599 return false;
1600 }
1601
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001602 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1603 // color buffer, leaving only nearest being unfiltered from above
1604 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1605 {
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001607 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001608 }
1609
Jamie Madill51f40ec2016-06-15 14:06:00 -04001610 const auto &glState = context->getGLState();
1611 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1612 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001613
1614 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001615 {
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001618 }
1619
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001620 if (readFramebuffer->id() == drawFramebuffer->id())
1621 {
1622 context->handleError(Error(GL_INVALID_OPERATION));
1623 return false;
1624 }
1625
Jamie Madill51f40ec2016-06-15 14:06:00 -04001626 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001627 {
Jamie Madill437fa652016-05-03 15:13:24 -04001628 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001629 return false;
1630 }
1631
Jamie Madill51f40ec2016-06-15 14:06:00 -04001632 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001633 {
Jamie Madill437fa652016-05-03 15:13:24 -04001634 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001635 return false;
1636 }
1637
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001638 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001641 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001642 }
1643
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001644 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1645
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001646 if (mask & GL_COLOR_BUFFER_BIT)
1647 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001648 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1649 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001650 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651
1652 if (readColorBuffer && drawColorBuffer)
1653 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001654 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001655
Geoff Langa15472a2015-08-11 11:48:03 -04001656 for (size_t drawbufferIdx = 0;
1657 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Geoff Langa15472a2015-08-11 11:48:03 -04001659 const FramebufferAttachment *attachment =
1660 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1661 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001662 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001663 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001664
Geoff Langb2f3d052013-08-13 12:49:27 -04001665 // The GL ES 3.0.2 spec (pg 193) states that:
1666 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1667 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1668 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001669 // Changes with EXT_color_buffer_float:
1670 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001671 GLenum readComponentType = readFormat.info->componentType;
1672 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001673 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1674 readComponentType == GL_SIGNED_NORMALIZED);
1675 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1676 drawComponentType == GL_SIGNED_NORMALIZED);
1677
1678 if (extensions.colorBufferFloat)
1679 {
1680 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1681 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1682
1683 if (readFixedOrFloat != drawFixedOrFloat)
1684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001686 "If the read buffer contains fixed-point or "
1687 "floating-point values, the draw buffer "
1688 "must as well."));
1689 return false;
1690 }
1691 }
1692 else if (readFixedPoint != drawFixedPoint)
1693 {
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001695 "If the read buffer contains fixed-point "
1696 "values, the draw buffer must as well."));
1697 return false;
1698 }
1699
1700 if (readComponentType == GL_UNSIGNED_INT &&
1701 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001702 {
Jamie Madill437fa652016-05-03 15:13:24 -04001703 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001704 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001705 }
1706
Jamie Madill6163c752015-12-07 16:32:59 -05001707 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001708 {
Jamie Madill437fa652016-05-03 15:13:24 -04001709 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001710 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001711 }
1712
Jamie Madilla3944d42016-07-22 22:13:26 -04001713 if (readColorBuffer->getSamples() > 0 &&
1714 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715 {
Jamie Madill437fa652016-05-03 15:13:24 -04001716 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001717 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718 }
1719 }
1720 }
1721
Jamie Madilla3944d42016-07-22 22:13:26 -04001722 if ((readFormat.info->componentType == GL_INT ||
1723 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1724 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 {
Jamie Madill437fa652016-05-03 15:13:24 -04001726 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001727 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729 }
1730 }
1731
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001732 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1733 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1734 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001736 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001737 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001738 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1739 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001740
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001741 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001742 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001743 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001747 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001749 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 }
1754 }
1755 }
1756 }
1757
1758 return true;
1759}
1760
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001761bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001762 GLint x,
1763 GLint y,
1764 GLsizei width,
1765 GLsizei height,
1766 GLenum format,
1767 GLenum type,
1768 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001769{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001770 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1771}
1772
1773bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1774 GLint x,
1775 GLint y,
1776 GLsizei width,
1777 GLsizei height,
1778 GLenum format,
1779 GLenum type,
1780 GLsizei bufSize,
1781 GLsizei *length,
1782 GLvoid *pixels)
1783{
1784 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001786 return false;
1787 }
1788
Geoff Lang62fce5b2016-09-30 10:46:35 -04001789 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1790 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001791 {
Geoff Langb1196682014-07-23 13:47:29 -04001792 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001793 }
1794
Geoff Lang62fce5b2016-09-30 10:46:35 -04001795 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001796 {
Geoff Langb1196682014-07-23 13:47:29 -04001797 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001798 }
1799
Jamie Madillc29968b2016-01-20 11:17:23 -05001800 return true;
1801}
1802
1803bool ValidateReadnPixelsEXT(Context *context,
1804 GLint x,
1805 GLint y,
1806 GLsizei width,
1807 GLsizei height,
1808 GLenum format,
1809 GLenum type,
1810 GLsizei bufSize,
1811 GLvoid *pixels)
1812{
1813 if (bufSize < 0)
1814 {
Jamie Madill437fa652016-05-03 15:13:24 -04001815 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 return false;
1817 }
1818
Geoff Lang62fce5b2016-09-30 10:46:35 -04001819 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1820 pixels);
1821}
Jamie Madill26e91952014-03-05 15:01:27 -05001822
Geoff Lang62fce5b2016-09-30 10:46:35 -04001823bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1824 GLint x,
1825 GLint y,
1826 GLsizei width,
1827 GLsizei height,
1828 GLenum format,
1829 GLenum type,
1830 GLsizei bufSize,
1831 GLsizei *length,
1832 GLvoid *data)
1833{
1834 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001835 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001836 return false;
1837 }
1838
Geoff Lang62fce5b2016-09-30 10:46:35 -04001839 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001840 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001841 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001842 }
1843
Geoff Lang62fce5b2016-09-30 10:46:35 -04001844 if (!ValidateRobustBufferSize(context, bufSize, *length))
1845 {
1846 return false;
1847 }
1848
1849 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001850}
1851
Olli Etuaho41997e72016-03-10 13:38:39 +02001852bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001853{
1854 if (!context->getExtensions().occlusionQueryBoolean &&
1855 !context->getExtensions().disjointTimerQuery)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858 return false;
1859 }
1860
Olli Etuaho41997e72016-03-10 13:38:39 +02001861 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862}
1863
Olli Etuaho41997e72016-03-10 13:38:39 +02001864bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865{
1866 if (!context->getExtensions().occlusionQueryBoolean &&
1867 !context->getExtensions().disjointTimerQuery)
1868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 return false;
1871 }
1872
Olli Etuaho41997e72016-03-10 13:38:39 +02001873 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001874}
1875
1876bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001877{
1878 if (!ValidQueryType(context, target))
1879 {
Jamie Madill437fa652016-05-03 15:13:24 -04001880 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001881 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001882 }
1883
1884 if (id == 0)
1885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001887 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001888 }
1889
1890 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1891 // of zero, if the active query object name for <target> is non-zero (for the
1892 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1893 // the active query for either target is non-zero), if <id> is the name of an
1894 // existing query object whose type does not match <target>, or if <id> is the
1895 // active query object name for any query type, the error INVALID_OPERATION is
1896 // generated.
1897
1898 // Ensure no other queries are active
1899 // NOTE: If other queries than occlusion are supported, we will need to check
1900 // separately that:
1901 // a) The query ID passed is not the current active query for any target/type
1902 // b) There are no active queries for the requested target (and in the case
1903 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1904 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001906 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001907 {
Jamie Madill437fa652016-05-03 15:13:24 -04001908 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001909 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001910 }
1911
1912 Query *queryObject = context->getQuery(id, true, target);
1913
1914 // check that name was obtained with glGenQueries
1915 if (!queryObject)
1916 {
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001918 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001919 }
1920
1921 // check for type mismatch
1922 if (queryObject->getType() != target)
1923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001925 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001926 }
1927
1928 return true;
1929}
1930
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001931bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1932{
1933 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001934 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return false;
1938 }
1939
1940 return ValidateBeginQueryBase(context, target, id);
1941}
1942
1943bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001944{
1945 if (!ValidQueryType(context, target))
1946 {
Jamie Madill437fa652016-05-03 15:13:24 -04001947 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001949 }
1950
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001951 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001952
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001956 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001957 }
1958
Jamie Madill45c785d2014-05-13 14:09:34 -04001959 return true;
1960}
1961
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001962bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1963{
1964 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001965 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 {
Jamie Madill437fa652016-05-03 15:13:24 -04001967 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001968 return false;
1969 }
1970
1971 return ValidateEndQueryBase(context, target);
1972}
1973
1974bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979 return false;
1980 }
1981
1982 if (target != GL_TIMESTAMP_EXT)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985 return false;
1986 }
1987
1988 Query *queryObject = context->getQuery(id, true, target);
1989 if (queryObject == nullptr)
1990 {
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001992 return false;
1993 }
1994
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001995 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001996 {
Jamie Madill437fa652016-05-03 15:13:24 -04001997 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998 return false;
1999 }
2000
2001 return true;
2002}
2003
2004bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
2005{
2006 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009 return false;
2010 }
2011
2012 switch (pname)
2013 {
2014 case GL_CURRENT_QUERY_EXT:
2015 if (target == GL_TIMESTAMP_EXT)
2016 {
Jamie Madill437fa652016-05-03 15:13:24 -04002017 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002018 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2019 return false;
2020 }
2021 break;
2022 case GL_QUERY_COUNTER_BITS_EXT:
2023 if (!context->getExtensions().disjointTimerQuery ||
2024 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2025 {
Jamie Madill437fa652016-05-03 15:13:24 -04002026 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002027 return false;
2028 }
2029 break;
2030 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002031 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032 return false;
2033 }
2034
2035 return true;
2036}
2037
2038bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2039{
2040 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002041 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002044 return false;
2045 }
2046
2047 return ValidateGetQueryivBase(context, target, pname);
2048}
2049
2050bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
2051{
2052 Query *queryObject = context->getQuery(id, false, GL_NONE);
2053
2054 if (!queryObject)
2055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
2059
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002060 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002061 {
Jamie Madill437fa652016-05-03 15:13:24 -04002062 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063 return false;
2064 }
2065
2066 switch (pname)
2067 {
2068 case GL_QUERY_RESULT_EXT:
2069 case GL_QUERY_RESULT_AVAILABLE_EXT:
2070 break;
2071
2072 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002074 return false;
2075 }
2076
2077 return true;
2078}
2079
2080bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2081{
2082 if (!context->getExtensions().disjointTimerQuery)
2083 {
Jamie Madill437fa652016-05-03 15:13:24 -04002084 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002085 return false;
2086 }
2087 return ValidateGetQueryObjectValueBase(context, id, pname);
2088}
2089
2090bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2091{
2092 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002093 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002096 return false;
2097 }
2098 return ValidateGetQueryObjectValueBase(context, id, pname);
2099}
2100
2101bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2102{
2103 if (!context->getExtensions().disjointTimerQuery)
2104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002106 return false;
2107 }
2108 return ValidateGetQueryObjectValueBase(context, id, pname);
2109}
2110
2111bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2112{
2113 if (!context->getExtensions().disjointTimerQuery)
2114 {
Jamie Madill437fa652016-05-03 15:13:24 -04002115 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002116 return false;
2117 }
2118 return ValidateGetQueryObjectValueBase(context, id, pname);
2119}
2120
Jamie Madill62d31cb2015-09-11 13:25:51 -04002121static bool ValidateUniformCommonBase(gl::Context *context,
2122 GLenum targetUniformType,
2123 GLint location,
2124 GLsizei count,
2125 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002126{
2127 if (count < 0)
2128 {
Jamie Madill437fa652016-05-03 15:13:24 -04002129 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002130 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002131 }
2132
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002133 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002134 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002135 {
Jamie Madill437fa652016-05-03 15:13:24 -04002136 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002137 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002138 }
2139
Geoff Langd8605522016-04-13 10:19:12 -04002140 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002141 {
2142 // Silently ignore the uniform command
2143 return false;
2144 }
2145
Geoff Lang7dd2e102014-11-10 15:19:26 -05002146 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002147 {
Jamie Madill437fa652016-05-03 15:13:24 -04002148 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002149 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002150 }
2151
Jamie Madill62d31cb2015-09-11 13:25:51 -04002152 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002153
2154 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002155 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002156 {
Jamie Madill437fa652016-05-03 15:13:24 -04002157 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002158 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002159 }
2160
Jamie Madill62d31cb2015-09-11 13:25:51 -04002161 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002162 return true;
2163}
2164
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2166{
2167 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002168 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2169 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002170 {
Jamie Madill437fa652016-05-03 15:13:24 -04002171 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002172 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002173 }
2174
Jamie Madill62d31cb2015-09-11 13:25:51 -04002175 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002176 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2177 {
2178 return false;
2179 }
2180
Jamie Madillf2575982014-06-25 16:04:54 -04002181 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002182 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002183 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2184 {
Jamie Madill437fa652016-05-03 15:13:24 -04002185 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002186 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002187 }
2188
2189 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002190}
2191
2192bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2193 GLboolean transpose)
2194{
2195 // Check for ES3 uniform entry points
2196 int rows = VariableRowCount(matrixType);
2197 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002198 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002201 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002202 }
2203
Martin Radev1be913c2016-07-11 17:59:16 +03002204 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002208 }
2209
Jamie Madill62d31cb2015-09-11 13:25:51 -04002210 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002211 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2212 {
2213 return false;
2214 }
2215
2216 if (uniform->type != matrixType)
2217 {
Jamie Madill437fa652016-05-03 15:13:24 -04002218 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002219 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002220 }
2221
2222 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002223}
2224
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002225bool ValidateStateQuery(ValidationContext *context,
2226 GLenum pname,
2227 GLenum *nativeType,
2228 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002229{
2230 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002233 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002234 }
2235
Jamie Madill0af26e12015-03-05 19:54:33 -05002236 const Caps &caps = context->getCaps();
2237
Jamie Madill893ab082014-05-16 16:56:10 -04002238 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2239 {
2240 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2241
Jamie Madill0af26e12015-03-05 19:54:33 -05002242 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002243 {
Jamie Madill437fa652016-05-03 15:13:24 -04002244 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002245 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002246 }
2247 }
2248
2249 switch (pname)
2250 {
2251 case GL_TEXTURE_BINDING_2D:
2252 case GL_TEXTURE_BINDING_CUBE_MAP:
2253 case GL_TEXTURE_BINDING_3D:
2254 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002255 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002256 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002257 if (!context->getExtensions().eglStreamConsumerExternal &&
2258 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002259 {
John Bauman18319182016-09-28 14:22:27 -07002260 context->handleError(Error(GL_INVALID_ENUM,
2261 "Neither NV_EGL_stream_consumer_external nor "
2262 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002263 return false;
2264 }
2265 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002266
2267 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2268 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2269 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002270 if (context->getGLState().getReadFramebuffer()->checkStatus(
2271 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002272 {
Jamie Madill437fa652016-05-03 15:13:24 -04002273 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002274 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002275 }
2276
Jamie Madill51f40ec2016-06-15 14:06:00 -04002277 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2278 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002279
2280 if (framebuffer->getReadBufferState() == GL_NONE)
2281 {
2282 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2283 return false;
2284 }
2285
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002286 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002287 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002288 {
Jamie Madill437fa652016-05-03 15:13:24 -04002289 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002290 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002291 }
2292 }
2293 break;
2294
2295 default:
2296 break;
2297 }
2298
2299 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002300 if (*numParams == 0)
2301 {
2302 return false;
2303 }
2304
2305 return true;
2306}
2307
2308bool ValidateRobustStateQuery(ValidationContext *context,
2309 GLenum pname,
2310 GLsizei bufSize,
2311 GLenum *nativeType,
2312 unsigned int *numParams)
2313{
2314 if (!ValidateRobustEntryPoint(context, bufSize))
2315 {
2316 return false;
2317 }
2318
2319 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2320 {
2321 return false;
2322 }
2323
2324 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002325 {
2326 return false;
2327 }
2328
2329 return true;
2330}
2331
Jamie Madillc29968b2016-01-20 11:17:23 -05002332bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2333 GLenum target,
2334 GLint level,
2335 GLenum internalformat,
2336 bool isSubImage,
2337 GLint xoffset,
2338 GLint yoffset,
2339 GLint zoffset,
2340 GLint x,
2341 GLint y,
2342 GLsizei width,
2343 GLsizei height,
2344 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002345 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002346{
Jamie Madill560a8d82014-05-21 13:06:20 -04002347 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2348 {
Jamie Madill437fa652016-05-03 15:13:24 -04002349 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002350 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002351 }
2352
2353 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2354 {
Jamie Madill437fa652016-05-03 15:13:24 -04002355 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357 }
2358
2359 if (border != 0)
2360 {
Jamie Madill437fa652016-05-03 15:13:24 -04002361 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002362 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002363 }
2364
2365 if (!ValidMipLevel(context, target, level))
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002368 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002369 }
2370
Jamie Madill51f40ec2016-06-15 14:06:00 -04002371 const auto &state = context->getGLState();
2372 auto readFramebuffer = state.getReadFramebuffer();
2373 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002374 {
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002376 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002377 }
2378
Jamie Madill51f40ec2016-06-15 14:06:00 -04002379 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002380 {
Jamie Madill437fa652016-05-03 15:13:24 -04002381 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002382 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002383 }
2384
Martin Radev138064f2016-07-15 12:03:41 +03002385 if (readFramebuffer->getReadBufferState() == GL_NONE)
2386 {
2387 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2388 return false;
2389 }
2390
Geoff Langaae65a42014-05-26 12:43:44 -04002391 const gl::Caps &caps = context->getCaps();
2392
Geoff Langaae65a42014-05-26 12:43:44 -04002393 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 switch (target)
2395 {
2396 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002397 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002398 break;
2399
2400 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2401 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2402 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2403 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2404 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2405 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002406 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 break;
2408
2409 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002410 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002411 break;
2412
2413 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002414 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 break;
2416
2417 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002418 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002419 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420 }
2421
Jamie Madillc29968b2016-01-20 11:17:23 -05002422 gl::Texture *texture =
2423 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 if (!texture)
2425 {
Jamie Madill437fa652016-05-03 15:13:24 -04002426 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002427 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 }
2429
Geoff Lang69cce582015-09-17 13:20:36 -04002430 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002431 {
Jamie Madill437fa652016-05-03 15:13:24 -04002432 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002433 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002434 }
2435
Geoff Lang5d601382014-07-22 15:14:06 -04002436 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2437
2438 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 {
Jamie Madill437fa652016-05-03 15:13:24 -04002440 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Geoff Langa9be0dc2014-12-17 12:34:40 -05002444 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Jamie Madill437fa652016-05-03 15:13:24 -04002446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002447 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 }
2449
2450 if (isSubImage)
2451 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002452 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2453 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2454 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 {
Jamie Madill437fa652016-05-03 15:13:24 -04002456 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 }
2459 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002460 else
2461 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002462 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002463 {
Jamie Madill437fa652016-05-03 15:13:24 -04002464 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002465 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002466 }
2467
Martin Radev1be913c2016-07-11 17:59:16 +03002468 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002469 {
Jamie Madill437fa652016-05-03 15:13:24 -04002470 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002472 }
2473
2474 int maxLevelDimension = (maxDimension >> level);
2475 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2476 {
Jamie Madill437fa652016-05-03 15:13:24 -04002477 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002478 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002479 }
2480 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002481
Jamie Madill0c8abca2016-07-22 20:21:26 -04002482 if (textureFormatOut)
2483 {
2484 *textureFormatOut = texture->getFormat(target, level);
2485 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002486 return true;
2487}
2488
Jamie Madillf25855c2015-11-03 11:06:18 -05002489static bool ValidateDrawBase(ValidationContext *context,
2490 GLenum mode,
2491 GLsizei count,
2492 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002493{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002494 switch (mode)
2495 {
2496 case GL_POINTS:
2497 case GL_LINES:
2498 case GL_LINE_LOOP:
2499 case GL_LINE_STRIP:
2500 case GL_TRIANGLES:
2501 case GL_TRIANGLE_STRIP:
2502 case GL_TRIANGLE_FAN:
2503 break;
2504 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002505 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002506 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002507 }
2508
Jamie Madill250d33f2014-06-06 17:09:03 -04002509 if (count < 0)
2510 {
Jamie Madill437fa652016-05-03 15:13:24 -04002511 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002513 }
2514
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002515 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002516
Jamie Madill250d33f2014-06-06 17:09:03 -04002517 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002518 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002519 {
Jamie Madill437fa652016-05-03 15:13:24 -04002520 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002521 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002522 }
2523
Jamie Madill51f40ec2016-06-15 14:06:00 -04002524 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002525 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002526 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002527 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2528 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2529 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2530 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2531 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2532 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002533 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002534 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2535 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002536 {
2537 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2538 // Section 6.10 of the WebGL 1.0 spec
2539 ERR(
2540 "This ANGLE implementation does not support separate front/back stencil "
2541 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002542 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002543 return false;
2544 }
Jamie Madillac528012014-06-20 13:21:23 -04002545 }
2546
Jamie Madill51f40ec2016-06-15 14:06:00 -04002547 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002548 {
Jamie Madill437fa652016-05-03 15:13:24 -04002549 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002550 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002551 }
2552
Geoff Lang7dd2e102014-11-10 15:19:26 -05002553 gl::Program *program = state.getProgram();
2554 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002555 {
Jamie Madill437fa652016-05-03 15:13:24 -04002556 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002557 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002558 }
2559
Geoff Lang7dd2e102014-11-10 15:19:26 -05002560 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002561 {
Jamie Madill437fa652016-05-03 15:13:24 -04002562 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002563 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002564 }
2565
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002566 // Uniform buffer validation
2567 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2568 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002569 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002570 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002571 const OffsetBindingPointer<Buffer> &uniformBuffer =
2572 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002573
Geoff Lang5d124a62015-09-15 13:03:27 -04002574 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002575 {
2576 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002577 context->handleError(
2578 Error(GL_INVALID_OPERATION,
2579 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002580 return false;
2581 }
2582
Geoff Lang5d124a62015-09-15 13:03:27 -04002583 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002584 if (uniformBufferSize == 0)
2585 {
2586 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002587 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002588 }
2589
Jamie Madill62d31cb2015-09-11 13:25:51 -04002590 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002591 {
2592 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002593 context->handleError(
2594 Error(GL_INVALID_OPERATION,
2595 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002596 return false;
2597 }
2598 }
2599
Jamie Madill250d33f2014-06-06 17:09:03 -04002600 // No-op if zero count
2601 return (count > 0);
2602}
2603
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002604bool ValidateDrawArrays(ValidationContext *context,
2605 GLenum mode,
2606 GLint first,
2607 GLsizei count,
2608 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002609{
Jamie Madillfd716582014-06-06 17:09:04 -04002610 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002611 {
Jamie Madill437fa652016-05-03 15:13:24 -04002612 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002613 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002614 }
2615
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002616 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002617 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002618 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2619 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002620 {
2621 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2622 // that does not match the current transform feedback object's draw mode (if transform feedback
2623 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002624 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002625 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002626 }
2627
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002628 if (!ValidateDrawBase(context, mode, count, primcount))
2629 {
2630 return false;
2631 }
2632
2633 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002634 {
2635 return false;
2636 }
2637
2638 return true;
2639}
2640
Geoff Langb1196682014-07-23 13:47:29 -04002641bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002642{
2643 if (primcount < 0)
2644 {
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002646 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002647 }
2648
Jamie Madill2b976812014-08-25 15:47:49 -04002649 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002650 {
2651 return false;
2652 }
2653
2654 // No-op if zero primitive count
2655 return (primcount > 0);
2656}
2657
Geoff Lang87a93302014-09-16 13:29:43 -04002658static bool ValidateDrawInstancedANGLE(Context *context)
2659{
2660 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002661 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002662
Geoff Lang7dd2e102014-11-10 15:19:26 -05002663 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002664
2665 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002666 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002667 {
2668 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002669 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002670 {
2671 return true;
2672 }
2673 }
2674
Jamie Madill437fa652016-05-03 15:13:24 -04002675 context->handleError(Error(GL_INVALID_OPERATION,
2676 "ANGLE_instanced_arrays requires that at least one active attribute"
2677 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002678 return false;
2679}
2680
2681bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2682{
2683 if (!ValidateDrawInstancedANGLE(context))
2684 {
2685 return false;
2686 }
2687
2688 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2689}
2690
Jamie Madillf25855c2015-11-03 11:06:18 -05002691bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002692 GLenum mode,
2693 GLsizei count,
2694 GLenum type,
2695 const GLvoid *indices,
2696 GLsizei primcount,
2697 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002698{
Jamie Madill250d33f2014-06-06 17:09:03 -04002699 switch (type)
2700 {
2701 case GL_UNSIGNED_BYTE:
2702 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002703 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002704 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002705 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2706 {
2707 context->handleError(Error(GL_INVALID_ENUM));
2708 return false;
2709 }
2710 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002711 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002712 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002713 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002714 }
2715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002716 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002717
2718 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002719 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002720 {
2721 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2722 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002723 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002724 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002725 }
2726
2727 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002728 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002729 {
Jamie Madill437fa652016-05-03 15:13:24 -04002730 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002731 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002732 }
2733
Jamie Madill2b976812014-08-25 15:47:49 -04002734 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002735 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002736 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002737 {
Jamie Madill437fa652016-05-03 15:13:24 -04002738 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002739 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002740 }
2741
Jamie Madillae3000b2014-08-25 15:47:51 -04002742 if (elementArrayBuffer)
2743 {
2744 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2745
2746 GLint64 offset = reinterpret_cast<GLint64>(indices);
2747 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2748
2749 // check for integer overflows
2750 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2751 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2752 {
Jamie Madill437fa652016-05-03 15:13:24 -04002753 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002754 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002755 }
2756
2757 // Check for reading past the end of the bound buffer object
2758 if (byteCount > elementArrayBuffer->getSize())
2759 {
Jamie Madill437fa652016-05-03 15:13:24 -04002760 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002761 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002762 }
2763 }
2764 else if (!indices)
2765 {
2766 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002767 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002768 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002769 }
2770
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002771 if (!ValidateDrawBase(context, mode, count, primcount))
2772 {
2773 return false;
2774 }
2775
Jamie Madill2b976812014-08-25 15:47:49 -04002776 // Use max index to validate if our vertex buffers are large enough for the pull.
2777 // TODO: offer fast path, with disabled index validation.
2778 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2779 if (elementArrayBuffer)
2780 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002781 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002782 Error error =
2783 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2784 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002785 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002786 {
Jamie Madill437fa652016-05-03 15:13:24 -04002787 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002788 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002789 }
2790 }
2791 else
2792 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002793 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002794 }
2795
Jamie Madille79b1e12015-11-04 16:36:37 -05002796 // If we use an index greater than our maximum supported index range, return an error.
2797 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2798 // return an error if possible here.
2799 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2800 {
Jamie Madill437fa652016-05-03 15:13:24 -04002801 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002802 return false;
2803 }
2804
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002805 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002806 {
2807 return false;
2808 }
2809
Geoff Lang3edfe032015-09-04 16:38:24 -04002810 // No op if there are no real indices in the index data (all are primitive restart).
2811 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002812}
2813
Geoff Langb1196682014-07-23 13:47:29 -04002814bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002815 GLenum mode,
2816 GLsizei count,
2817 GLenum type,
2818 const GLvoid *indices,
2819 GLsizei primcount,
2820 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002821{
2822 if (primcount < 0)
2823 {
Jamie Madill437fa652016-05-03 15:13:24 -04002824 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002825 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002826 }
2827
Jamie Madill2b976812014-08-25 15:47:49 -04002828 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002829 {
2830 return false;
2831 }
2832
2833 // No-op zero primitive count
2834 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002835}
2836
Geoff Lang3edfe032015-09-04 16:38:24 -04002837bool ValidateDrawElementsInstancedANGLE(Context *context,
2838 GLenum mode,
2839 GLsizei count,
2840 GLenum type,
2841 const GLvoid *indices,
2842 GLsizei primcount,
2843 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002844{
2845 if (!ValidateDrawInstancedANGLE(context))
2846 {
2847 return false;
2848 }
2849
2850 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2851}
2852
Geoff Langb1196682014-07-23 13:47:29 -04002853bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002854 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002855{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002856 if (!ValidFramebufferTarget(target))
2857 {
Jamie Madill437fa652016-05-03 15:13:24 -04002858 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002859 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002860 }
2861
2862 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002863 {
2864 return false;
2865 }
2866
Jamie Madill55ec3b12014-07-03 10:38:57 -04002867 if (texture != 0)
2868 {
2869 gl::Texture *tex = context->getTexture(texture);
2870
2871 if (tex == NULL)
2872 {
Jamie Madill437fa652016-05-03 15:13:24 -04002873 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002874 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002875 }
2876
2877 if (level < 0)
2878 {
Jamie Madill437fa652016-05-03 15:13:24 -04002879 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002880 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002881 }
2882 }
2883
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002884 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002885 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002886
Jamie Madill84115c92015-04-23 15:00:07 -04002887 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002888 {
Jamie Madill437fa652016-05-03 15:13:24 -04002889 context->handleError(
2890 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002891 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002892 }
2893
2894 return true;
2895}
2896
Geoff Langb1196682014-07-23 13:47:29 -04002897bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002898 GLenum textarget, GLuint texture, GLint level)
2899{
Geoff Lang95663912015-04-02 15:54:45 -04002900 // 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 +03002901 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2902 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002903 {
Jamie Madill437fa652016-05-03 15:13:24 -04002904 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002905 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002906 }
2907
2908 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002909 {
2910 return false;
2911 }
2912
Jamie Madill55ec3b12014-07-03 10:38:57 -04002913 if (texture != 0)
2914 {
2915 gl::Texture *tex = context->getTexture(texture);
2916 ASSERT(tex);
2917
Jamie Madill2a6564e2014-07-11 09:53:19 -04002918 const gl::Caps &caps = context->getCaps();
2919
Jamie Madill55ec3b12014-07-03 10:38:57 -04002920 switch (textarget)
2921 {
2922 case GL_TEXTURE_2D:
2923 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002924 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002925 {
Jamie Madill437fa652016-05-03 15:13:24 -04002926 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002927 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002928 }
2929 if (tex->getTarget() != GL_TEXTURE_2D)
2930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002933 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002934 }
2935 break;
2936
2937 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2938 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2939 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2940 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2941 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2942 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2943 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002944 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002945 {
Jamie Madill437fa652016-05-03 15:13:24 -04002946 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002947 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002948 }
2949 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2950 {
Jamie Madill437fa652016-05-03 15:13:24 -04002951 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002952 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002953 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002954 }
2955 break;
2956
2957 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002958 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002959 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002960 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002961
Jamie Madilla3944d42016-07-22 22:13:26 -04002962 const Format &format = tex->getFormat(textarget, level);
2963 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002964 {
Jamie Madill437fa652016-05-03 15:13:24 -04002965 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002966 return false;
2967 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002968 }
2969
Jamie Madill570f7c82014-07-03 10:38:54 -04002970 return true;
2971}
2972
Geoff Langb1196682014-07-23 13:47:29 -04002973bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002974{
2975 if (program == 0)
2976 {
Jamie Madill437fa652016-05-03 15:13:24 -04002977 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002979 }
2980
Dian Xiang769769a2015-09-09 15:20:08 -07002981 gl::Program *programObject = GetValidProgram(context, program);
2982 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002983 {
2984 return false;
2985 }
2986
Jamie Madill0063c512014-08-25 15:47:53 -04002987 if (!programObject || !programObject->isLinked())
2988 {
Jamie Madill437fa652016-05-03 15:13:24 -04002989 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002990 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002991 }
2992
Geoff Lang7dd2e102014-11-10 15:19:26 -05002993 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002994 {
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 Madill549c7fd2014-08-25 15:47:56 -04002997 }
2998
Jamie Madill0063c512014-08-25 15:47:53 -04002999 return true;
3000}
3001
Geoff Langb1196682014-07-23 13:47:29 -04003002bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003003{
3004 return ValidateGetUniformBase(context, program, location);
3005}
3006
Geoff Langb1196682014-07-23 13:47:29 -04003007bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003008{
Jamie Madill78f41802014-08-25 15:47:55 -04003009 return ValidateGetUniformBase(context, program, location);
3010}
3011
Geoff Langf41d0ee2016-10-07 13:04:23 -04003012static bool ValidateSizedGetUniform(Context *context,
3013 GLuint program,
3014 GLint location,
3015 GLsizei bufSize,
3016 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003017{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003018 if (length)
3019 {
3020 *length = 0;
3021 }
3022
Jamie Madill78f41802014-08-25 15:47:55 -04003023 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003024 {
Jamie Madill78f41802014-08-25 15:47:55 -04003025 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003026 }
3027
Geoff Langf41d0ee2016-10-07 13:04:23 -04003028 if (bufSize < 0)
3029 {
3030 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3031 return false;
3032 }
3033
Jamie Madilla502c742014-08-28 17:19:13 -04003034 gl::Program *programObject = context->getProgram(program);
3035 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003036
Jamie Madill78f41802014-08-25 15:47:55 -04003037 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003038 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3039 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003040 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003041 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003042 context->handleError(
3043 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003045 }
3046
Geoff Langf41d0ee2016-10-07 13:04:23 -04003047 if (length)
3048 {
3049 // Cast is safe because of comparison to bufSize.
3050 *length = static_cast<GLsizei>(requiredBytes);
3051 }
3052
Jamie Madill0063c512014-08-25 15:47:53 -04003053 return true;
3054}
3055
Geoff Langb1196682014-07-23 13:47:29 -04003056bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003057{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003058 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003059}
3060
Geoff Langb1196682014-07-23 13:47:29 -04003061bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003062{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003063 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3064}
3065
3066bool ValidateGetUniformfvRobustANGLE(Context *context,
3067 GLuint program,
3068 GLint location,
3069 GLsizei bufSize,
3070 GLsizei *length,
3071 GLfloat *params)
3072{
3073 if (!ValidateRobustEntryPoint(context, bufSize))
3074 {
3075 return false;
3076 }
3077
3078 // bufSize is validated in ValidateSizedGetUniform
3079 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3080}
3081
3082bool ValidateGetUniformivRobustANGLE(Context *context,
3083 GLuint program,
3084 GLint location,
3085 GLsizei bufSize,
3086 GLsizei *length,
3087 GLint *params)
3088{
3089 if (!ValidateRobustEntryPoint(context, bufSize))
3090 {
3091 return false;
3092 }
3093
3094 // bufSize is validated in ValidateSizedGetUniform
3095 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3096}
3097
3098bool ValidateGetUniformuivRobustANGLE(Context *context,
3099 GLuint program,
3100 GLint location,
3101 GLsizei bufSize,
3102 GLsizei *length,
3103 GLuint *params)
3104{
3105 if (!ValidateRobustEntryPoint(context, bufSize))
3106 {
3107 return false;
3108 }
3109
3110 if (context->getClientMajorVersion() < 3)
3111 {
3112 context->handleError(
3113 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3114 return false;
3115 }
3116
3117 // bufSize is validated in ValidateSizedGetUniform
3118 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003119}
3120
Austin Kinross08332632015-05-05 13:35:47 -07003121bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3122 const GLenum *attachments, bool defaultFramebuffer)
3123{
3124 if (numAttachments < 0)
3125 {
Jamie Madill437fa652016-05-03 15:13:24 -04003126 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003127 return false;
3128 }
3129
3130 for (GLsizei i = 0; i < numAttachments; ++i)
3131 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003132 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003133 {
3134 if (defaultFramebuffer)
3135 {
Jamie Madill437fa652016-05-03 15:13:24 -04003136 context->handleError(Error(
3137 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003138 return false;
3139 }
3140
3141 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3142 {
Jamie Madill437fa652016-05-03 15:13:24 -04003143 context->handleError(Error(GL_INVALID_OPERATION,
3144 "Requested color attachment is greater than the maximum "
3145 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003146 return false;
3147 }
3148 }
3149 else
3150 {
3151 switch (attachments[i])
3152 {
3153 case GL_DEPTH_ATTACHMENT:
3154 case GL_STENCIL_ATTACHMENT:
3155 case GL_DEPTH_STENCIL_ATTACHMENT:
3156 if (defaultFramebuffer)
3157 {
Jamie Madill437fa652016-05-03 15:13:24 -04003158 context->handleError(
3159 Error(GL_INVALID_ENUM,
3160 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003161 return false;
3162 }
3163 break;
3164 case GL_COLOR:
3165 case GL_DEPTH:
3166 case GL_STENCIL:
3167 if (!defaultFramebuffer)
3168 {
Jamie Madill437fa652016-05-03 15:13:24 -04003169 context->handleError(
3170 Error(GL_INVALID_ENUM,
3171 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003172 return false;
3173 }
3174 break;
3175 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003176 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003177 return false;
3178 }
3179 }
3180 }
3181
3182 return true;
3183}
3184
Austin Kinross6ee1e782015-05-29 17:05:37 -07003185bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3186{
3187 // Note that debug marker calls must not set error state
3188
3189 if (length < 0)
3190 {
3191 return false;
3192 }
3193
3194 if (marker == nullptr)
3195 {
3196 return false;
3197 }
3198
3199 return true;
3200}
3201
3202bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3203{
3204 // Note that debug marker calls must not set error state
3205
3206 if (length < 0)
3207 {
3208 return false;
3209 }
3210
3211 if (length > 0 && marker == nullptr)
3212 {
3213 return false;
3214 }
3215
3216 return true;
3217}
3218
Geoff Langdcab33b2015-07-21 13:03:16 -04003219bool ValidateEGLImageTargetTexture2DOES(Context *context,
3220 egl::Display *display,
3221 GLenum target,
3222 egl::Image *image)
3223{
Geoff Langa8406172015-07-21 16:53:39 -04003224 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3225 {
Jamie Madill437fa652016-05-03 15:13:24 -04003226 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003227 return false;
3228 }
3229
3230 switch (target)
3231 {
3232 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003233 if (!context->getExtensions().eglImage)
3234 {
3235 context->handleError(Error(
3236 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3237 }
3238 break;
3239
3240 case GL_TEXTURE_EXTERNAL_OES:
3241 if (!context->getExtensions().eglImageExternal)
3242 {
3243 context->handleError(Error(
3244 GL_INVALID_ENUM,
3245 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3246 }
Geoff Langa8406172015-07-21 16:53:39 -04003247 break;
3248
3249 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003250 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003251 return false;
3252 }
3253
3254 if (!display->isValidImage(image))
3255 {
Jamie Madill437fa652016-05-03 15:13:24 -04003256 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003257 return false;
3258 }
3259
3260 if (image->getSamples() > 0)
3261 {
Jamie Madill437fa652016-05-03 15:13:24 -04003262 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003263 "cannot create a 2D texture from a multisampled EGL image."));
3264 return false;
3265 }
3266
Jamie Madilla3944d42016-07-22 22:13:26 -04003267 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003268 if (!textureCaps.texturable)
3269 {
Jamie Madill437fa652016-05-03 15:13:24 -04003270 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003271 "EGL image internal format is not supported as a texture."));
3272 return false;
3273 }
3274
Geoff Langdcab33b2015-07-21 13:03:16 -04003275 return true;
3276}
3277
3278bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3279 egl::Display *display,
3280 GLenum target,
3281 egl::Image *image)
3282{
Geoff Langa8406172015-07-21 16:53:39 -04003283 if (!context->getExtensions().eglImage)
3284 {
Jamie Madill437fa652016-05-03 15:13:24 -04003285 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003286 return false;
3287 }
3288
3289 switch (target)
3290 {
3291 case GL_RENDERBUFFER:
3292 break;
3293
3294 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003295 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003296 return false;
3297 }
3298
3299 if (!display->isValidImage(image))
3300 {
Jamie Madill437fa652016-05-03 15:13:24 -04003301 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003302 return false;
3303 }
3304
Jamie Madilla3944d42016-07-22 22:13:26 -04003305 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003306 if (!textureCaps.renderable)
3307 {
Jamie Madill437fa652016-05-03 15:13:24 -04003308 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003309 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3310 return false;
3311 }
3312
Geoff Langdcab33b2015-07-21 13:03:16 -04003313 return true;
3314}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003315
3316bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3317{
Geoff Lang36167ab2015-12-07 10:27:14 -05003318 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003319 {
3320 // The default VAO should always exist
3321 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003322 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003323 return false;
3324 }
3325
3326 return true;
3327}
3328
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003329bool ValidateLinkProgram(Context *context, GLuint program)
3330{
3331 if (context->hasActiveTransformFeedback(program))
3332 {
3333 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003334 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003335 "Cannot link program while program is associated with an active "
3336 "transform feedback object."));
3337 return false;
3338 }
3339 return true;
3340}
3341
Geoff Langc5629752015-12-07 16:29:04 -05003342bool ValidateProgramBinaryBase(Context *context,
3343 GLuint program,
3344 GLenum binaryFormat,
3345 const void *binary,
3346 GLint length)
3347{
3348 Program *programObject = GetValidProgram(context, program);
3349 if (programObject == nullptr)
3350 {
3351 return false;
3352 }
3353
3354 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3355 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3356 programBinaryFormats.end())
3357 {
Jamie Madill437fa652016-05-03 15:13:24 -04003358 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003359 return false;
3360 }
3361
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003362 if (context->hasActiveTransformFeedback(program))
3363 {
3364 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003365 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003366 "Cannot change program binary while program is associated with "
3367 "an active transform feedback object."));
3368 return false;
3369 }
3370
Geoff Langc5629752015-12-07 16:29:04 -05003371 return true;
3372}
3373
3374bool ValidateGetProgramBinaryBase(Context *context,
3375 GLuint program,
3376 GLsizei bufSize,
3377 GLsizei *length,
3378 GLenum *binaryFormat,
3379 void *binary)
3380{
3381 Program *programObject = GetValidProgram(context, program);
3382 if (programObject == nullptr)
3383 {
3384 return false;
3385 }
3386
3387 if (!programObject->isLinked())
3388 {
Jamie Madill437fa652016-05-03 15:13:24 -04003389 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003390 return false;
3391 }
3392
3393 return true;
3394}
Jamie Madillc29968b2016-01-20 11:17:23 -05003395
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003396bool ValidateUseProgram(Context *context, GLuint program)
3397{
3398 if (program != 0)
3399 {
3400 Program *programObject = context->getProgram(program);
3401 if (!programObject)
3402 {
3403 // ES 3.1.0 section 7.3 page 72
3404 if (context->getShader(program))
3405 {
Jamie Madill437fa652016-05-03 15:13:24 -04003406 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003407 Error(GL_INVALID_OPERATION,
3408 "Attempted to use a single shader instead of a shader program."));
3409 return false;
3410 }
3411 else
3412 {
Jamie Madill437fa652016-05-03 15:13:24 -04003413 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003414 return false;
3415 }
3416 }
3417 if (!programObject->isLinked())
3418 {
Jamie Madill437fa652016-05-03 15:13:24 -04003419 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003420 return false;
3421 }
3422 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003423 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003424 {
3425 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003426 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003427 Error(GL_INVALID_OPERATION,
3428 "Cannot change active program while transform feedback is unpaused."));
3429 return false;
3430 }
3431
3432 return true;
3433}
3434
Jamie Madillc29968b2016-01-20 11:17:23 -05003435bool ValidateCopyTexImage2D(ValidationContext *context,
3436 GLenum target,
3437 GLint level,
3438 GLenum internalformat,
3439 GLint x,
3440 GLint y,
3441 GLsizei width,
3442 GLsizei height,
3443 GLint border)
3444{
Martin Radev1be913c2016-07-11 17:59:16 +03003445 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003446 {
3447 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3448 0, x, y, width, height, border);
3449 }
3450
Martin Radev1be913c2016-07-11 17:59:16 +03003451 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003452 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3453 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003454}
Jamie Madillc29968b2016-01-20 11:17:23 -05003455
3456bool ValidateFramebufferRenderbuffer(Context *context,
3457 GLenum target,
3458 GLenum attachment,
3459 GLenum renderbuffertarget,
3460 GLuint renderbuffer)
3461{
3462 if (!ValidFramebufferTarget(target) ||
3463 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3464 {
Jamie Madill437fa652016-05-03 15:13:24 -04003465 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003466 return false;
3467 }
3468
3469 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3470 renderbuffertarget, renderbuffer);
3471}
3472
3473bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3474{
3475 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3476 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3477 {
Jamie Madill437fa652016-05-03 15:13:24 -04003478 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003479 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3480 return false;
3481 }
3482
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003483 ASSERT(context->getGLState().getDrawFramebuffer());
3484 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003485 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3486
3487 // This should come first before the check for the default frame buffer
3488 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3489 // rather than INVALID_OPERATION
3490 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3491 {
3492 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3493
3494 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003495 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3496 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003497 {
3498 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003499 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3500 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3501 // 3.1 is still a bit ambiguous about the error, but future specs are
3502 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003503 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003504 return false;
3505 }
3506 else if (bufs[colorAttachment] >= maxColorAttachment)
3507 {
Jamie Madill437fa652016-05-03 15:13:24 -04003508 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003509 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003510 return false;
3511 }
3512 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3513 frameBufferId != 0)
3514 {
3515 // INVALID_OPERATION-GL is bound to buffer and ith argument
3516 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003517 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003518 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3519 return false;
3520 }
3521 }
3522
3523 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3524 // and n is not 1 or bufs is bound to value other than BACK and NONE
3525 if (frameBufferId == 0)
3526 {
3527 if (n != 1)
3528 {
Jamie Madill437fa652016-05-03 15:13:24 -04003529 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003530 "n must be 1 when GL is bound to the default framebuffer"));
3531 return false;
3532 }
3533
3534 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3535 {
Jamie Madill437fa652016-05-03 15:13:24 -04003536 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003537 GL_INVALID_OPERATION,
3538 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3539 return false;
3540 }
3541 }
3542
3543 return true;
3544}
3545
3546bool ValidateCopyTexSubImage2D(Context *context,
3547 GLenum target,
3548 GLint level,
3549 GLint xoffset,
3550 GLint yoffset,
3551 GLint x,
3552 GLint y,
3553 GLsizei width,
3554 GLsizei height)
3555{
Martin Radev1be913c2016-07-11 17:59:16 +03003556 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003557 {
3558 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3559 yoffset, x, y, width, height, 0);
3560 }
3561
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003562 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3563 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003564}
3565
Olli Etuaho4f667482016-03-30 15:56:35 +03003566bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3567{
3568 if (!ValidBufferTarget(context, target))
3569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003571 return false;
3572 }
3573
3574 if (pname != GL_BUFFER_MAP_POINTER)
3575 {
Jamie Madill437fa652016-05-03 15:13:24 -04003576 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 return false;
3578 }
3579
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003580 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003581
3582 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3583 // target bound to zero generate an INVALID_OPERATION error."
3584 // GLES 3.1 section 6.6 explicitly specifies this error.
3585 if (!buffer)
3586 {
Jamie Madill437fa652016-05-03 15:13:24 -04003587 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003588 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3589 return false;
3590 }
3591
3592 return true;
3593}
3594
3595bool ValidateUnmapBufferBase(Context *context, GLenum target)
3596{
3597 if (!ValidBufferTarget(context, target))
3598 {
Jamie Madill437fa652016-05-03 15:13:24 -04003599 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003600 return false;
3601 }
3602
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003603 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003604
3605 if (buffer == nullptr || !buffer->isMapped())
3606 {
Jamie Madill437fa652016-05-03 15:13:24 -04003607 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003608 return false;
3609 }
3610
3611 return true;
3612}
3613
3614bool ValidateMapBufferRangeBase(Context *context,
3615 GLenum target,
3616 GLintptr offset,
3617 GLsizeiptr length,
3618 GLbitfield access)
3619{
3620 if (!ValidBufferTarget(context, target))
3621 {
Jamie Madill437fa652016-05-03 15:13:24 -04003622 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
3626 if (offset < 0 || length < 0)
3627 {
Jamie Madill437fa652016-05-03 15:13:24 -04003628 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 return false;
3630 }
3631
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003632 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003633
3634 if (!buffer)
3635 {
Jamie Madill437fa652016-05-03 15:13:24 -04003636 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003637 return false;
3638 }
3639
3640 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003641 CheckedNumeric<size_t> checkedOffset(offset);
3642 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003643
Jamie Madille2e406c2016-06-02 13:04:10 -04003644 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003645 {
Jamie Madill437fa652016-05-03 15:13:24 -04003646 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3648 return false;
3649 }
3650
3651 // Check for invalid bits in the mask
3652 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3653 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3654 GL_MAP_UNSYNCHRONIZED_BIT;
3655
3656 if (access & ~(allAccessBits))
3657 {
Jamie Madill437fa652016-05-03 15:13:24 -04003658 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003659 return false;
3660 }
3661
3662 if (length == 0)
3663 {
Jamie Madill437fa652016-05-03 15:13:24 -04003664 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003665 return false;
3666 }
3667
3668 if (buffer->isMapped())
3669 {
Jamie Madill437fa652016-05-03 15:13:24 -04003670 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003671 return false;
3672 }
3673
3674 // Check for invalid bit combinations
3675 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3676 {
Jamie Madill437fa652016-05-03 15:13:24 -04003677 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3679 return false;
3680 }
3681
3682 GLbitfield writeOnlyBits =
3683 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3684
3685 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3686 {
Jamie Madill437fa652016-05-03 15:13:24 -04003687 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 "Invalid access bits when mapping buffer for reading: 0x%X.",
3689 access));
3690 return false;
3691 }
3692
3693 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3694 {
Jamie Madill437fa652016-05-03 15:13:24 -04003695 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003696 GL_INVALID_OPERATION,
3697 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3698 return false;
3699 }
3700 return true;
3701}
3702
3703bool ValidateFlushMappedBufferRangeBase(Context *context,
3704 GLenum target,
3705 GLintptr offset,
3706 GLsizeiptr length)
3707{
3708 if (offset < 0 || length < 0)
3709 {
Jamie Madill437fa652016-05-03 15:13:24 -04003710 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
3714 if (!ValidBufferTarget(context, target))
3715 {
Jamie Madill437fa652016-05-03 15:13:24 -04003716 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003717 return false;
3718 }
3719
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003720 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003721
3722 if (buffer == nullptr)
3723 {
Jamie Madill437fa652016-05-03 15:13:24 -04003724 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003725 return false;
3726 }
3727
3728 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003731 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3732 return false;
3733 }
3734
3735 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003736 CheckedNumeric<size_t> checkedOffset(offset);
3737 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003738
Jamie Madille2e406c2016-06-02 13:04:10 -04003739 if (!checkedSize.IsValid() ||
3740 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 {
Jamie Madill437fa652016-05-03 15:13:24 -04003742 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3744 return false;
3745 }
3746
3747 return true;
3748}
3749
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003750bool ValidateGenerateMipmap(Context *context, GLenum target)
3751{
3752 if (!ValidTextureTarget(context, target))
3753 {
3754 context->handleError(Error(GL_INVALID_ENUM));
3755 return false;
3756 }
3757
3758 Texture *texture = context->getTargetTexture(target);
3759
3760 if (texture == nullptr)
3761 {
3762 context->handleError(Error(GL_INVALID_OPERATION));
3763 return false;
3764 }
3765
3766 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3767
3768 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3769 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3770 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3771 {
3772 context->handleError(Error(GL_INVALID_OPERATION));
3773 return false;
3774 }
3775
Jamie Madilla3944d42016-07-22 22:13:26 -04003776 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3777 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3778 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003779
3780 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3781 // unsized formats or that are color renderable and filterable. Since we do not track if
3782 // the texture was created with sized or unsized format (only sized formats are stored),
3783 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3784 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3785 // textures since they're the only texture format that can be created with unsized formats
3786 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3787 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003788 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3789 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003790 {
3791 context->handleError(Error(GL_INVALID_OPERATION));
3792 return false;
3793 }
3794
3795 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003796 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003797 {
3798 context->handleError(Error(GL_INVALID_OPERATION));
3799 return false;
3800 }
3801
3802 // Non-power of 2 ES2 check
3803 if (!context->getExtensions().textureNPOT &&
3804 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3805 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3806 {
Martin Radev1be913c2016-07-11 17:59:16 +03003807 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003808 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3809 context->handleError(Error(GL_INVALID_OPERATION));
3810 return false;
3811 }
3812
3813 // Cube completeness check
3814 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3815 {
3816 context->handleError(Error(GL_INVALID_OPERATION));
3817 return false;
3818 }
3819
3820 return true;
3821}
3822
Olli Etuaho41997e72016-03-10 13:38:39 +02003823bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3824{
3825 return ValidateGenOrDelete(context, n);
3826}
3827
3828bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3829{
3830 return ValidateGenOrDelete(context, n);
3831}
3832
3833bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3834{
3835 return ValidateGenOrDelete(context, n);
3836}
3837
3838bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3839{
3840 return ValidateGenOrDelete(context, n);
3841}
3842
3843bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3844{
3845 return ValidateGenOrDelete(context, n);
3846}
3847
3848bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3849{
3850 return ValidateGenOrDelete(context, n);
3851}
3852
3853bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3854{
3855 return ValidateGenOrDelete(context, n);
3856}
3857
3858bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3859{
3860 return ValidateGenOrDelete(context, n);
3861}
3862
3863bool ValidateGenOrDelete(Context *context, GLint n)
3864{
3865 if (n < 0)
3866 {
Jamie Madill437fa652016-05-03 15:13:24 -04003867 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003868 return false;
3869 }
3870 return true;
3871}
3872
Geoff Langf41a7152016-09-19 15:11:17 -04003873bool ValidateEnable(Context *context, GLenum cap)
3874{
3875 if (!ValidCap(context, cap, false))
3876 {
3877 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3878 return false;
3879 }
3880
3881 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3882 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3883 {
3884 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3885 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3886
3887 // We also output an error message to the debugger window if tracing is active, so that
3888 // developers can see the error message.
3889 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003890 return false;
3891 }
3892
3893 return true;
3894}
3895
3896bool ValidateDisable(Context *context, GLenum cap)
3897{
3898 if (!ValidCap(context, cap, false))
3899 {
3900 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3901 return false;
3902 }
3903
3904 return true;
3905}
3906
3907bool ValidateIsEnabled(Context *context, GLenum cap)
3908{
3909 if (!ValidCap(context, cap, true))
3910 {
3911 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3912 return false;
3913 }
3914
3915 return true;
3916}
3917
Geoff Langff5b2d52016-09-07 11:32:23 -04003918bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3919{
3920 if (!context->getExtensions().robustClientMemory)
3921 {
3922 context->handleError(
3923 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3924 return false;
3925 }
3926
3927 if (bufSize < 0)
3928 {
3929 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3930 return false;
3931 }
3932
3933 return true;
3934}
3935
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003936bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3937{
3938 if (bufSize < numParams)
3939 {
3940 context->handleError(Error(GL_INVALID_OPERATION,
3941 "%u parameters are required but %i were provided.", numParams,
3942 bufSize));
3943 return false;
3944 }
3945
3946 return true;
3947}
3948
Geoff Langff5b2d52016-09-07 11:32:23 -04003949bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
3950 GLenum target,
3951 GLenum attachment,
3952 GLenum pname,
3953 GLsizei *numParams)
3954{
3955 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
3956 *numParams = 1;
3957
3958 if (!ValidFramebufferTarget(target))
3959 {
3960 context->handleError(Error(GL_INVALID_ENUM));
3961 return false;
3962 }
3963
3964 int clientVersion = context->getClientMajorVersion();
3965
3966 switch (pname)
3967 {
3968 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3969 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3970 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3971 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3972 break;
3973
3974 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3975 if (clientVersion < 3 && !context->getExtensions().sRGB)
3976 {
3977 context->handleError(Error(GL_INVALID_ENUM));
3978 return false;
3979 }
3980 break;
3981
3982 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3983 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3984 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3985 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3986 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3987 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3988 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3989 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3990 if (clientVersion < 3)
3991 {
3992 context->handleError(Error(GL_INVALID_ENUM));
3993 return false;
3994 }
3995 break;
3996
3997 default:
3998 context->handleError(Error(GL_INVALID_ENUM));
3999 return false;
4000 }
4001
4002 // Determine if the attachment is a valid enum
4003 switch (attachment)
4004 {
4005 case GL_BACK:
4006 case GL_FRONT:
4007 case GL_DEPTH:
4008 case GL_STENCIL:
4009 case GL_DEPTH_STENCIL_ATTACHMENT:
4010 if (clientVersion < 3)
4011 {
4012 context->handleError(Error(GL_INVALID_ENUM));
4013 return false;
4014 }
4015 break;
4016
4017 case GL_DEPTH_ATTACHMENT:
4018 case GL_STENCIL_ATTACHMENT:
4019 break;
4020
4021 default:
4022 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4023 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4024 {
4025 context->handleError(Error(GL_INVALID_ENUM));
4026 return false;
4027 }
4028 break;
4029 }
4030
4031 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4032 ASSERT(framebuffer);
4033
4034 if (framebuffer->id() == 0)
4035 {
4036 if (clientVersion < 3)
4037 {
4038 context->handleError(Error(GL_INVALID_OPERATION));
4039 return false;
4040 }
4041
4042 switch (attachment)
4043 {
4044 case GL_BACK:
4045 case GL_DEPTH:
4046 case GL_STENCIL:
4047 break;
4048
4049 default:
4050 context->handleError(Error(GL_INVALID_OPERATION));
4051 return false;
4052 }
4053 }
4054 else
4055 {
4056 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4057 {
4058 // Valid attachment query
4059 }
4060 else
4061 {
4062 switch (attachment)
4063 {
4064 case GL_DEPTH_ATTACHMENT:
4065 case GL_STENCIL_ATTACHMENT:
4066 break;
4067
4068 case GL_DEPTH_STENCIL_ATTACHMENT:
4069 if (!framebuffer->hasValidDepthStencil())
4070 {
4071 context->handleError(Error(GL_INVALID_OPERATION));
4072 return false;
4073 }
4074 break;
4075
4076 default:
4077 context->handleError(Error(GL_INVALID_OPERATION));
4078 return false;
4079 }
4080 }
4081 }
4082
4083 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4084 if (attachmentObject)
4085 {
4086 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4087 attachmentObject->type() == GL_TEXTURE ||
4088 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4089
4090 switch (pname)
4091 {
4092 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4093 if (attachmentObject->type() != GL_RENDERBUFFER &&
4094 attachmentObject->type() != GL_TEXTURE)
4095 {
4096 context->handleError(Error(GL_INVALID_ENUM));
4097 return false;
4098 }
4099 break;
4100
4101 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4102 if (attachmentObject->type() != GL_TEXTURE)
4103 {
4104 context->handleError(Error(GL_INVALID_ENUM));
4105 return false;
4106 }
4107 break;
4108
4109 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4110 if (attachmentObject->type() != GL_TEXTURE)
4111 {
4112 context->handleError(Error(GL_INVALID_ENUM));
4113 return false;
4114 }
4115 break;
4116
4117 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4118 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4119 {
4120 context->handleError(Error(GL_INVALID_OPERATION));
4121 return false;
4122 }
4123 break;
4124
4125 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4126 if (attachmentObject->type() != GL_TEXTURE)
4127 {
4128 context->handleError(Error(GL_INVALID_ENUM));
4129 return false;
4130 }
4131 break;
4132
4133 default:
4134 break;
4135 }
4136 }
4137 else
4138 {
4139 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4140 // is NONE, then querying any other pname will generate INVALID_ENUM.
4141
4142 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4143 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4144 // INVALID_OPERATION for all other pnames
4145
4146 switch (pname)
4147 {
4148 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4149 break;
4150
4151 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4152 if (clientVersion < 3)
4153 {
4154 context->handleError(Error(GL_INVALID_ENUM));
4155 return false;
4156 }
4157 break;
4158
4159 default:
4160 if (clientVersion < 3)
4161 {
4162 context->handleError(Error(GL_INVALID_ENUM));
4163 return false;
4164 }
4165 else
4166 {
4167 context->handleError(Error(GL_INVALID_OPERATION));
4168 return false;
4169 }
4170 }
4171 }
4172
4173 return true;
4174}
4175
4176bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4177 GLenum target,
4178 GLenum attachment,
4179 GLenum pname,
4180 GLsizei bufSize,
4181 GLsizei *numParams)
4182{
4183 if (!ValidateRobustEntryPoint(context, bufSize))
4184 {
4185 return false;
4186 }
4187
4188 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4189 {
4190 return false;
4191 }
4192
4193 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4194 {
4195 return false;
4196 }
4197
4198 return true;
4199}
4200
4201bool ValidateGetBufferParameteriv(ValidationContext *context,
4202 GLenum target,
4203 GLenum pname,
4204 GLsizei *numParams)
4205{
4206 // Initialize result
4207 *numParams = 0;
4208
4209 if (!ValidBufferTarget(context, target))
4210 {
4211 context->handleError(Error(GL_INVALID_ENUM));
4212 return false;
4213 }
4214
4215 if (!ValidBufferParameter(context, pname, numParams))
4216 {
4217 context->handleError(Error(GL_INVALID_ENUM));
4218 return false;
4219 }
4220
4221 if (context->getGLState().getTargetBuffer(target) == nullptr)
4222 {
4223 // A null buffer means that "0" is bound to the requested buffer target
4224 context->handleError(Error(GL_INVALID_OPERATION));
4225 return false;
4226 }
4227
4228 return true;
4229}
4230
4231bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4232 GLenum target,
4233 GLenum pname,
4234 GLsizei bufSize,
4235 GLsizei *numParams)
4236{
4237 if (!ValidateRobustEntryPoint(context, bufSize))
4238 {
4239 return false;
4240 }
4241
4242 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
4243 {
4244 return false;
4245 }
4246
4247 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4248 {
4249 return false;
4250 }
4251
4252 return true;
4253}
4254
4255bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4256{
4257 // Currently, all GetProgramiv queries return 1 parameter
4258 *numParams = 1;
4259
4260 Program *programObject = GetValidProgram(context, program);
4261 if (!programObject)
4262 {
4263 return false;
4264 }
4265
4266 switch (pname)
4267 {
4268 case GL_DELETE_STATUS:
4269 case GL_LINK_STATUS:
4270 case GL_VALIDATE_STATUS:
4271 case GL_INFO_LOG_LENGTH:
4272 case GL_ATTACHED_SHADERS:
4273 case GL_ACTIVE_ATTRIBUTES:
4274 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4275 case GL_ACTIVE_UNIFORMS:
4276 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4277 break;
4278
4279 case GL_PROGRAM_BINARY_LENGTH:
4280 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4281 {
4282 context->handleError(Error(GL_INVALID_ENUM,
4283 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4284 "GL_OES_get_program_binary or ES 3.0."));
4285 return false;
4286 }
4287 break;
4288
4289 case GL_ACTIVE_UNIFORM_BLOCKS:
4290 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4291 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4292 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4293 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4294 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4295 if (context->getClientMajorVersion() < 3)
4296 {
4297 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4298 return false;
4299 }
4300 break;
4301
4302 default:
4303 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4304 return false;
4305 }
4306
4307 return true;
4308}
4309
4310bool ValidateGetProgramivRobustANGLE(Context *context,
4311 GLuint program,
4312 GLenum pname,
4313 GLsizei bufSize,
4314 GLsizei *numParams)
4315{
4316 if (!ValidateRobustEntryPoint(context, bufSize))
4317 {
4318 return false;
4319 }
4320
4321 if (!ValidateGetProgramiv(context, program, pname, numParams))
4322 {
4323 return false;
4324 }
4325
4326 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4327 {
4328 return false;
4329 }
4330
4331 return true;
4332}
4333
Geoff Lang740d9022016-10-07 11:20:52 -04004334bool ValidateGetRenderbufferParameteriv(Context *context,
4335 GLenum target,
4336 GLenum pname,
4337 GLint *params)
4338{
4339 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4340}
4341
4342bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4343 GLenum target,
4344 GLenum pname,
4345 GLsizei bufSize,
4346 GLsizei *length,
4347 GLint *params)
4348{
4349 if (!ValidateRobustEntryPoint(context, bufSize))
4350 {
4351 return false;
4352 }
4353
4354 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4355 {
4356 return false;
4357 }
4358
4359 if (!ValidateRobustBufferSize(context, bufSize, *length))
4360 {
4361 return false;
4362 }
4363
4364 return true;
4365}
4366
Geoff Langd7d0ed32016-10-07 11:33:51 -04004367bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4368{
4369 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4370}
4371
4372bool ValidateGetShaderivRobustANGLE(Context *context,
4373 GLuint shader,
4374 GLenum pname,
4375 GLsizei bufSize,
4376 GLsizei *length,
4377 GLint *params)
4378{
4379 if (!ValidateRobustEntryPoint(context, bufSize))
4380 {
4381 return false;
4382 }
4383
4384 if (!ValidateGetShaderivBase(context, shader, pname, length))
4385 {
4386 return false;
4387 }
4388
4389 if (!ValidateRobustBufferSize(context, bufSize, *length))
4390 {
4391 return false;
4392 }
4393
4394 return true;
4395}
4396
Geoff Langc1984ed2016-10-07 12:41:00 -04004397bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4398{
4399 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4400}
4401
4402bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4403 GLenum target,
4404 GLenum pname,
4405 GLsizei bufSize,
4406 GLsizei *length,
4407 GLfloat *params)
4408{
4409 if (!ValidateRobustEntryPoint(context, bufSize))
4410 {
4411 return false;
4412 }
4413
4414 if (!ValidateGetTexParameterBase(context, target, pname, length))
4415 {
4416 return false;
4417 }
4418
4419 if (!ValidateRobustBufferSize(context, bufSize, *length))
4420 {
4421 return false;
4422 }
4423
4424 return true;
4425}
4426
4427bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4428{
4429 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4430}
4431
4432bool ValidateGetTexParameterivRobustANGLE(Context *context,
4433 GLenum target,
4434 GLenum pname,
4435 GLsizei bufSize,
4436 GLsizei *length,
4437 GLint *params)
4438{
4439 if (!ValidateRobustEntryPoint(context, bufSize))
4440 {
4441 return false;
4442 }
4443
4444 if (!ValidateGetTexParameterBase(context, target, pname, length))
4445 {
4446 return false;
4447 }
4448
4449 if (!ValidateRobustBufferSize(context, bufSize, *length))
4450 {
4451 return false;
4452 }
4453
4454 return true;
4455}
4456
4457bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4458{
4459 return ValidateTexParameterBase(context, target, pname, -1, &param);
4460}
4461
4462bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4463{
4464 return ValidateTexParameterBase(context, target, pname, -1, params);
4465}
4466
4467bool ValidateTexParameterfvRobustANGLE(Context *context,
4468 GLenum target,
4469 GLenum pname,
4470 GLsizei bufSize,
4471 const GLfloat *params)
4472{
4473 if (!ValidateRobustEntryPoint(context, bufSize))
4474 {
4475 return false;
4476 }
4477
4478 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4479}
4480
4481bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4482{
4483 return ValidateTexParameterBase(context, target, pname, -1, &param);
4484}
4485
4486bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4487{
4488 return ValidateTexParameterBase(context, target, pname, -1, params);
4489}
4490
4491bool ValidateTexParameterivRobustANGLE(Context *context,
4492 GLenum target,
4493 GLenum pname,
4494 GLsizei bufSize,
4495 const GLint *params)
4496{
4497 if (!ValidateRobustEntryPoint(context, bufSize))
4498 {
4499 return false;
4500 }
4501
4502 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4503}
4504
4505bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4506{
4507 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4508}
4509
4510bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4511 GLuint sampler,
4512 GLenum pname,
4513 GLuint bufSize,
4514 GLsizei *length,
4515 GLfloat *params)
4516{
4517 if (!ValidateRobustEntryPoint(context, bufSize))
4518 {
4519 return false;
4520 }
4521
4522 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4523 {
4524 return false;
4525 }
4526
4527 if (!ValidateRobustBufferSize(context, bufSize, *length))
4528 {
4529 return false;
4530 }
4531
4532 return true;
4533}
4534
4535bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4536{
4537 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4538}
4539
4540bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4541 GLuint sampler,
4542 GLenum pname,
4543 GLuint bufSize,
4544 GLsizei *length,
4545 GLint *params)
4546{
4547 if (!ValidateRobustEntryPoint(context, bufSize))
4548 {
4549 return false;
4550 }
4551
4552 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4553 {
4554 return false;
4555 }
4556
4557 if (!ValidateRobustBufferSize(context, bufSize, *length))
4558 {
4559 return false;
4560 }
4561
4562 return true;
4563}
4564
4565bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4566{
4567 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4568}
4569
4570bool ValidateSamplerParameterfv(Context *context,
4571 GLuint sampler,
4572 GLenum pname,
4573 const GLfloat *params)
4574{
4575 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4576}
4577
4578bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4579 GLuint sampler,
4580 GLenum pname,
4581 GLsizei bufSize,
4582 const GLfloat *params)
4583{
4584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
4588
4589 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4590}
4591
4592bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4593{
4594 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4595}
4596
4597bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4598{
4599 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4600}
4601
4602bool ValidateSamplerParameterivRobustANGLE(Context *context,
4603 GLuint sampler,
4604 GLenum pname,
4605 GLsizei bufSize,
4606 const GLint *params)
4607{
4608 if (!ValidateRobustEntryPoint(context, bufSize))
4609 {
4610 return false;
4611 }
4612
4613 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4614}
4615
Geoff Lang0b031062016-10-13 14:30:04 -04004616bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
4617{
4618 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4619}
4620
4621bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4622 GLuint index,
4623 GLenum pname,
4624 GLsizei bufSize,
4625 GLsizei *length,
4626 GLfloat *params)
4627{
4628 if (!ValidateRobustEntryPoint(context, bufSize))
4629 {
4630 return false;
4631 }
4632
4633 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4634 {
4635 return false;
4636 }
4637
4638 if (!ValidateRobustBufferSize(context, bufSize, *length))
4639 {
4640 return false;
4641 }
4642
4643 return true;
4644}
4645
4646bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
4647{
4648 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4649}
4650
4651bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4652 GLuint index,
4653 GLenum pname,
4654 GLsizei bufSize,
4655 GLsizei *length,
4656 GLint *params)
4657{
4658 if (!ValidateRobustEntryPoint(context, bufSize))
4659 {
4660 return false;
4661 }
4662
4663 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4664 {
4665 return false;
4666 }
4667
4668 if (!ValidateRobustBufferSize(context, bufSize, *length))
4669 {
4670 return false;
4671 }
4672
4673 return true;
4674}
4675
4676bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
4677{
4678 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
4679}
4680
4681bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4682 GLuint index,
4683 GLenum pname,
4684 GLsizei bufSize,
4685 GLsizei *length,
4686 void **pointer)
4687{
4688 if (!ValidateRobustEntryPoint(context, bufSize))
4689 {
4690 return false;
4691 }
4692
4693 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4694 {
4695 return false;
4696 }
4697
4698 if (!ValidateRobustBufferSize(context, bufSize, *length))
4699 {
4700 return false;
4701 }
4702
4703 return true;
4704}
4705
4706bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4707{
4708 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4709}
4710
4711bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4712 GLuint index,
4713 GLenum pname,
4714 GLsizei bufSize,
4715 GLsizei *length,
4716 GLint *params)
4717{
4718 if (!ValidateRobustEntryPoint(context, bufSize))
4719 {
4720 return false;
4721 }
4722
4723 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4724 {
4725 return false;
4726 }
4727
4728 if (!ValidateRobustBufferSize(context, bufSize, *length))
4729 {
4730 return false;
4731 }
4732
4733 return true;
4734}
4735
4736bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4737{
4738 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4739}
4740
4741bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4742 GLuint index,
4743 GLenum pname,
4744 GLsizei bufSize,
4745 GLsizei *length,
4746 GLuint *params)
4747{
4748 if (!ValidateRobustEntryPoint(context, bufSize))
4749 {
4750 return false;
4751 }
4752
4753 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4754 {
4755 return false;
4756 }
4757
4758 if (!ValidateRobustBufferSize(context, bufSize, *length))
4759 {
4760 return false;
4761 }
4762
4763 return true;
4764}
4765
Jamie Madillc29968b2016-01-20 11:17:23 -05004766} // namespace gl