blob: 6fdae40aa06d24232005ff1cb2893d891c46d10a [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 Langff5b2d52016-09-07 11:32:23 -0400170bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
171{
172 if (bufSize < numParams)
173 {
174 context->handleError(Error(GL_INVALID_OPERATION,
175 "%u parameters are required but %i were provided.", numParams,
176 bufSize));
177 return false;
178 }
179
180 return true;
181}
182
Geoff Lang62fce5b2016-09-30 10:46:35 -0400183bool ValidateReadPixelsBase(ValidationContext *context,
184 GLint x,
185 GLint y,
186 GLsizei width,
187 GLsizei height,
188 GLenum format,
189 GLenum type,
190 GLsizei bufSize,
191 GLsizei *length,
192 GLvoid *pixels)
193{
194 if (length != nullptr)
195 {
196 *length = 0;
197 }
198
199 if (width < 0 || height < 0)
200 {
201 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
202 return false;
203 }
204
205 auto readFramebuffer = context->getGLState().getReadFramebuffer();
206
207 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
208 {
209 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
210 return false;
211 }
212
213 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
214 {
215 context->handleError(Error(GL_INVALID_OPERATION));
216 return false;
217 }
218
219 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
220 ASSERT(framebuffer);
221
222 if (framebuffer->getReadBufferState() == GL_NONE)
223 {
224 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
225 return false;
226 }
227
228 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
229 if (!readBuffer)
230 {
231 context->handleError(Error(GL_INVALID_OPERATION));
232 return false;
233 }
234
235 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
236 GLenum currentType = framebuffer->getImplementationColorReadType();
237 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
238
239 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
240 bool validFormatTypeCombination =
241 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
242
243 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
244 {
245 context->handleError(Error(GL_INVALID_OPERATION));
246 return false;
247 }
248
249 // Check for pixel pack buffer related API errors
250 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
251 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
252 {
253 // ...the buffer object's data store is currently mapped.
254 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
255 return false;
256 }
257
258 // .. the data would be packed to the buffer object such that the memory writes required
259 // would exceed the data store size.
260 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
261 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
262 const gl::Extents size(width, height, 1);
263 const auto &pack = context->getGLState().getPackState();
264
265 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
266 if (endByteOrErr.isError())
267 {
268 context->handleError(endByteOrErr.getError());
269 return false;
270 }
271
272 size_t endByte = endByteOrErr.getResult();
273 if (bufSize >= 0)
274 {
275
276 if (static_cast<size_t>(bufSize) < endByte)
277 {
278 context->handleError(
279 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
280 return false;
281 }
282 }
283
284 if (pixelPackBuffer != nullptr)
285 {
286 CheckedNumeric<size_t> checkedEndByte(endByte);
287 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
288 checkedEndByte += checkedOffset;
289
290 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
291 {
292 // Overflow past the end of the buffer
293 context->handleError(
294 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
295 return false;
296 }
297 }
298
299 if (length != nullptr)
300 {
301 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
302 {
303 context->handleError(
304 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
305 return false;
306 }
307
308 *length = static_cast<GLsizei>(endByte);
309 }
310
311 return true;
312}
313
Geoff Lang740d9022016-10-07 11:20:52 -0400314bool ValidateGetRenderbufferParameterivBase(Context *context,
315 GLenum target,
316 GLenum pname,
317 GLsizei *length)
318{
319 if (length)
320 {
321 *length = 0;
322 }
323
324 if (target != GL_RENDERBUFFER)
325 {
326 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
327 return false;
328 }
329
330 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
331 if (renderbuffer == nullptr)
332 {
333 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
334 return false;
335 }
336
337 switch (pname)
338 {
339 case GL_RENDERBUFFER_WIDTH:
340 case GL_RENDERBUFFER_HEIGHT:
341 case GL_RENDERBUFFER_INTERNAL_FORMAT:
342 case GL_RENDERBUFFER_RED_SIZE:
343 case GL_RENDERBUFFER_GREEN_SIZE:
344 case GL_RENDERBUFFER_BLUE_SIZE:
345 case GL_RENDERBUFFER_ALPHA_SIZE:
346 case GL_RENDERBUFFER_DEPTH_SIZE:
347 case GL_RENDERBUFFER_STENCIL_SIZE:
348 break;
349
350 case GL_RENDERBUFFER_SAMPLES_ANGLE:
351 if (!context->getExtensions().framebufferMultisample)
352 {
353 context->handleError(
354 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
355 return false;
356 }
357 break;
358
359 default:
360 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
361 return false;
362 }
363
364 if (length)
365 {
366 *length = 1;
367 }
368 return true;
369}
370
Geoff Langd7d0ed32016-10-07 11:33:51 -0400371bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
372{
373 if (length)
374 {
375 *length = 0;
376 }
377
378 if (GetValidShader(context, shader) == nullptr)
379 {
380 return false;
381 }
382
383 switch (pname)
384 {
385 case GL_SHADER_TYPE:
386 case GL_DELETE_STATUS:
387 case GL_COMPILE_STATUS:
388 case GL_INFO_LOG_LENGTH:
389 case GL_SHADER_SOURCE_LENGTH:
390 break;
391
392 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
393 if (!context->getExtensions().translatedShaderSource)
394 {
395 context->handleError(
396 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
397 return false;
398 }
399 break;
400
401 default:
402 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
403 return false;
404 }
405
406 if (length)
407 {
408 *length = 1;
409 }
410 return true;
411}
412
Geoff Langc1984ed2016-10-07 12:41:00 -0400413bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
414{
415 if (length)
416 {
417 *length = 0;
418 }
419
420 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
421 {
422 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
423 return false;
424 }
425
426 if (context->getTargetTexture(target) == nullptr)
427 {
428 // Should only be possible for external textures
429 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
430 return false;
431 }
432
433 switch (pname)
434 {
435 case GL_TEXTURE_MAG_FILTER:
436 case GL_TEXTURE_MIN_FILTER:
437 case GL_TEXTURE_WRAP_S:
438 case GL_TEXTURE_WRAP_T:
439 break;
440
441 case GL_TEXTURE_USAGE_ANGLE:
442 if (!context->getExtensions().textureUsage)
443 {
444 context->handleError(
445 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
446 return false;
447 }
448 break;
449
450 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
451 if (!context->getExtensions().textureFilterAnisotropic)
452 {
453 context->handleError(
454 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
455 return false;
456 }
457 break;
458
459 case GL_TEXTURE_IMMUTABLE_FORMAT:
460 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
461 {
462 context->handleError(
463 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
464 return false;
465 }
466 break;
467
468 case GL_TEXTURE_WRAP_R:
469 case GL_TEXTURE_IMMUTABLE_LEVELS:
470 case GL_TEXTURE_SWIZZLE_R:
471 case GL_TEXTURE_SWIZZLE_G:
472 case GL_TEXTURE_SWIZZLE_B:
473 case GL_TEXTURE_SWIZZLE_A:
474 case GL_TEXTURE_BASE_LEVEL:
475 case GL_TEXTURE_MAX_LEVEL:
476 case GL_TEXTURE_MIN_LOD:
477 case GL_TEXTURE_MAX_LOD:
478 case GL_TEXTURE_COMPARE_MODE:
479 case GL_TEXTURE_COMPARE_FUNC:
480 if (context->getClientMajorVersion() < 3)
481 {
482 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
483 return false;
484 }
485 break;
486
487 default:
488 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
489 return false;
490 }
491
492 if (length)
493 {
494 *length = 1;
495 }
496 return true;
497}
498
499template <typename ParamType>
500bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
501{
502 switch (ConvertToGLenum(params[0]))
503 {
504 case GL_CLAMP_TO_EDGE:
505 break;
506
507 case GL_REPEAT:
508 case GL_MIRRORED_REPEAT:
509 if (isExternalTextureTarget)
510 {
511 // OES_EGL_image_external specifies this error.
512 context->handleError(Error(
513 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
514 return false;
515 }
516 break;
517
518 default:
519 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
520 return false;
521 }
522
523 return true;
524}
525
526template <typename ParamType>
527bool ValidateTextureMinFilterValue(Context *context,
528 ParamType *params,
529 bool isExternalTextureTarget)
530{
531 switch (ConvertToGLenum(params[0]))
532 {
533 case GL_NEAREST:
534 case GL_LINEAR:
535 break;
536
537 case GL_NEAREST_MIPMAP_NEAREST:
538 case GL_LINEAR_MIPMAP_NEAREST:
539 case GL_NEAREST_MIPMAP_LINEAR:
540 case GL_LINEAR_MIPMAP_LINEAR:
541 if (isExternalTextureTarget)
542 {
543 // OES_EGL_image_external specifies this error.
544 context->handleError(
545 Error(GL_INVALID_ENUM,
546 "external textures only support NEAREST and LINEAR filtering"));
547 return false;
548 }
549 break;
550
551 default:
552 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
553 return false;
554 }
555
556 return true;
557}
558
559template <typename ParamType>
560bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
561{
562 switch (ConvertToGLenum(params[0]))
563 {
564 case GL_NEAREST:
565 case GL_LINEAR:
566 break;
567
568 default:
569 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
570 return false;
571 }
572
573 return true;
574}
575
576template <typename ParamType>
577bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
578{
579 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
580 switch (ConvertToGLenum(params[0]))
581 {
582 case GL_NONE:
583 case GL_COMPARE_REF_TO_TEXTURE:
584 break;
585
586 default:
587 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
588 return false;
589 }
590
591 return true;
592}
593
594template <typename ParamType>
595bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
596{
597 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
598 switch (ConvertToGLenum(params[0]))
599 {
600 case GL_LEQUAL:
601 case GL_GEQUAL:
602 case GL_LESS:
603 case GL_GREATER:
604 case GL_EQUAL:
605 case GL_NOTEQUAL:
606 case GL_ALWAYS:
607 case GL_NEVER:
608 break;
609
610 default:
611 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
612 return false;
613 }
614
615 return true;
616}
617
618template <typename ParamType>
619bool ValidateTexParameterBase(Context *context,
620 GLenum target,
621 GLenum pname,
622 GLsizei bufSize,
623 ParamType *params)
624{
625 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
626 {
627 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
628 return false;
629 }
630
631 if (context->getTargetTexture(target) == nullptr)
632 {
633 // Should only be possible for external textures
634 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
635 return false;
636 }
637
638 const GLsizei minBufSize = 1;
639 if (bufSize >= 0 && bufSize < minBufSize)
640 {
641 context->handleError(
642 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
643 return false;
644 }
645
646 switch (pname)
647 {
648 case GL_TEXTURE_WRAP_R:
649 case GL_TEXTURE_SWIZZLE_R:
650 case GL_TEXTURE_SWIZZLE_G:
651 case GL_TEXTURE_SWIZZLE_B:
652 case GL_TEXTURE_SWIZZLE_A:
653 case GL_TEXTURE_BASE_LEVEL:
654 case GL_TEXTURE_MAX_LEVEL:
655 case GL_TEXTURE_COMPARE_MODE:
656 case GL_TEXTURE_COMPARE_FUNC:
657 case GL_TEXTURE_MIN_LOD:
658 case GL_TEXTURE_MAX_LOD:
659 if (context->getClientMajorVersion() < 3)
660 {
661 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
662 return false;
663 }
664 if (target == GL_TEXTURE_EXTERNAL_OES &&
665 !context->getExtensions().eglImageExternalEssl3)
666 {
667 context->handleError(Error(GL_INVALID_ENUM,
668 "ES3 texture parameters are not available without "
669 "GL_OES_EGL_image_external_essl3."));
670 return false;
671 }
672 break;
673
674 default:
675 break;
676 }
677
678 switch (pname)
679 {
680 case GL_TEXTURE_WRAP_S:
681 case GL_TEXTURE_WRAP_T:
682 case GL_TEXTURE_WRAP_R:
683 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
684 {
685 return false;
686 }
687 break;
688
689 case GL_TEXTURE_MIN_FILTER:
690 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
691 {
692 return false;
693 }
694 break;
695
696 case GL_TEXTURE_MAG_FILTER:
697 if (!ValidateTextureMagFilterValue(context, params))
698 {
699 return false;
700 }
701 break;
702
703 case GL_TEXTURE_USAGE_ANGLE:
704 switch (ConvertToGLenum(params[0]))
705 {
706 case GL_NONE:
707 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
708 break;
709
710 default:
711 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
712 return false;
713 }
714 break;
715
716 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
717 if (!context->getExtensions().textureFilterAnisotropic)
718 {
719 context->handleError(
720 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
721 return false;
722 }
723
724 // we assume the parameter passed to this validation method is truncated, not rounded
725 if (params[0] < 1)
726 {
727 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
728 return false;
729 }
730 break;
731
732 case GL_TEXTURE_MIN_LOD:
733 case GL_TEXTURE_MAX_LOD:
734 // any value is permissible
735 break;
736
737 case GL_TEXTURE_COMPARE_MODE:
738 if (!ValidateTextureCompareModeValue(context, params))
739 {
740 return false;
741 }
742 break;
743
744 case GL_TEXTURE_COMPARE_FUNC:
745 if (!ValidateTextureCompareFuncValue(context, params))
746 {
747 return false;
748 }
749 break;
750
751 case GL_TEXTURE_SWIZZLE_R:
752 case GL_TEXTURE_SWIZZLE_G:
753 case GL_TEXTURE_SWIZZLE_B:
754 case GL_TEXTURE_SWIZZLE_A:
755 switch (ConvertToGLenum(params[0]))
756 {
757 case GL_RED:
758 case GL_GREEN:
759 case GL_BLUE:
760 case GL_ALPHA:
761 case GL_ZERO:
762 case GL_ONE:
763 break;
764
765 default:
766 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
767 return false;
768 }
769 break;
770
771 case GL_TEXTURE_BASE_LEVEL:
772 if (params[0] < 0)
773 {
774 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
775 return false;
776 }
777 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
778 {
779 context->handleError(
780 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
781 return false;
782 }
783 break;
784
785 case GL_TEXTURE_MAX_LEVEL:
786 if (params[0] < 0)
787 {
788 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
789 return false;
790 }
791 break;
792
793 default:
794 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
795 return false;
796 }
797
798 return true;
799}
800
801template <typename ParamType>
802bool ValidateSamplerParameterBase(Context *context,
803 GLuint sampler,
804 GLenum pname,
805 GLsizei bufSize,
806 ParamType *params)
807{
808 if (context->getClientMajorVersion() < 3)
809 {
810 context->handleError(
811 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
812 return false;
813 }
814
815 if (!context->isSampler(sampler))
816 {
817 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
818 return false;
819 }
820
821 const GLsizei minBufSize = 1;
822 if (bufSize >= 0 && bufSize < minBufSize)
823 {
824 context->handleError(
825 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
826 return false;
827 }
828
829 switch (pname)
830 {
831 case GL_TEXTURE_WRAP_S:
832 case GL_TEXTURE_WRAP_T:
833 case GL_TEXTURE_WRAP_R:
834 if (!ValidateTextureWrapModeValue(context, params, false))
835 {
836 return false;
837 }
838 break;
839
840 case GL_TEXTURE_MIN_FILTER:
841 if (!ValidateTextureMinFilterValue(context, params, false))
842 {
843 return false;
844 }
845 break;
846
847 case GL_TEXTURE_MAG_FILTER:
848 if (!ValidateTextureMagFilterValue(context, params))
849 {
850 return false;
851 }
852 break;
853
854 case GL_TEXTURE_MIN_LOD:
855 case GL_TEXTURE_MAX_LOD:
856 // any value is permissible
857 break;
858
859 case GL_TEXTURE_COMPARE_MODE:
860 if (!ValidateTextureCompareModeValue(context, params))
861 {
862 return false;
863 }
864 break;
865
866 case GL_TEXTURE_COMPARE_FUNC:
867 if (!ValidateTextureCompareFuncValue(context, params))
868 {
869 return false;
870 }
871 break;
872
873 default:
874 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
875 return false;
876 }
877
878 return true;
879}
880
881bool ValidateGetSamplerParameterBase(Context *context,
882 GLuint sampler,
883 GLenum pname,
884 GLsizei *length)
885{
886 if (length)
887 {
888 *length = 0;
889 }
890
891 if (context->getClientMajorVersion() < 3)
892 {
893 context->handleError(
894 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
895 return false;
896 }
897
898 if (!context->isSampler(sampler))
899 {
900 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
901 return false;
902 }
903
904 switch (pname)
905 {
906 case GL_TEXTURE_WRAP_S:
907 case GL_TEXTURE_WRAP_T:
908 case GL_TEXTURE_WRAP_R:
909 case GL_TEXTURE_MIN_FILTER:
910 case GL_TEXTURE_MAG_FILTER:
911 case GL_TEXTURE_MIN_LOD:
912 case GL_TEXTURE_MAX_LOD:
913 case GL_TEXTURE_COMPARE_MODE:
914 case GL_TEXTURE_COMPARE_FUNC:
915 break;
916
917 default:
918 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
919 return false;
920 }
921
922 if (length)
923 {
924 *length = 1;
925 }
926 return true;
927}
928
Geoff Lang0b031062016-10-13 14:30:04 -0400929bool ValidateGetVertexAttribBase(Context *context,
930 GLuint index,
931 GLenum pname,
932 GLsizei *length,
933 bool pointer,
934 bool pureIntegerEntryPoint)
935{
936 if (length)
937 {
938 *length = 0;
939 }
940
941 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
942 {
943 context->handleError(
944 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
945 return false;
946 }
947
948 if (index >= context->getCaps().maxVertexAttributes)
949 {
950 context->handleError(Error(
951 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
952 return false;
953 }
954
955 if (pointer)
956 {
957 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
958 {
959 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
960 return false;
961 }
962 }
963 else
964 {
965 switch (pname)
966 {
967 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
968 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
969 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
970 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
971 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
972 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
973 case GL_CURRENT_VERTEX_ATTRIB:
974 break;
975
976 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
977 static_assert(
978 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
979 "ANGLE extension enums not equal to GL enums.");
980 if (context->getClientMajorVersion() < 3 &&
981 !context->getExtensions().instancedArrays)
982 {
983 context->handleError(Error(GL_INVALID_ENUM,
984 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
985 "3.0 or GL_ANGLE_instanced_arrays."));
986 return false;
987 }
988 break;
989
990 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
991 if (context->getClientMajorVersion() < 3)
992 {
993 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
994 return false;
995 }
996 break;
997
998 default:
999 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1000 return false;
1001 }
1002 }
1003
1004 if (length)
1005 {
1006 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1007 {
1008 *length = 4;
1009 }
1010 else
1011 {
1012 *length = 1;
1013 }
1014 }
1015
1016 return true;
1017}
1018
Geoff Langf41a7152016-09-19 15:11:17 -04001019} // anonymous namespace
1020
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001021bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001022{
Jamie Madilld7460c72014-01-21 16:38:14 -05001023 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001024 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001025 case GL_TEXTURE_2D:
1026 case GL_TEXTURE_CUBE_MAP:
1027 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001028
Jamie Madilld7460c72014-01-21 16:38:14 -05001029 case GL_TEXTURE_3D:
1030 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001031 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001032
1033 default:
1034 return false;
1035 }
Jamie Madill35d15012013-10-07 10:46:37 -04001036}
1037
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001038bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1039{
1040 switch (target)
1041 {
1042 case GL_TEXTURE_2D:
1043 case GL_TEXTURE_CUBE_MAP:
1044 return true;
1045
1046 default:
1047 return false;
1048 }
1049}
1050
1051bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1052{
1053 switch (target)
1054 {
1055 case GL_TEXTURE_3D:
1056 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001057 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001058
1059 default:
1060 return false;
1061 }
1062}
1063
Ian Ewellbda75592016-04-18 17:25:54 -04001064// Most texture GL calls are not compatible with external textures, so we have a separate validation
1065// function for use in the GL calls that do
1066bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1067{
1068 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1069 (context->getExtensions().eglImageExternal ||
1070 context->getExtensions().eglStreamConsumerExternal);
1071}
1072
Shannon Woods4dfed832014-03-17 20:03:39 -04001073// This function differs from ValidTextureTarget in that the target must be
1074// usable as the destination of a 2D operation-- so a cube face is valid, but
1075// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001076// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001077bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001078{
1079 switch (target)
1080 {
1081 case GL_TEXTURE_2D:
1082 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1083 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1084 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1085 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1086 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1087 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1088 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001089 default:
1090 return false;
1091 }
1092}
1093
1094bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1095{
1096 switch (target)
1097 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001098 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001099 case GL_TEXTURE_2D_ARRAY:
1100 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001101 default:
1102 return false;
1103 }
1104}
1105
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001106bool ValidFramebufferTarget(GLenum target)
1107{
Geoff Langd4475812015-03-18 10:53:05 -04001108 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1109 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001110
1111 switch (target)
1112 {
1113 case GL_FRAMEBUFFER: return true;
1114 case GL_READ_FRAMEBUFFER: return true;
1115 case GL_DRAW_FRAMEBUFFER: return true;
1116 default: return false;
1117 }
1118}
1119
Jamie Madill29639852016-09-02 15:00:09 -04001120bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001121{
1122 switch (target)
1123 {
1124 case GL_ARRAY_BUFFER:
1125 case GL_ELEMENT_ARRAY_BUFFER:
1126 return true;
1127
Jamie Madill8c96d582014-03-05 15:01:23 -05001128 case GL_PIXEL_PACK_BUFFER:
1129 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001130 return (context->getExtensions().pixelBufferObject ||
1131 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001132
Shannon Woodsb3801742014-03-27 14:59:19 -04001133 case GL_COPY_READ_BUFFER:
1134 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001135 case GL_TRANSFORM_FEEDBACK_BUFFER:
1136 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001137 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001138
1139 default:
1140 return false;
1141 }
1142}
1143
Geoff Langff5b2d52016-09-07 11:32:23 -04001144bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -05001145{
Geoff Langff5b2d52016-09-07 11:32:23 -04001146 // All buffer parameter queries return one value.
1147 *numParams = 1;
1148
Geoff Langcc6f55d2015-03-20 13:01:02 -04001149 const Extensions &extensions = context->getExtensions();
1150
Jamie Madill70656a62014-03-05 15:01:26 -05001151 switch (pname)
1152 {
1153 case GL_BUFFER_USAGE:
1154 case GL_BUFFER_SIZE:
1155 return true;
1156
Geoff Langcc6f55d2015-03-20 13:01:02 -04001157 case GL_BUFFER_ACCESS_OES:
1158 return extensions.mapBuffer;
1159
1160 case GL_BUFFER_MAPPED:
1161 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +03001162 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
1163 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -04001164
Jamie Madill70656a62014-03-05 15:01:26 -05001165 // GL_BUFFER_MAP_POINTER is a special case, and may only be
1166 // queried with GetBufferPointerv
1167 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -05001168 case GL_BUFFER_MAP_OFFSET:
1169 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +03001170 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -05001171
1172 default:
1173 return false;
1174 }
1175}
1176
Jamie Madillc29968b2016-01-20 11:17:23 -05001177bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001178{
Jamie Madillc29968b2016-01-20 11:17:23 -05001179 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001180 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001181 switch (target)
1182 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001183 case GL_TEXTURE_2D:
1184 maxDimension = caps.max2DTextureSize;
1185 break;
Geoff Langce635692013-09-24 13:56:32 -04001186 case GL_TEXTURE_CUBE_MAP:
1187 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1188 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1189 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1190 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1191 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001192 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1193 maxDimension = caps.maxCubeMapTextureSize;
1194 break;
1195 case GL_TEXTURE_3D:
1196 maxDimension = caps.max3DTextureSize;
1197 break;
1198 case GL_TEXTURE_2D_ARRAY:
1199 maxDimension = caps.max2DTextureSize;
1200 break;
Geoff Langce635692013-09-24 13:56:32 -04001201 default: UNREACHABLE();
1202 }
1203
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001204 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001205}
1206
Austin Kinross08528e12015-10-07 16:24:40 -07001207bool ValidImageSizeParameters(const Context *context,
1208 GLenum target,
1209 GLint level,
1210 GLsizei width,
1211 GLsizei height,
1212 GLsizei depth,
1213 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001214{
1215 if (level < 0 || width < 0 || height < 0 || depth < 0)
1216 {
1217 return false;
1218 }
1219
Austin Kinross08528e12015-10-07 16:24:40 -07001220 // TexSubImage parameters can be NPOT without textureNPOT extension,
1221 // as long as the destination texture is POT.
1222 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001223 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001224 {
1225 return false;
1226 }
1227
1228 if (!ValidMipLevel(context, target, level))
1229 {
1230 return false;
1231 }
1232
1233 return true;
1234}
1235
Geoff Lang0d8b7242015-09-09 14:56:53 -04001236bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1237{
1238 // List of compressed format that require that the texture size is smaller than or a multiple of
1239 // the compressed block size.
1240 switch (internalFormat)
1241 {
1242 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1243 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1244 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1245 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001246 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001247 return true;
1248
1249 default:
1250 return false;
1251 }
1252}
1253
Jamie Madillc29968b2016-01-20 11:17:23 -05001254bool ValidCompressedImageSize(const ValidationContext *context,
1255 GLenum internalFormat,
1256 GLsizei width,
1257 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001258{
Geoff Lang5d601382014-07-22 15:14:06 -04001259 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1260 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001261 {
1262 return false;
1263 }
1264
Geoff Lang0d8b7242015-09-09 14:56:53 -04001265 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001266 {
1267 return false;
1268 }
1269
Geoff Lang0d8b7242015-09-09 14:56:53 -04001270 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1271 {
1272 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1273 width % formatInfo.compressedBlockWidth != 0) ||
1274 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1275 height % formatInfo.compressedBlockHeight != 0))
1276 {
1277 return false;
1278 }
1279 }
1280
Geoff Langd4f180b2013-09-24 13:57:44 -04001281 return true;
1282}
1283
Geoff Langff5b2d52016-09-07 11:32:23 -04001284bool ValidImageDataSize(ValidationContext *context,
1285 GLenum textureTarget,
1286 GLsizei width,
1287 GLsizei height,
1288 GLsizei depth,
1289 GLenum internalFormat,
1290 GLenum type,
1291 const GLvoid *pixels,
1292 GLsizei imageSize)
1293{
1294 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1295 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1296 {
1297 // Checks are not required
1298 return true;
1299 }
1300
1301 // ...the data would be unpacked from the buffer object such that the memory reads required
1302 // would exceed the data store size.
1303 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1304 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1305 const gl::Extents size(width, height, depth);
1306 const auto &unpack = context->getGLState().getUnpackState();
1307
1308 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1309 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1310 if (endByteOrErr.isError())
1311 {
1312 context->handleError(endByteOrErr.getError());
1313 return false;
1314 }
1315
1316 GLuint endByte = endByteOrErr.getResult();
1317
1318 if (pixelUnpackBuffer)
1319 {
1320 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1321 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1322 checkedEndByte += checkedOffset;
1323
1324 if (!checkedEndByte.IsValid() ||
1325 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1326 {
1327 // Overflow past the end of the buffer
1328 context->handleError(Error(GL_INVALID_OPERATION));
1329 return false;
1330 }
1331 }
1332 else
1333 {
1334 ASSERT(imageSize >= 0);
1335 if (pixels == nullptr && imageSize != 0)
1336 {
1337 context->handleError(
1338 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1339 }
1340
1341 if (endByte > static_cast<GLuint>(imageSize))
1342 {
1343 context->handleError(
1344 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1345 return false;
1346 }
1347 }
1348
1349 return true;
1350}
1351
Geoff Lang37dde692014-01-31 16:34:54 -05001352bool ValidQueryType(const Context *context, GLenum queryType)
1353{
Geoff Langd4475812015-03-18 10:53:05 -04001354 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1355 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 -05001356
1357 switch (queryType)
1358 {
1359 case GL_ANY_SAMPLES_PASSED:
1360 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1361 return true;
1362 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001363 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001364 case GL_TIME_ELAPSED_EXT:
1365 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001366 case GL_COMMANDS_COMPLETED_CHROMIUM:
1367 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001368 default:
1369 return false;
1370 }
1371}
1372
Jamie Madillef300b12016-10-07 15:12:09 -04001373Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001374{
1375 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1376 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1377 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1378
Dian Xiang769769a2015-09-09 15:20:08 -07001379 Program *validProgram = context->getProgram(id);
1380
1381 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001382 {
Dian Xiang769769a2015-09-09 15:20:08 -07001383 if (context->getShader(id))
1384 {
Jamie Madill437fa652016-05-03 15:13:24 -04001385 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001386 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1387 }
1388 else
1389 {
Jamie Madill437fa652016-05-03 15:13:24 -04001390 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001391 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001392 }
Dian Xiang769769a2015-09-09 15:20:08 -07001393
1394 return validProgram;
1395}
1396
Jamie Madillef300b12016-10-07 15:12:09 -04001397Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001398{
1399 // See ValidProgram for spec details.
1400
1401 Shader *validShader = context->getShader(id);
1402
1403 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001404 {
Dian Xiang769769a2015-09-09 15:20:08 -07001405 if (context->getProgram(id))
1406 {
Jamie Madill437fa652016-05-03 15:13:24 -04001407 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001408 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1409 }
1410 else
1411 {
Jamie Madill437fa652016-05-03 15:13:24 -04001412 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001413 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001414 }
Dian Xiang769769a2015-09-09 15:20:08 -07001415
1416 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001417}
1418
Geoff Langb1196682014-07-23 13:47:29 -04001419bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001420{
1421 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1422 {
1423 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1424
Geoff Langaae65a42014-05-26 12:43:44 -04001425 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001426 {
Jamie Madill437fa652016-05-03 15:13:24 -04001427 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001428 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001429 }
1430 }
1431 else
1432 {
1433 switch (attachment)
1434 {
1435 case GL_DEPTH_ATTACHMENT:
1436 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001437 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001438
1439 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001440 if (!context->getExtensions().webglCompatibility &&
1441 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001442 {
1443 context->handleError(Error(GL_INVALID_ENUM));
1444 return false;
1445 }
1446 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001447
1448 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001449 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001450 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001451 }
1452 }
1453
1454 return true;
1455}
1456
Corentin Walleze0902642014-11-04 12:32:15 -08001457bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1458 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459{
1460 switch (target)
1461 {
1462 case GL_RENDERBUFFER:
1463 break;
1464 default:
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 if (width < 0 || height < 0 || samples < 0)
1470 {
Jamie Madill437fa652016-05-03 15:13:24 -04001471 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001472 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 }
1474
Geoff Langd87878e2014-09-19 15:42:59 -04001475 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1476 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001479 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 }
1481
1482 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1483 // 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 -08001484 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001485 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001486 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001487 {
Jamie Madill437fa652016-05-03 15:13:24 -04001488 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001489 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001490 }
1491
Geoff Langaae65a42014-05-26 12:43:44 -04001492 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001493 {
Jamie Madill437fa652016-05-03 15:13:24 -04001494 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001495 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001496 }
1497
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001498 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 if (handle == 0)
1500 {
Jamie Madill437fa652016-05-03 15:13:24 -04001501 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001502 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001503 }
1504
1505 return true;
1506}
1507
Corentin Walleze0902642014-11-04 12:32:15 -08001508bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1509 GLenum internalformat, GLsizei width, GLsizei height)
1510{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001511 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001512
1513 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001514 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001515 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001516 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001517 {
Jamie Madill437fa652016-05-03 15:13:24 -04001518 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001519 return false;
1520 }
1521
1522 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1523 // the specified storage. This is different than ES 3.0 in which a sample number higher
1524 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001525 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001526 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001527 {
Geoff Langa4903b72015-03-02 16:02:48 -08001528 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1529 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001532 return false;
1533 }
Corentin Walleze0902642014-11-04 12:32:15 -08001534 }
1535
1536 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1537}
1538
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001539bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1540 GLenum renderbuffertarget, GLuint renderbuffer)
1541{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001542 if (!ValidFramebufferTarget(target))
1543 {
Jamie Madill437fa652016-05-03 15:13:24 -04001544 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001545 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001546 }
1547
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001548 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001549
Jamie Madill84115c92015-04-23 15:00:07 -04001550 ASSERT(framebuffer);
1551 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001552 {
Jamie Madill437fa652016-05-03 15:13:24 -04001553 context->handleError(
1554 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001555 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556 }
1557
Jamie Madillb4472272014-07-03 10:38:55 -04001558 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001559 {
Jamie Madillb4472272014-07-03 10:38:55 -04001560 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001561 }
1562
Jamie Madillab9d82c2014-01-21 16:38:14 -05001563 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1564 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1565 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1566 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1567 if (renderbuffer != 0)
1568 {
1569 if (!context->getRenderbuffer(renderbuffer))
1570 {
Jamie Madill437fa652016-05-03 15:13:24 -04001571 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001572 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001573 }
1574 }
1575
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001576 return true;
1577}
1578
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001579bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001580 GLint srcX0,
1581 GLint srcY0,
1582 GLint srcX1,
1583 GLint srcY1,
1584 GLint dstX0,
1585 GLint dstY0,
1586 GLint dstX1,
1587 GLint dstY1,
1588 GLbitfield mask,
1589 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001590{
1591 switch (filter)
1592 {
1593 case GL_NEAREST:
1594 break;
1595 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596 break;
1597 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001598 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001599 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001600 }
1601
1602 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1603 {
Jamie Madill437fa652016-05-03 15:13:24 -04001604 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
1608 if (mask == 0)
1609 {
1610 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1611 // buffers are copied.
1612 return false;
1613 }
1614
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001615 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1616 // color buffer, leaving only nearest being unfiltered from above
1617 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1618 {
Jamie Madill437fa652016-05-03 15:13:24 -04001619 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 }
1622
Jamie Madill51f40ec2016-06-15 14:06:00 -04001623 const auto &glState = context->getGLState();
1624 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1625 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001626
1627 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001628 {
Jamie Madill437fa652016-05-03 15:13:24 -04001629 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001630 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001631 }
1632
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001633 if (readFramebuffer->id() == drawFramebuffer->id())
1634 {
1635 context->handleError(Error(GL_INVALID_OPERATION));
1636 return false;
1637 }
1638
Jamie Madill51f40ec2016-06-15 14:06:00 -04001639 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001640 {
Jamie Madill437fa652016-05-03 15:13:24 -04001641 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001642 return false;
1643 }
1644
Jamie Madill51f40ec2016-06-15 14:06:00 -04001645 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001648 return false;
1649 }
1650
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001651 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001652 {
Jamie Madill437fa652016-05-03 15:13:24 -04001653 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001655 }
1656
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001657 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1658
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 if (mask & GL_COLOR_BUFFER_BIT)
1660 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001661 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1662 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001663 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001664
1665 if (readColorBuffer && drawColorBuffer)
1666 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001667 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001668
Geoff Langa15472a2015-08-11 11:48:03 -04001669 for (size_t drawbufferIdx = 0;
1670 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 {
Geoff Langa15472a2015-08-11 11:48:03 -04001672 const FramebufferAttachment *attachment =
1673 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1674 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001675 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001676 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001677
Geoff Langb2f3d052013-08-13 12:49:27 -04001678 // The GL ES 3.0.2 spec (pg 193) states that:
1679 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1680 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1681 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001682 // Changes with EXT_color_buffer_float:
1683 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001684 GLenum readComponentType = readFormat.info->componentType;
1685 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001686 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1687 readComponentType == GL_SIGNED_NORMALIZED);
1688 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1689 drawComponentType == GL_SIGNED_NORMALIZED);
1690
1691 if (extensions.colorBufferFloat)
1692 {
1693 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1694 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1695
1696 if (readFixedOrFloat != drawFixedOrFloat)
1697 {
Jamie Madill437fa652016-05-03 15:13:24 -04001698 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001699 "If the read buffer contains fixed-point or "
1700 "floating-point values, the draw buffer "
1701 "must as well."));
1702 return false;
1703 }
1704 }
1705 else if (readFixedPoint != drawFixedPoint)
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001708 "If the read buffer contains fixed-point "
1709 "values, the draw buffer must as well."));
1710 return false;
1711 }
1712
1713 if (readComponentType == GL_UNSIGNED_INT &&
1714 drawComponentType != GL_UNSIGNED_INT)
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
Jamie Madill6163c752015-12-07 16:32:59 -05001720 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001721 {
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001723 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724 }
1725
Jamie Madilla3944d42016-07-22 22:13:26 -04001726 if (readColorBuffer->getSamples() > 0 &&
1727 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 {
Jamie Madill437fa652016-05-03 15:13:24 -04001729 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 }
1732 }
1733 }
1734
Jamie Madilla3944d42016-07-22 22:13:26 -04001735 if ((readFormat.info->componentType == GL_INT ||
1736 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1737 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001738 {
Jamie Madill437fa652016-05-03 15:13:24 -04001739 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001740 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001741 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001742 }
1743 }
1744
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001745 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1746 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1747 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001749 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001751 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1752 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001754 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001755 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001756 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001761
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001762 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001763 {
Jamie Madill437fa652016-05-03 15:13:24 -04001764 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001765 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001766 }
1767 }
1768 }
1769 }
1770
1771 return true;
1772}
1773
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001774bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001775 GLint x,
1776 GLint y,
1777 GLsizei width,
1778 GLsizei height,
1779 GLenum format,
1780 GLenum type,
1781 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001782{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001783 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1784}
1785
1786bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1787 GLint x,
1788 GLint y,
1789 GLsizei width,
1790 GLsizei height,
1791 GLenum format,
1792 GLenum type,
1793 GLsizei bufSize,
1794 GLsizei *length,
1795 GLvoid *pixels)
1796{
1797 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001799 return false;
1800 }
1801
Geoff Lang62fce5b2016-09-30 10:46:35 -04001802 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1803 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001804 {
Geoff Langb1196682014-07-23 13:47:29 -04001805 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001806 }
1807
Geoff Lang62fce5b2016-09-30 10:46:35 -04001808 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001809 {
Geoff Langb1196682014-07-23 13:47:29 -04001810 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001811 }
1812
Jamie Madillc29968b2016-01-20 11:17:23 -05001813 return true;
1814}
1815
1816bool ValidateReadnPixelsEXT(Context *context,
1817 GLint x,
1818 GLint y,
1819 GLsizei width,
1820 GLsizei height,
1821 GLenum format,
1822 GLenum type,
1823 GLsizei bufSize,
1824 GLvoid *pixels)
1825{
1826 if (bufSize < 0)
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001829 return false;
1830 }
1831
Geoff Lang62fce5b2016-09-30 10:46:35 -04001832 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1833 pixels);
1834}
Jamie Madill26e91952014-03-05 15:01:27 -05001835
Geoff Lang62fce5b2016-09-30 10:46:35 -04001836bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1837 GLint x,
1838 GLint y,
1839 GLsizei width,
1840 GLsizei height,
1841 GLenum format,
1842 GLenum type,
1843 GLsizei bufSize,
1844 GLsizei *length,
1845 GLvoid *data)
1846{
1847 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001848 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001849 return false;
1850 }
1851
Geoff Lang62fce5b2016-09-30 10:46:35 -04001852 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001853 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001854 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001855 }
1856
Geoff Lang62fce5b2016-09-30 10:46:35 -04001857 if (!ValidateRobustBufferSize(context, bufSize, *length))
1858 {
1859 return false;
1860 }
1861
1862 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001863}
1864
Olli Etuaho41997e72016-03-10 13:38:39 +02001865bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001866{
1867 if (!context->getExtensions().occlusionQueryBoolean &&
1868 !context->getExtensions().disjointTimerQuery)
1869 {
Jamie Madill437fa652016-05-03 15:13:24 -04001870 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871 return false;
1872 }
1873
Olli Etuaho41997e72016-03-10 13:38:39 +02001874 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001875}
1876
Olli Etuaho41997e72016-03-10 13:38:39 +02001877bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001878{
1879 if (!context->getExtensions().occlusionQueryBoolean &&
1880 !context->getExtensions().disjointTimerQuery)
1881 {
Jamie Madill437fa652016-05-03 15:13:24 -04001882 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001883 return false;
1884 }
1885
Olli Etuaho41997e72016-03-10 13:38:39 +02001886 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001887}
1888
1889bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001890{
1891 if (!ValidQueryType(context, target))
1892 {
Jamie Madill437fa652016-05-03 15:13:24 -04001893 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001894 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001895 }
1896
1897 if (id == 0)
1898 {
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001900 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001901 }
1902
1903 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1904 // of zero, if the active query object name for <target> is non-zero (for the
1905 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1906 // the active query for either target is non-zero), if <id> is the name of an
1907 // existing query object whose type does not match <target>, or if <id> is the
1908 // active query object name for any query type, the error INVALID_OPERATION is
1909 // generated.
1910
1911 // Ensure no other queries are active
1912 // NOTE: If other queries than occlusion are supported, we will need to check
1913 // separately that:
1914 // a) The query ID passed is not the current active query for any target/type
1915 // b) There are no active queries for the requested target (and in the case
1916 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1917 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001919 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001920 {
Jamie Madill437fa652016-05-03 15:13:24 -04001921 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001922 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001923 }
1924
1925 Query *queryObject = context->getQuery(id, true, target);
1926
1927 // check that name was obtained with glGenQueries
1928 if (!queryObject)
1929 {
Jamie Madill437fa652016-05-03 15:13:24 -04001930 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001931 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001932 }
1933
1934 // check for type mismatch
1935 if (queryObject->getType() != target)
1936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001938 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001939 }
1940
1941 return true;
1942}
1943
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001944bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1945{
1946 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001947 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001950 return false;
1951 }
1952
1953 return ValidateBeginQueryBase(context, target, id);
1954}
1955
1956bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001957{
1958 if (!ValidQueryType(context, target))
1959 {
Jamie Madill437fa652016-05-03 15:13:24 -04001960 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001961 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001962 }
1963
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001964 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001965
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001967 {
Jamie Madill437fa652016-05-03 15:13:24 -04001968 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001969 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001970 }
1971
Jamie Madill45c785d2014-05-13 14:09:34 -04001972 return true;
1973}
1974
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001975bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1976{
1977 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001978 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979 {
Jamie Madill437fa652016-05-03 15:13:24 -04001980 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001981 return false;
1982 }
1983
1984 return ValidateEndQueryBase(context, target);
1985}
1986
1987bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1988{
1989 if (!context->getExtensions().disjointTimerQuery)
1990 {
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001992 return false;
1993 }
1994
1995 if (target != GL_TIMESTAMP_EXT)
1996 {
Jamie Madill437fa652016-05-03 15:13:24 -04001997 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998 return false;
1999 }
2000
2001 Query *queryObject = context->getQuery(id, true, target);
2002 if (queryObject == nullptr)
2003 {
Jamie Madill437fa652016-05-03 15:13:24 -04002004 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005 return false;
2006 }
2007
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002008 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009 {
Jamie Madill437fa652016-05-03 15:13:24 -04002010 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002011 return false;
2012 }
2013
2014 return true;
2015}
2016
2017bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
2018{
2019 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002022 return false;
2023 }
2024
2025 switch (pname)
2026 {
2027 case GL_CURRENT_QUERY_EXT:
2028 if (target == GL_TIMESTAMP_EXT)
2029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002031 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2032 return false;
2033 }
2034 break;
2035 case GL_QUERY_COUNTER_BITS_EXT:
2036 if (!context->getExtensions().disjointTimerQuery ||
2037 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2038 {
Jamie Madill437fa652016-05-03 15:13:24 -04002039 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002040 return false;
2041 }
2042 break;
2043 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002044 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045 return false;
2046 }
2047
2048 return true;
2049}
2050
2051bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2052{
2053 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002054 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
2059
2060 return ValidateGetQueryivBase(context, target, pname);
2061}
2062
2063bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
2064{
2065 Query *queryObject = context->getQuery(id, false, GL_NONE);
2066
2067 if (!queryObject)
2068 {
Jamie Madill437fa652016-05-03 15:13:24 -04002069 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002070 return false;
2071 }
2072
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002073 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002074 {
Jamie Madill437fa652016-05-03 15:13:24 -04002075 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002076 return false;
2077 }
2078
2079 switch (pname)
2080 {
2081 case GL_QUERY_RESULT_EXT:
2082 case GL_QUERY_RESULT_AVAILABLE_EXT:
2083 break;
2084
2085 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002086 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002087 return false;
2088 }
2089
2090 return true;
2091}
2092
2093bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2094{
2095 if (!context->getExtensions().disjointTimerQuery)
2096 {
Jamie Madill437fa652016-05-03 15:13:24 -04002097 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002098 return false;
2099 }
2100 return ValidateGetQueryObjectValueBase(context, id, pname);
2101}
2102
2103bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2104{
2105 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002106 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002107 {
Jamie Madill437fa652016-05-03 15:13:24 -04002108 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002109 return false;
2110 }
2111 return ValidateGetQueryObjectValueBase(context, id, pname);
2112}
2113
2114bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2115{
2116 if (!context->getExtensions().disjointTimerQuery)
2117 {
Jamie Madill437fa652016-05-03 15:13:24 -04002118 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119 return false;
2120 }
2121 return ValidateGetQueryObjectValueBase(context, id, pname);
2122}
2123
2124bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2125{
2126 if (!context->getExtensions().disjointTimerQuery)
2127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002129 return false;
2130 }
2131 return ValidateGetQueryObjectValueBase(context, id, pname);
2132}
2133
Jamie Madill62d31cb2015-09-11 13:25:51 -04002134static bool ValidateUniformCommonBase(gl::Context *context,
2135 GLenum targetUniformType,
2136 GLint location,
2137 GLsizei count,
2138 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002139{
2140 if (count < 0)
2141 {
Jamie Madill437fa652016-05-03 15:13:24 -04002142 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002143 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002144 }
2145
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002146 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002147 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002148 {
Jamie Madill437fa652016-05-03 15:13:24 -04002149 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002150 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002151 }
2152
Geoff Langd8605522016-04-13 10:19:12 -04002153 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002154 {
2155 // Silently ignore the uniform command
2156 return false;
2157 }
2158
Geoff Lang7dd2e102014-11-10 15:19:26 -05002159 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002160 {
Jamie Madill437fa652016-05-03 15:13:24 -04002161 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002162 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002163 }
2164
Jamie Madill62d31cb2015-09-11 13:25:51 -04002165 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002166
2167 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002168 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002169 {
Jamie Madill437fa652016-05-03 15:13:24 -04002170 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002171 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002172 }
2173
Jamie Madill62d31cb2015-09-11 13:25:51 -04002174 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002175 return true;
2176}
2177
Jamie Madillaa981bd2014-05-20 10:55:55 -04002178bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2179{
2180 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002181 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2182 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002183 {
Jamie Madill437fa652016-05-03 15:13:24 -04002184 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002185 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186 }
2187
Jamie Madill62d31cb2015-09-11 13:25:51 -04002188 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002189 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2190 {
2191 return false;
2192 }
2193
Jamie Madillf2575982014-06-25 16:04:54 -04002194 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002195 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002196 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002199 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002200 }
2201
2202 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002203}
2204
2205bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2206 GLboolean transpose)
2207{
2208 // Check for ES3 uniform entry points
2209 int rows = VariableRowCount(matrixType);
2210 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002211 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002212 {
Jamie Madill437fa652016-05-03 15:13:24 -04002213 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002214 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002215 }
2216
Martin Radev1be913c2016-07-11 17:59:16 +03002217 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002220 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002221 }
2222
Jamie Madill62d31cb2015-09-11 13:25:51 -04002223 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002224 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2225 {
2226 return false;
2227 }
2228
2229 if (uniform->type != matrixType)
2230 {
Jamie Madill437fa652016-05-03 15:13:24 -04002231 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002232 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002233 }
2234
2235 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002236}
2237
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002238bool ValidateStateQuery(ValidationContext *context,
2239 GLenum pname,
2240 GLenum *nativeType,
2241 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002242{
2243 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2244 {
Jamie Madill437fa652016-05-03 15:13:24 -04002245 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002246 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002247 }
2248
Jamie Madill0af26e12015-03-05 19:54:33 -05002249 const Caps &caps = context->getCaps();
2250
Jamie Madill893ab082014-05-16 16:56:10 -04002251 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2252 {
2253 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2254
Jamie Madill0af26e12015-03-05 19:54:33 -05002255 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002256 {
Jamie Madill437fa652016-05-03 15:13:24 -04002257 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002258 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002259 }
2260 }
2261
2262 switch (pname)
2263 {
2264 case GL_TEXTURE_BINDING_2D:
2265 case GL_TEXTURE_BINDING_CUBE_MAP:
2266 case GL_TEXTURE_BINDING_3D:
2267 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002268 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002269 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002270 if (!context->getExtensions().eglStreamConsumerExternal &&
2271 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002272 {
John Bauman18319182016-09-28 14:22:27 -07002273 context->handleError(Error(GL_INVALID_ENUM,
2274 "Neither NV_EGL_stream_consumer_external nor "
2275 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002276 return false;
2277 }
2278 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002279
2280 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2281 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2282 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002283 if (context->getGLState().getReadFramebuffer()->checkStatus(
2284 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002285 {
Jamie Madill437fa652016-05-03 15:13:24 -04002286 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002287 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002288 }
2289
Jamie Madill51f40ec2016-06-15 14:06:00 -04002290 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2291 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002292
2293 if (framebuffer->getReadBufferState() == GL_NONE)
2294 {
2295 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2296 return false;
2297 }
2298
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002299 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002300 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002301 {
Jamie Madill437fa652016-05-03 15:13:24 -04002302 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002303 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002304 }
2305 }
2306 break;
2307
2308 default:
2309 break;
2310 }
2311
2312 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002313 if (*numParams == 0)
2314 {
2315 return false;
2316 }
2317
2318 return true;
2319}
2320
2321bool ValidateRobustStateQuery(ValidationContext *context,
2322 GLenum pname,
2323 GLsizei bufSize,
2324 GLenum *nativeType,
2325 unsigned int *numParams)
2326{
2327 if (!ValidateRobustEntryPoint(context, bufSize))
2328 {
2329 return false;
2330 }
2331
2332 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2333 {
2334 return false;
2335 }
2336
2337 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002338 {
2339 return false;
2340 }
2341
2342 return true;
2343}
2344
Jamie Madillc29968b2016-01-20 11:17:23 -05002345bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2346 GLenum target,
2347 GLint level,
2348 GLenum internalformat,
2349 bool isSubImage,
2350 GLint xoffset,
2351 GLint yoffset,
2352 GLint zoffset,
2353 GLint x,
2354 GLint y,
2355 GLsizei width,
2356 GLsizei height,
2357 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002358 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002359{
Jamie Madill560a8d82014-05-21 13:06:20 -04002360 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2361 {
Jamie Madill437fa652016-05-03 15:13:24 -04002362 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002363 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002364 }
2365
2366 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2367 {
Jamie Madill437fa652016-05-03 15:13:24 -04002368 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002369 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002370 }
2371
2372 if (border != 0)
2373 {
Jamie Madill437fa652016-05-03 15:13:24 -04002374 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002375 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002376 }
2377
2378 if (!ValidMipLevel(context, target, level))
2379 {
Jamie Madill437fa652016-05-03 15:13:24 -04002380 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002381 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002382 }
2383
Jamie Madill51f40ec2016-06-15 14:06:00 -04002384 const auto &state = context->getGLState();
2385 auto readFramebuffer = state.getReadFramebuffer();
2386 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002387 {
Jamie Madill437fa652016-05-03 15:13:24 -04002388 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002389 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002390 }
2391
Jamie Madill51f40ec2016-06-15 14:06:00 -04002392 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 {
Jamie Madill437fa652016-05-03 15:13:24 -04002394 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002395 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002396 }
2397
Martin Radev138064f2016-07-15 12:03:41 +03002398 if (readFramebuffer->getReadBufferState() == GL_NONE)
2399 {
2400 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2401 return false;
2402 }
2403
Geoff Langaae65a42014-05-26 12:43:44 -04002404 const gl::Caps &caps = context->getCaps();
2405
Geoff Langaae65a42014-05-26 12:43:44 -04002406 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 switch (target)
2408 {
2409 case GL_TEXTURE_2D:
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_CUBE_MAP_POSITIVE_X:
2414 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2415 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2416 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2417 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2418 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002419 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420 break;
2421
2422 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002423 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 break;
2425
2426 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002427 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 break;
2429
2430 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002431 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002433 }
2434
Jamie Madillc29968b2016-01-20 11:17:23 -05002435 gl::Texture *texture =
2436 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 if (!texture)
2438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 }
2442
Geoff Lang69cce582015-09-17 13:20:36 -04002443 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002444 {
Jamie Madill437fa652016-05-03 15:13:24 -04002445 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 }
2448
Geoff Lang5d601382014-07-22 15:14:06 -04002449 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2450
2451 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 {
Jamie Madill437fa652016-05-03 15:13:24 -04002453 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 }
2456
Geoff Langa9be0dc2014-12-17 12:34:40 -05002457 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 {
Jamie Madill437fa652016-05-03 15:13:24 -04002459 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002460 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002461 }
2462
2463 if (isSubImage)
2464 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002465 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2466 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2467 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002468 {
Jamie Madill437fa652016-05-03 15:13:24 -04002469 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002470 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002471 }
2472 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002473 else
2474 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002475 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002476 {
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
Martin Radev1be913c2016-07-11 17:59:16 +03002481 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002482 {
Jamie Madill437fa652016-05-03 15:13:24 -04002483 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002484 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002485 }
2486
2487 int maxLevelDimension = (maxDimension >> level);
2488 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2489 {
Jamie Madill437fa652016-05-03 15:13:24 -04002490 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002491 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002492 }
2493 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002494
Jamie Madill0c8abca2016-07-22 20:21:26 -04002495 if (textureFormatOut)
2496 {
2497 *textureFormatOut = texture->getFormat(target, level);
2498 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002499 return true;
2500}
2501
Jamie Madillf25855c2015-11-03 11:06:18 -05002502static bool ValidateDrawBase(ValidationContext *context,
2503 GLenum mode,
2504 GLsizei count,
2505 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002506{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002507 switch (mode)
2508 {
2509 case GL_POINTS:
2510 case GL_LINES:
2511 case GL_LINE_LOOP:
2512 case GL_LINE_STRIP:
2513 case GL_TRIANGLES:
2514 case GL_TRIANGLE_STRIP:
2515 case GL_TRIANGLE_FAN:
2516 break;
2517 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002518 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002519 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002520 }
2521
Jamie Madill250d33f2014-06-06 17:09:03 -04002522 if (count < 0)
2523 {
Jamie Madill437fa652016-05-03 15:13:24 -04002524 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002526 }
2527
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002528 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002529
Jamie Madill250d33f2014-06-06 17:09:03 -04002530 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002531 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002532 {
Jamie Madill437fa652016-05-03 15:13:24 -04002533 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002534 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002535 }
2536
Jamie Madill51f40ec2016-06-15 14:06:00 -04002537 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002538 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002539 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002540 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2541 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2542 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2543 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2544 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2545 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002546 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002547 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2548 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002549 {
2550 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2551 // Section 6.10 of the WebGL 1.0 spec
2552 ERR(
2553 "This ANGLE implementation does not support separate front/back stencil "
2554 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002555 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002556 return false;
2557 }
Jamie Madillac528012014-06-20 13:21:23 -04002558 }
2559
Jamie Madill51f40ec2016-06-15 14:06:00 -04002560 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002561 {
Jamie Madill437fa652016-05-03 15:13:24 -04002562 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002563 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002564 }
2565
Geoff Lang7dd2e102014-11-10 15:19:26 -05002566 gl::Program *program = state.getProgram();
2567 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002568 {
Jamie Madill437fa652016-05-03 15:13:24 -04002569 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002570 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002571 }
2572
Geoff Lang7dd2e102014-11-10 15:19:26 -05002573 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002574 {
Jamie Madill437fa652016-05-03 15:13:24 -04002575 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002576 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002577 }
2578
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002579 // Uniform buffer validation
2580 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2581 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002582 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002583 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002584 const OffsetBindingPointer<Buffer> &uniformBuffer =
2585 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002586
Geoff Lang5d124a62015-09-15 13:03:27 -04002587 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002588 {
2589 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002590 context->handleError(
2591 Error(GL_INVALID_OPERATION,
2592 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002593 return false;
2594 }
2595
Geoff Lang5d124a62015-09-15 13:03:27 -04002596 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002597 if (uniformBufferSize == 0)
2598 {
2599 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002600 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002601 }
2602
Jamie Madill62d31cb2015-09-11 13:25:51 -04002603 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002604 {
2605 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002606 context->handleError(
2607 Error(GL_INVALID_OPERATION,
2608 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002609 return false;
2610 }
2611 }
2612
Jamie Madill250d33f2014-06-06 17:09:03 -04002613 // No-op if zero count
2614 return (count > 0);
2615}
2616
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002617bool ValidateDrawArrays(ValidationContext *context,
2618 GLenum mode,
2619 GLint first,
2620 GLsizei count,
2621 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002622{
Jamie Madillfd716582014-06-06 17:09:04 -04002623 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002624 {
Jamie Madill437fa652016-05-03 15:13:24 -04002625 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002626 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002627 }
2628
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002629 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002630 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002631 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2632 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002633 {
2634 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2635 // that does not match the current transform feedback object's draw mode (if transform feedback
2636 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002638 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002639 }
2640
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002641 if (!ValidateDrawBase(context, mode, count, primcount))
2642 {
2643 return false;
2644 }
2645
2646 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002647 {
2648 return false;
2649 }
2650
2651 return true;
2652}
2653
Geoff Langb1196682014-07-23 13:47:29 -04002654bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002655{
2656 if (primcount < 0)
2657 {
Jamie Madill437fa652016-05-03 15:13:24 -04002658 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002659 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002660 }
2661
Jamie Madill2b976812014-08-25 15:47:49 -04002662 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002663 {
2664 return false;
2665 }
2666
2667 // No-op if zero primitive count
2668 return (primcount > 0);
2669}
2670
Geoff Lang87a93302014-09-16 13:29:43 -04002671static bool ValidateDrawInstancedANGLE(Context *context)
2672{
2673 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002674 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002675
Geoff Lang7dd2e102014-11-10 15:19:26 -05002676 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002677
2678 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002679 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002680 {
2681 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002682 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002683 {
2684 return true;
2685 }
2686 }
2687
Jamie Madill437fa652016-05-03 15:13:24 -04002688 context->handleError(Error(GL_INVALID_OPERATION,
2689 "ANGLE_instanced_arrays requires that at least one active attribute"
2690 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002691 return false;
2692}
2693
2694bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2695{
2696 if (!ValidateDrawInstancedANGLE(context))
2697 {
2698 return false;
2699 }
2700
2701 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2702}
2703
Jamie Madillf25855c2015-11-03 11:06:18 -05002704bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002705 GLenum mode,
2706 GLsizei count,
2707 GLenum type,
2708 const GLvoid *indices,
2709 GLsizei primcount,
2710 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002711{
Jamie Madill250d33f2014-06-06 17:09:03 -04002712 switch (type)
2713 {
2714 case GL_UNSIGNED_BYTE:
2715 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002716 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002717 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002718 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2719 {
2720 context->handleError(Error(GL_INVALID_ENUM));
2721 return false;
2722 }
2723 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002724 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002725 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002726 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002727 }
2728
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002729 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002730
2731 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002732 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002733 {
2734 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2735 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002736 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002737 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002738 }
2739
2740 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002741 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002742 {
Jamie Madill437fa652016-05-03 15:13:24 -04002743 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002744 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002745 }
2746
Jamie Madill2b976812014-08-25 15:47:49 -04002747 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002748 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002749 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002750 {
Jamie Madill437fa652016-05-03 15:13:24 -04002751 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002753 }
2754
Jamie Madillae3000b2014-08-25 15:47:51 -04002755 if (elementArrayBuffer)
2756 {
2757 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2758
2759 GLint64 offset = reinterpret_cast<GLint64>(indices);
2760 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2761
2762 // check for integer overflows
2763 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2764 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2765 {
Jamie Madill437fa652016-05-03 15:13:24 -04002766 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002767 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002768 }
2769
2770 // Check for reading past the end of the bound buffer object
2771 if (byteCount > elementArrayBuffer->getSize())
2772 {
Jamie Madill437fa652016-05-03 15:13:24 -04002773 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002774 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002775 }
2776 }
2777 else if (!indices)
2778 {
2779 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002780 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002781 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002782 }
2783
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002784 if (!ValidateDrawBase(context, mode, count, primcount))
2785 {
2786 return false;
2787 }
2788
Jamie Madill2b976812014-08-25 15:47:49 -04002789 // Use max index to validate if our vertex buffers are large enough for the pull.
2790 // TODO: offer fast path, with disabled index validation.
2791 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2792 if (elementArrayBuffer)
2793 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002794 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002795 Error error =
2796 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2797 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002798 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002799 {
Jamie Madill437fa652016-05-03 15:13:24 -04002800 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002801 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002802 }
2803 }
2804 else
2805 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002806 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002807 }
2808
Jamie Madille79b1e12015-11-04 16:36:37 -05002809 // If we use an index greater than our maximum supported index range, return an error.
2810 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2811 // return an error if possible here.
2812 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2813 {
Jamie Madill437fa652016-05-03 15:13:24 -04002814 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002815 return false;
2816 }
2817
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002818 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002819 {
2820 return false;
2821 }
2822
Geoff Lang3edfe032015-09-04 16:38:24 -04002823 // No op if there are no real indices in the index data (all are primitive restart).
2824 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002825}
2826
Geoff Langb1196682014-07-23 13:47:29 -04002827bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002828 GLenum mode,
2829 GLsizei count,
2830 GLenum type,
2831 const GLvoid *indices,
2832 GLsizei primcount,
2833 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002834{
2835 if (primcount < 0)
2836 {
Jamie Madill437fa652016-05-03 15:13:24 -04002837 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002838 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002839 }
2840
Jamie Madill2b976812014-08-25 15:47:49 -04002841 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002842 {
2843 return false;
2844 }
2845
2846 // No-op zero primitive count
2847 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002848}
2849
Geoff Lang3edfe032015-09-04 16:38:24 -04002850bool ValidateDrawElementsInstancedANGLE(Context *context,
2851 GLenum mode,
2852 GLsizei count,
2853 GLenum type,
2854 const GLvoid *indices,
2855 GLsizei primcount,
2856 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002857{
2858 if (!ValidateDrawInstancedANGLE(context))
2859 {
2860 return false;
2861 }
2862
2863 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2864}
2865
Geoff Langb1196682014-07-23 13:47:29 -04002866bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002867 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002868{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002869 if (!ValidFramebufferTarget(target))
2870 {
Jamie Madill437fa652016-05-03 15:13:24 -04002871 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002872 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002873 }
2874
2875 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002876 {
2877 return false;
2878 }
2879
Jamie Madill55ec3b12014-07-03 10:38:57 -04002880 if (texture != 0)
2881 {
2882 gl::Texture *tex = context->getTexture(texture);
2883
2884 if (tex == NULL)
2885 {
Jamie Madill437fa652016-05-03 15:13:24 -04002886 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002887 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002888 }
2889
2890 if (level < 0)
2891 {
Jamie Madill437fa652016-05-03 15:13:24 -04002892 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002893 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002894 }
2895 }
2896
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002897 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002898 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002899
Jamie Madill84115c92015-04-23 15:00:07 -04002900 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002901 {
Jamie Madill437fa652016-05-03 15:13:24 -04002902 context->handleError(
2903 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002904 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002905 }
2906
2907 return true;
2908}
2909
Geoff Langb1196682014-07-23 13:47:29 -04002910bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002911 GLenum textarget, GLuint texture, GLint level)
2912{
Geoff Lang95663912015-04-02 15:54:45 -04002913 // 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 +03002914 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2915 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002916 {
Jamie Madill437fa652016-05-03 15:13:24 -04002917 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002918 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002919 }
2920
2921 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002922 {
2923 return false;
2924 }
2925
Jamie Madill55ec3b12014-07-03 10:38:57 -04002926 if (texture != 0)
2927 {
2928 gl::Texture *tex = context->getTexture(texture);
2929 ASSERT(tex);
2930
Jamie Madill2a6564e2014-07-11 09:53:19 -04002931 const gl::Caps &caps = context->getCaps();
2932
Jamie Madill55ec3b12014-07-03 10:38:57 -04002933 switch (textarget)
2934 {
2935 case GL_TEXTURE_2D:
2936 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002937 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002938 {
Jamie Madill437fa652016-05-03 15:13:24 -04002939 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002940 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002941 }
2942 if (tex->getTarget() != GL_TEXTURE_2D)
2943 {
Jamie Madill437fa652016-05-03 15:13:24 -04002944 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002945 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002946 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002947 }
2948 break;
2949
2950 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2951 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2952 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2953 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2954 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2955 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2956 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002957 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002958 {
Jamie Madill437fa652016-05-03 15:13:24 -04002959 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002960 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002961 }
2962 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2963 {
Jamie Madill437fa652016-05-03 15:13:24 -04002964 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002965 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002966 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002967 }
2968 break;
2969
2970 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002971 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002972 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002973 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002974
Jamie Madilla3944d42016-07-22 22:13:26 -04002975 const Format &format = tex->getFormat(textarget, level);
2976 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002977 {
Jamie Madill437fa652016-05-03 15:13:24 -04002978 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002979 return false;
2980 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002981 }
2982
Jamie Madill570f7c82014-07-03 10:38:54 -04002983 return true;
2984}
2985
Geoff Langb1196682014-07-23 13:47:29 -04002986bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002987{
2988 if (program == 0)
2989 {
Jamie Madill437fa652016-05-03 15:13:24 -04002990 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002992 }
2993
Dian Xiang769769a2015-09-09 15:20:08 -07002994 gl::Program *programObject = GetValidProgram(context, program);
2995 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002996 {
2997 return false;
2998 }
2999
Jamie Madill0063c512014-08-25 15:47:53 -04003000 if (!programObject || !programObject->isLinked())
3001 {
Jamie Madill437fa652016-05-03 15:13:24 -04003002 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003004 }
3005
Geoff Lang7dd2e102014-11-10 15:19:26 -05003006 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003007 {
Jamie Madill437fa652016-05-03 15:13:24 -04003008 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003009 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003010 }
3011
Jamie Madill0063c512014-08-25 15:47:53 -04003012 return true;
3013}
3014
Geoff Langb1196682014-07-23 13:47:29 -04003015bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003016{
3017 return ValidateGetUniformBase(context, program, location);
3018}
3019
Geoff Langb1196682014-07-23 13:47:29 -04003020bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003021{
Jamie Madill78f41802014-08-25 15:47:55 -04003022 return ValidateGetUniformBase(context, program, location);
3023}
3024
Geoff Langf41d0ee2016-10-07 13:04:23 -04003025static bool ValidateSizedGetUniform(Context *context,
3026 GLuint program,
3027 GLint location,
3028 GLsizei bufSize,
3029 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003030{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003031 if (length)
3032 {
3033 *length = 0;
3034 }
3035
Jamie Madill78f41802014-08-25 15:47:55 -04003036 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003037 {
Jamie Madill78f41802014-08-25 15:47:55 -04003038 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003039 }
3040
Geoff Langf41d0ee2016-10-07 13:04:23 -04003041 if (bufSize < 0)
3042 {
3043 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3044 return false;
3045 }
3046
Jamie Madilla502c742014-08-28 17:19:13 -04003047 gl::Program *programObject = context->getProgram(program);
3048 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003049
Jamie Madill78f41802014-08-25 15:47:55 -04003050 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003051 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3052 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003053 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003054 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003055 context->handleError(
3056 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003057 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003058 }
3059
Geoff Langf41d0ee2016-10-07 13:04:23 -04003060 if (length)
3061 {
3062 // Cast is safe because of comparison to bufSize.
3063 *length = static_cast<GLsizei>(requiredBytes);
3064 }
3065
Jamie Madill0063c512014-08-25 15:47:53 -04003066 return true;
3067}
3068
Geoff Langb1196682014-07-23 13:47:29 -04003069bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003070{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003071 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003072}
3073
Geoff Langb1196682014-07-23 13:47:29 -04003074bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003075{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003076 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3077}
3078
3079bool ValidateGetUniformfvRobustANGLE(Context *context,
3080 GLuint program,
3081 GLint location,
3082 GLsizei bufSize,
3083 GLsizei *length,
3084 GLfloat *params)
3085{
3086 if (!ValidateRobustEntryPoint(context, bufSize))
3087 {
3088 return false;
3089 }
3090
3091 // bufSize is validated in ValidateSizedGetUniform
3092 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3093}
3094
3095bool ValidateGetUniformivRobustANGLE(Context *context,
3096 GLuint program,
3097 GLint location,
3098 GLsizei bufSize,
3099 GLsizei *length,
3100 GLint *params)
3101{
3102 if (!ValidateRobustEntryPoint(context, bufSize))
3103 {
3104 return false;
3105 }
3106
3107 // bufSize is validated in ValidateSizedGetUniform
3108 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3109}
3110
3111bool ValidateGetUniformuivRobustANGLE(Context *context,
3112 GLuint program,
3113 GLint location,
3114 GLsizei bufSize,
3115 GLsizei *length,
3116 GLuint *params)
3117{
3118 if (!ValidateRobustEntryPoint(context, bufSize))
3119 {
3120 return false;
3121 }
3122
3123 if (context->getClientMajorVersion() < 3)
3124 {
3125 context->handleError(
3126 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3127 return false;
3128 }
3129
3130 // bufSize is validated in ValidateSizedGetUniform
3131 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003132}
3133
Austin Kinross08332632015-05-05 13:35:47 -07003134bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3135 const GLenum *attachments, bool defaultFramebuffer)
3136{
3137 if (numAttachments < 0)
3138 {
Jamie Madill437fa652016-05-03 15:13:24 -04003139 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003140 return false;
3141 }
3142
3143 for (GLsizei i = 0; i < numAttachments; ++i)
3144 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003145 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003146 {
3147 if (defaultFramebuffer)
3148 {
Jamie Madill437fa652016-05-03 15:13:24 -04003149 context->handleError(Error(
3150 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003151 return false;
3152 }
3153
3154 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3155 {
Jamie Madill437fa652016-05-03 15:13:24 -04003156 context->handleError(Error(GL_INVALID_OPERATION,
3157 "Requested color attachment is greater than the maximum "
3158 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003159 return false;
3160 }
3161 }
3162 else
3163 {
3164 switch (attachments[i])
3165 {
3166 case GL_DEPTH_ATTACHMENT:
3167 case GL_STENCIL_ATTACHMENT:
3168 case GL_DEPTH_STENCIL_ATTACHMENT:
3169 if (defaultFramebuffer)
3170 {
Jamie Madill437fa652016-05-03 15:13:24 -04003171 context->handleError(
3172 Error(GL_INVALID_ENUM,
3173 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003174 return false;
3175 }
3176 break;
3177 case GL_COLOR:
3178 case GL_DEPTH:
3179 case GL_STENCIL:
3180 if (!defaultFramebuffer)
3181 {
Jamie Madill437fa652016-05-03 15:13:24 -04003182 context->handleError(
3183 Error(GL_INVALID_ENUM,
3184 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003185 return false;
3186 }
3187 break;
3188 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003189 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003190 return false;
3191 }
3192 }
3193 }
3194
3195 return true;
3196}
3197
Austin Kinross6ee1e782015-05-29 17:05:37 -07003198bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3199{
3200 // Note that debug marker calls must not set error state
3201
3202 if (length < 0)
3203 {
3204 return false;
3205 }
3206
3207 if (marker == nullptr)
3208 {
3209 return false;
3210 }
3211
3212 return true;
3213}
3214
3215bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3216{
3217 // Note that debug marker calls must not set error state
3218
3219 if (length < 0)
3220 {
3221 return false;
3222 }
3223
3224 if (length > 0 && marker == nullptr)
3225 {
3226 return false;
3227 }
3228
3229 return true;
3230}
3231
Geoff Langdcab33b2015-07-21 13:03:16 -04003232bool ValidateEGLImageTargetTexture2DOES(Context *context,
3233 egl::Display *display,
3234 GLenum target,
3235 egl::Image *image)
3236{
Geoff Langa8406172015-07-21 16:53:39 -04003237 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3238 {
Jamie Madill437fa652016-05-03 15:13:24 -04003239 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003240 return false;
3241 }
3242
3243 switch (target)
3244 {
3245 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003246 if (!context->getExtensions().eglImage)
3247 {
3248 context->handleError(Error(
3249 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3250 }
3251 break;
3252
3253 case GL_TEXTURE_EXTERNAL_OES:
3254 if (!context->getExtensions().eglImageExternal)
3255 {
3256 context->handleError(Error(
3257 GL_INVALID_ENUM,
3258 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3259 }
Geoff Langa8406172015-07-21 16:53:39 -04003260 break;
3261
3262 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003263 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003264 return false;
3265 }
3266
3267 if (!display->isValidImage(image))
3268 {
Jamie Madill437fa652016-05-03 15:13:24 -04003269 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003270 return false;
3271 }
3272
3273 if (image->getSamples() > 0)
3274 {
Jamie Madill437fa652016-05-03 15:13:24 -04003275 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003276 "cannot create a 2D texture from a multisampled EGL image."));
3277 return false;
3278 }
3279
Jamie Madilla3944d42016-07-22 22:13:26 -04003280 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003281 if (!textureCaps.texturable)
3282 {
Jamie Madill437fa652016-05-03 15:13:24 -04003283 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003284 "EGL image internal format is not supported as a texture."));
3285 return false;
3286 }
3287
Geoff Langdcab33b2015-07-21 13:03:16 -04003288 return true;
3289}
3290
3291bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3292 egl::Display *display,
3293 GLenum target,
3294 egl::Image *image)
3295{
Geoff Langa8406172015-07-21 16:53:39 -04003296 if (!context->getExtensions().eglImage)
3297 {
Jamie Madill437fa652016-05-03 15:13:24 -04003298 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003299 return false;
3300 }
3301
3302 switch (target)
3303 {
3304 case GL_RENDERBUFFER:
3305 break;
3306
3307 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003308 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003309 return false;
3310 }
3311
3312 if (!display->isValidImage(image))
3313 {
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003315 return false;
3316 }
3317
Jamie Madilla3944d42016-07-22 22:13:26 -04003318 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003319 if (!textureCaps.renderable)
3320 {
Jamie Madill437fa652016-05-03 15:13:24 -04003321 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003322 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3323 return false;
3324 }
3325
Geoff Langdcab33b2015-07-21 13:03:16 -04003326 return true;
3327}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003328
3329bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3330{
Geoff Lang36167ab2015-12-07 10:27:14 -05003331 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003332 {
3333 // The default VAO should always exist
3334 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003335 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003336 return false;
3337 }
3338
3339 return true;
3340}
3341
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003342bool ValidateLinkProgram(Context *context, GLuint program)
3343{
3344 if (context->hasActiveTransformFeedback(program))
3345 {
3346 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003347 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003348 "Cannot link program while program is associated with an active "
3349 "transform feedback object."));
3350 return false;
3351 }
3352 return true;
3353}
3354
Geoff Langc5629752015-12-07 16:29:04 -05003355bool ValidateProgramBinaryBase(Context *context,
3356 GLuint program,
3357 GLenum binaryFormat,
3358 const void *binary,
3359 GLint length)
3360{
3361 Program *programObject = GetValidProgram(context, program);
3362 if (programObject == nullptr)
3363 {
3364 return false;
3365 }
3366
3367 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3368 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3369 programBinaryFormats.end())
3370 {
Jamie Madill437fa652016-05-03 15:13:24 -04003371 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003372 return false;
3373 }
3374
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003375 if (context->hasActiveTransformFeedback(program))
3376 {
3377 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003378 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003379 "Cannot change program binary while program is associated with "
3380 "an active transform feedback object."));
3381 return false;
3382 }
3383
Geoff Langc5629752015-12-07 16:29:04 -05003384 return true;
3385}
3386
3387bool ValidateGetProgramBinaryBase(Context *context,
3388 GLuint program,
3389 GLsizei bufSize,
3390 GLsizei *length,
3391 GLenum *binaryFormat,
3392 void *binary)
3393{
3394 Program *programObject = GetValidProgram(context, program);
3395 if (programObject == nullptr)
3396 {
3397 return false;
3398 }
3399
3400 if (!programObject->isLinked())
3401 {
Jamie Madill437fa652016-05-03 15:13:24 -04003402 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003403 return false;
3404 }
3405
3406 return true;
3407}
Jamie Madillc29968b2016-01-20 11:17:23 -05003408
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003409bool ValidateUseProgram(Context *context, GLuint program)
3410{
3411 if (program != 0)
3412 {
3413 Program *programObject = context->getProgram(program);
3414 if (!programObject)
3415 {
3416 // ES 3.1.0 section 7.3 page 72
3417 if (context->getShader(program))
3418 {
Jamie Madill437fa652016-05-03 15:13:24 -04003419 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003420 Error(GL_INVALID_OPERATION,
3421 "Attempted to use a single shader instead of a shader program."));
3422 return false;
3423 }
3424 else
3425 {
Jamie Madill437fa652016-05-03 15:13:24 -04003426 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003427 return false;
3428 }
3429 }
3430 if (!programObject->isLinked())
3431 {
Jamie Madill437fa652016-05-03 15:13:24 -04003432 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003433 return false;
3434 }
3435 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003436 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003437 {
3438 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003439 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003440 Error(GL_INVALID_OPERATION,
3441 "Cannot change active program while transform feedback is unpaused."));
3442 return false;
3443 }
3444
3445 return true;
3446}
3447
Jamie Madillc29968b2016-01-20 11:17:23 -05003448bool ValidateCopyTexImage2D(ValidationContext *context,
3449 GLenum target,
3450 GLint level,
3451 GLenum internalformat,
3452 GLint x,
3453 GLint y,
3454 GLsizei width,
3455 GLsizei height,
3456 GLint border)
3457{
Martin Radev1be913c2016-07-11 17:59:16 +03003458 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003459 {
3460 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3461 0, x, y, width, height, border);
3462 }
3463
Martin Radev1be913c2016-07-11 17:59:16 +03003464 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003465 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3466 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003467}
Jamie Madillc29968b2016-01-20 11:17:23 -05003468
3469bool ValidateFramebufferRenderbuffer(Context *context,
3470 GLenum target,
3471 GLenum attachment,
3472 GLenum renderbuffertarget,
3473 GLuint renderbuffer)
3474{
3475 if (!ValidFramebufferTarget(target) ||
3476 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3477 {
Jamie Madill437fa652016-05-03 15:13:24 -04003478 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003479 return false;
3480 }
3481
3482 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3483 renderbuffertarget, renderbuffer);
3484}
3485
3486bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3487{
3488 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3489 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3490 {
Jamie Madill437fa652016-05-03 15:13:24 -04003491 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003492 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3493 return false;
3494 }
3495
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003496 ASSERT(context->getGLState().getDrawFramebuffer());
3497 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003498 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3499
3500 // This should come first before the check for the default frame buffer
3501 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3502 // rather than INVALID_OPERATION
3503 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3504 {
3505 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3506
3507 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003508 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3509 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003510 {
3511 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003512 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3513 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3514 // 3.1 is still a bit ambiguous about the error, but future specs are
3515 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003516 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003517 return false;
3518 }
3519 else if (bufs[colorAttachment] >= maxColorAttachment)
3520 {
Jamie Madill437fa652016-05-03 15:13:24 -04003521 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003522 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003523 return false;
3524 }
3525 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3526 frameBufferId != 0)
3527 {
3528 // INVALID_OPERATION-GL is bound to buffer and ith argument
3529 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003530 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003531 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3532 return false;
3533 }
3534 }
3535
3536 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3537 // and n is not 1 or bufs is bound to value other than BACK and NONE
3538 if (frameBufferId == 0)
3539 {
3540 if (n != 1)
3541 {
Jamie Madill437fa652016-05-03 15:13:24 -04003542 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003543 "n must be 1 when GL is bound to the default framebuffer"));
3544 return false;
3545 }
3546
3547 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3548 {
Jamie Madill437fa652016-05-03 15:13:24 -04003549 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003550 GL_INVALID_OPERATION,
3551 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3552 return false;
3553 }
3554 }
3555
3556 return true;
3557}
3558
3559bool ValidateCopyTexSubImage2D(Context *context,
3560 GLenum target,
3561 GLint level,
3562 GLint xoffset,
3563 GLint yoffset,
3564 GLint x,
3565 GLint y,
3566 GLsizei width,
3567 GLsizei height)
3568{
Martin Radev1be913c2016-07-11 17:59:16 +03003569 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003570 {
3571 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3572 yoffset, x, y, width, height, 0);
3573 }
3574
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003575 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3576 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003577}
3578
Olli Etuaho4f667482016-03-30 15:56:35 +03003579bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3580{
3581 if (!ValidBufferTarget(context, target))
3582 {
Jamie Madill437fa652016-05-03 15:13:24 -04003583 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003584 return false;
3585 }
3586
3587 if (pname != GL_BUFFER_MAP_POINTER)
3588 {
Jamie Madill437fa652016-05-03 15:13:24 -04003589 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 return false;
3591 }
3592
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003593 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003594
3595 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3596 // target bound to zero generate an INVALID_OPERATION error."
3597 // GLES 3.1 section 6.6 explicitly specifies this error.
3598 if (!buffer)
3599 {
Jamie Madill437fa652016-05-03 15:13:24 -04003600 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003601 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3602 return false;
3603 }
3604
3605 return true;
3606}
3607
3608bool ValidateUnmapBufferBase(Context *context, GLenum target)
3609{
3610 if (!ValidBufferTarget(context, target))
3611 {
Jamie Madill437fa652016-05-03 15:13:24 -04003612 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
3615
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003616 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003617
3618 if (buffer == nullptr || !buffer->isMapped())
3619 {
Jamie Madill437fa652016-05-03 15:13:24 -04003620 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 return false;
3622 }
3623
3624 return true;
3625}
3626
3627bool ValidateMapBufferRangeBase(Context *context,
3628 GLenum target,
3629 GLintptr offset,
3630 GLsizeiptr length,
3631 GLbitfield access)
3632{
3633 if (!ValidBufferTarget(context, target))
3634 {
Jamie Madill437fa652016-05-03 15:13:24 -04003635 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 return false;
3637 }
3638
3639 if (offset < 0 || length < 0)
3640 {
Jamie Madill437fa652016-05-03 15:13:24 -04003641 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003642 return false;
3643 }
3644
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003645 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003646
3647 if (!buffer)
3648 {
Jamie Madill437fa652016-05-03 15:13:24 -04003649 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003650 return false;
3651 }
3652
3653 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003654 CheckedNumeric<size_t> checkedOffset(offset);
3655 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003656
Jamie Madille2e406c2016-06-02 13:04:10 -04003657 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 {
Jamie Madill437fa652016-05-03 15:13:24 -04003659 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003660 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3661 return false;
3662 }
3663
3664 // Check for invalid bits in the mask
3665 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3666 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3667 GL_MAP_UNSYNCHRONIZED_BIT;
3668
3669 if (access & ~(allAccessBits))
3670 {
Jamie Madill437fa652016-05-03 15:13:24 -04003671 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003672 return false;
3673 }
3674
3675 if (length == 0)
3676 {
Jamie Madill437fa652016-05-03 15:13:24 -04003677 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 return false;
3679 }
3680
3681 if (buffer->isMapped())
3682 {
Jamie Madill437fa652016-05-03 15:13:24 -04003683 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 // Check for invalid bit combinations
3688 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3689 {
Jamie Madill437fa652016-05-03 15:13:24 -04003690 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003691 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3692 return false;
3693 }
3694
3695 GLbitfield writeOnlyBits =
3696 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3697
3698 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3699 {
Jamie Madill437fa652016-05-03 15:13:24 -04003700 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003701 "Invalid access bits when mapping buffer for reading: 0x%X.",
3702 access));
3703 return false;
3704 }
3705
3706 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3707 {
Jamie Madill437fa652016-05-03 15:13:24 -04003708 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003709 GL_INVALID_OPERATION,
3710 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3711 return false;
3712 }
3713 return true;
3714}
3715
3716bool ValidateFlushMappedBufferRangeBase(Context *context,
3717 GLenum target,
3718 GLintptr offset,
3719 GLsizeiptr length)
3720{
3721 if (offset < 0 || length < 0)
3722 {
Jamie Madill437fa652016-05-03 15:13:24 -04003723 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003724 return false;
3725 }
3726
3727 if (!ValidBufferTarget(context, target))
3728 {
Jamie Madill437fa652016-05-03 15:13:24 -04003729 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003730 return false;
3731 }
3732
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003733 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003734
3735 if (buffer == nullptr)
3736 {
Jamie Madill437fa652016-05-03 15:13:24 -04003737 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003738 return false;
3739 }
3740
3741 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3742 {
Jamie Madill437fa652016-05-03 15:13:24 -04003743 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003744 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3745 return false;
3746 }
3747
3748 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003749 CheckedNumeric<size_t> checkedOffset(offset);
3750 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003751
Jamie Madille2e406c2016-06-02 13:04:10 -04003752 if (!checkedSize.IsValid() ||
3753 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003754 {
Jamie Madill437fa652016-05-03 15:13:24 -04003755 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003756 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3757 return false;
3758 }
3759
3760 return true;
3761}
3762
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003763bool ValidateGenerateMipmap(Context *context, GLenum target)
3764{
3765 if (!ValidTextureTarget(context, target))
3766 {
3767 context->handleError(Error(GL_INVALID_ENUM));
3768 return false;
3769 }
3770
3771 Texture *texture = context->getTargetTexture(target);
3772
3773 if (texture == nullptr)
3774 {
3775 context->handleError(Error(GL_INVALID_OPERATION));
3776 return false;
3777 }
3778
3779 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3780
3781 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3782 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3783 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3784 {
3785 context->handleError(Error(GL_INVALID_OPERATION));
3786 return false;
3787 }
3788
Jamie Madilla3944d42016-07-22 22:13:26 -04003789 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3790 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3791 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003792
3793 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3794 // unsized formats or that are color renderable and filterable. Since we do not track if
3795 // the texture was created with sized or unsized format (only sized formats are stored),
3796 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3797 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3798 // textures since they're the only texture format that can be created with unsized formats
3799 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3800 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003801 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3802 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003803 {
3804 context->handleError(Error(GL_INVALID_OPERATION));
3805 return false;
3806 }
3807
3808 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003809 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003810 {
3811 context->handleError(Error(GL_INVALID_OPERATION));
3812 return false;
3813 }
3814
3815 // Non-power of 2 ES2 check
3816 if (!context->getExtensions().textureNPOT &&
3817 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3818 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3819 {
Martin Radev1be913c2016-07-11 17:59:16 +03003820 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003821 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3822 context->handleError(Error(GL_INVALID_OPERATION));
3823 return false;
3824 }
3825
3826 // Cube completeness check
3827 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3828 {
3829 context->handleError(Error(GL_INVALID_OPERATION));
3830 return false;
3831 }
3832
3833 return true;
3834}
3835
Olli Etuaho41997e72016-03-10 13:38:39 +02003836bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3837{
3838 return ValidateGenOrDelete(context, n);
3839}
3840
3841bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3842{
3843 return ValidateGenOrDelete(context, n);
3844}
3845
3846bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3847{
3848 return ValidateGenOrDelete(context, n);
3849}
3850
3851bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3852{
3853 return ValidateGenOrDelete(context, n);
3854}
3855
3856bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3857{
3858 return ValidateGenOrDelete(context, n);
3859}
3860
3861bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3862{
3863 return ValidateGenOrDelete(context, n);
3864}
3865
3866bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3867{
3868 return ValidateGenOrDelete(context, n);
3869}
3870
3871bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3872{
3873 return ValidateGenOrDelete(context, n);
3874}
3875
3876bool ValidateGenOrDelete(Context *context, GLint n)
3877{
3878 if (n < 0)
3879 {
Jamie Madill437fa652016-05-03 15:13:24 -04003880 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003881 return false;
3882 }
3883 return true;
3884}
3885
Geoff Langf41a7152016-09-19 15:11:17 -04003886bool ValidateEnable(Context *context, GLenum cap)
3887{
3888 if (!ValidCap(context, cap, false))
3889 {
3890 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3891 return false;
3892 }
3893
3894 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3895 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3896 {
3897 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3898 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3899
3900 // We also output an error message to the debugger window if tracing is active, so that
3901 // developers can see the error message.
3902 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003903 return false;
3904 }
3905
3906 return true;
3907}
3908
3909bool ValidateDisable(Context *context, GLenum cap)
3910{
3911 if (!ValidCap(context, cap, false))
3912 {
3913 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3914 return false;
3915 }
3916
3917 return true;
3918}
3919
3920bool ValidateIsEnabled(Context *context, GLenum cap)
3921{
3922 if (!ValidCap(context, cap, true))
3923 {
3924 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3925 return false;
3926 }
3927
3928 return true;
3929}
3930
Geoff Langff5b2d52016-09-07 11:32:23 -04003931bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3932{
3933 if (!context->getExtensions().robustClientMemory)
3934 {
3935 context->handleError(
3936 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3937 return false;
3938 }
3939
3940 if (bufSize < 0)
3941 {
3942 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3943 return false;
3944 }
3945
3946 return true;
3947}
3948
3949bool 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